2015-01-25 17 views
8

Bir uygulamada, onu klasik bir Spring webapp'dan (bir Tomcat sisteminde konuşlandırıldı) bir Spring Boot (V1.2.1) uygulamasına dönüştürdüğümden beri, Kuvars tabanlı planlanmış işler artık çalışmıyor.Spring Boot: Quartz iş uygulamasında @Service kullanma

böyle bu Kuvars işleri planlamak:

// My own Schedule object which holds data about what to schedule when 
Schedule schedule = scheduleService.get(id of the schedule); 

String scheduleId = schedule.getId(); 

JobKey jobKey = new JobKey(scheduleId); 
TriggerKey triggerKey = new TriggerKey(scheduleId); 

JobDataMap jobData = new JobDataMap(); 
jobData.put("scheduleId", scheduleId); 

JobBuilder jobBuilder = JobBuilder.newJob(ScheduledActionRunner.class) 
    .withIdentity(jobKey) 
    .withDescription(schedule.getName()) 
    .usingJobData(jobData); 

JobDetail job = jobBuilder.build(); 

TriggerBuilder triggerBuilder = TriggerBuilder.newTrigger() 
    .forJob(jobKey) 
    .withIdentity(triggerKey) 
    .withDescription(schedule.getName()); 

triggerBuilder = triggerBuilder.withSchedule(CronScheduleBuilder.cronSchedule(schedule.toCronExpression())); 

Trigger trigger = triggerBuilder.build(); 

org.quartz.Scheduler scheduler = schedulerFactoryBean.getScheduler(); 

scheduler.scheduleJob(job, trigger); 

ScheduledActionRunner:

@Component 
public class ScheduledActionRunner extends QuartzJobBean { 

    @Autowired 
    private ScheduleService scheduleService; 

    public ScheduledActionRunner() { 
    } 

    @Override 
    public void executeInternal(final JobExecutionContext context) throws JobExecutionException { 
     SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this); 
     final JobDataMap jobDataMap = context.getMergedJobDataMap(); 
     final String scheduleId = jobDataMap.getString("scheduleId"); 
     final Schedule schedule = scheduleService.get(scheduleId); 
     // here it goes BANG since scheduleService is null 
    } 
} 

ScheduleService hazırda veri getirir klasik Bahar hizmetidir. Yukarıda belirttiğim gibi, Spring Boot'a taşınana kadar bu işe yaradı.

Bu kodu klasik Yay uygulamasıyla uyguladığımda, SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this); hizmeti otomatik olarak halletmek için hile yaptı.

İlkbaharda önyükleme ortamında bu işi yeniden yapmak için ne gerekir?

Düzenleme: Bahar 'ThreadPoolTaskScheduler.The kodunun lehine Kuvars kullanarak uzaklaşmaya seçti sonunda

çok basitleştirilmiş ve beklendiği gibi çalışır.

+0

yorumun public (!) Yöntemine aşağıdaki şerhi Bundan sonra

@EnableScheduling public class Application{ .... 

yerleştirerek basit tarafından zamanlayıcı kullanmak üzere yapılandırabilirsiniz Spring.Boot sen kullanma Dewfy (yorum yapmak için yeterli reporuma sahip olmadığımdan): @Transactional ek açıklama ile yöntemi işaretlemem gerekiyordu, çünkü hazırda bekletme oturumu eklenemedi. – gooboo

cevap

11

SpringBeanAutowiringSupport, sizin durumunuzda bulunmayan web uygulama içeriğini kullanır. Eğer kuartzda yaylı bir baklaya ihtiyaç duyarsanız, ilkbaharda sağlanan kuvars desteğini kullanmalısınız. Bu, tüm yönetilen çekirdeklere tam erişim sağlayacaktır. Daha fazla bilgi için bahar belgelerinde http://docs.spring.io/spring/docs/current/spring-framework-reference/html/scheduling.html numaralı telefondan kuvars bölümüne bakın. Ayrıca, yay ile yönetilen fasulye içeren kullanım kuvveti örneğine bakınız. Örnek kodunuza dayanmaktadır. Böylece, ilk kod parçacığını (kuartz başlatma işleminin yapıldığı yer) follwoing yayı alternatifleriyle değiştirebilirsiniz.

oluştur

@Component 
public class ActionCronTriggerFactoryBean extends CronTriggerFactoryBean { 

