Spring Download: using @Service in a Quartz job

In the application, since I converted it from the classic Spring webapp (deployed on a Tomcat system) to the Spring Boot application (V1.2.1), I ran into the problem that quartz-based scheduled tasks are not working anymore.

I plan these Quartz assignments as follows:

// 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 is a classic Spring service that retrieves data from Hibernate. As I said above, this worked fine until I switched to Spring Boot.

When I implemented this code with the classic Spring application, SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this); did the trick to take care of outsourcing the service.

What is needed to re-work in the Spring boot environment?

Edit:

In the end, I decided to abandon the use of Quartz in favor of Spring ThreadPoolTaskScheduler. The code has been greatly simplified and works as expected.

+8
java spring spring-boot hibernate quartz-scheduler
source share
2 answers

SpringBeanAutowiringSupport uses a web application context that is not available in your case. If you need spring-driven beans in quartz, you should use the quartz support provided by spring. This will give you full access to all managed beans. For more information, see the Quartz Section in spring docs at http://docs.spring.io/spring/docs/current/spring-framework-reference/html/scheduling.html . Also see the following example using quartz with spring beans. The example is based on your code. Thus, you can change the first code fragment (where the quartz is initialized) with the following spring alternatives.

Create factory job detail

 @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(); } } 

Create a factory trigger

 @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(); } } 

And finally, create a SchedulerFactory

 @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(); } } 
+11
source share

My answer is not entirely consistent with your question, but Spring will give you another option - to run the scheduler based on cron-expression on any service.

With Spring.Boot, you can configure the application to use the scheduler with simple placement

 @EnableScheduling public class Application{ .... 

After that, just post the following annotation in the public (!) @Service method

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

All Articles