    @Autowired 
    private ScheduledActionRunnerJobDetailFactory jobDetailFactory; 

    @Value("${cron.pattern}") 
    private String pattern; 

    @Override 
    public void afterPropertiesSet() throws ParseException { 
     setCronExpression(pattern); 
     setJobDetail(jobDetailFactory.getObject()); 
     super.afterPropertiesSet(); 
    } 

} 

tetik fabrikası iş detay fabrikası

@Component 
public class ScheduledActionRunnerJobDetailFactory extends JobDetailFactoryBean { 

    @Autowired 
    private ScheduleService scheduleService; 

    @Override 
    public void afterPropertiesSet() { 
     setJobClass(ScheduledActionRunner.class); 
     Map<String, Object> data = new HashMap<String, Object>(); 
     data.put("scheduleService", scheduleService); 
     setJobDataAsMap(data); 
     super.afterPropertiesSet(); 
    } 
} 

oluştur Ve nihayet sorgulamaya

@Component 
public class ActionSchedulerFactoryBean extends SchedulerFactoryBean { 

    @Autowired 
    private ScheduledActionRunnerJobDetailFactory jobDetailFactory; 

    @Autowired 
    private ActionCronTriggerFactoryBean triggerFactory; 

    @Override 
    public void afterPropertiesSet() throws Exception { 
     setJobDetails(jobDetailFactory.getObject()); 
     setTriggers(triggerFactory.getObject()); 
     super.afterPropertiesSet(); 
    } 

} 
+0

Cevabınız için teşekkür ederiz @Babl. Önerilen kodunuzu denemeden önce, tek ve son sorum şu: Uygulama, Spring Boot'ı kullanmak için değiştirmeden önce neden işe yaradı?Önceki Bahar Önyükleme zaten JavaConfig ve Spring 4.1 dayanıyordu ve zamanlama iyi çalıştı. – yglodt

+1

Daha önce bahsettiğim gibi, SpringBeanAutowiringSupport, fasulye bulmak ve onları nesnenize enjekte etmek için web uygulama bağlamını kullanır, ancak bahar önyükleme uygulaması tam olarak bir web uygulaması olmadığı için bağlam boştur. Bu nedenle, SpringBeanAutowiringSupport için bir günlükleri debug leve'de etkinleştirirseniz, hedef sınıfın bir Spring web uygulamasında oluşturulmadığını söyleyen bir devri mesajı görürsünüz. İlkbahar için debug leve'i açmanın herhangi bir yolu, bu konuyla ilgili birçok içsel bilgi verecektir;) – Babl

+0

Detaylı açıklama için teşekkürler! – yglodt

9

Benim cevabım değil tamamen eşleşir SchedulerFactory oluşturmak, ancak Bahar maruz Başka bir yetenek - herhangi bir hizmette cron-ifade tabanlı zamanlayıcıyı başlatmak için.

sadece gelen cevap @Service

@Service 
public class MyService{ 
... 
    @Scheduled(cron = "0 * * * * MON-FRI") 
    public void myScheduledMethod(){ 
    .... 
    } 
+2

Teşekkürler, bunun farkındayım ve statik olan Çizelgeler için zaten kullanıyorum. Yukarıda tarif ettiğim problem, kullanıcı tarafından ayarlanabilen Schedule'lerden geliyor. Bu yüzden, @Scheduled notu ile mümkün olmadığını bildiğim kadarıyla bunları çalışma zamanında eklemek/düzenlemek/kaldırmak zorundayım. – yglodt