By default, quartz does not recognize spring beans configured in applicationContext.xml
or with @Bean
annotation. If you try to @Autowired
these beans in Quartz Job
or QuartzJobBean
, you will get NullPointerException
.
Inject Spring context to QuartzJobBean
Solution is to inject Spring’s ApplicationContext
instance to org.quartz.SchedulerContext
which is available using org.quartz.JobExecutionContext
parameter to executeInternal()
method.
Inject applicationContext to SchedulerContext
This is typical,
SchedulerFactoryBean
bean entry. UsesetApplicationContextSchedulerContextKey()
method. This method set the key of anApplicationContext
reference to expose in theSchedulerContext
.@Bean public SchedulerFactoryBean schedulerFactoryBean() throws IOException, SchedulerException { SchedulerFactoryBean scheduler = new SchedulerFactoryBean(); scheduler.setTriggers(jobOneTrigger(), jobTwoTrigger()); scheduler.setQuartzProperties(quartzProperties()); scheduler.setJobDetails(jobOneDetail(), jobTwoDetail()); scheduler.setApplicationContextSchedulerContextKey("applicationContext"); return scheduler; }
Access inject beans in Quartz QuartzJobBean
Now, all you need to do is – get
applicationContext
reference and start fetching beans as per your need.import org.quartz.JobExecutionContext; import org.quartz.JobExecutionException; import org.springframework.batch.core.Job; import org.springframework.batch.core.JobParameters; import org.springframework.batch.core.JobParametersBuilder; import org.springframework.batch.core.configuration.JobLocator; import org.springframework.batch.core.launch.JobLauncher; import org.springframework.context.ApplicationContext; import org.springframework.scheduling.quartz.QuartzJobBean; public class CustomQuartzJob extends QuartzJobBean { private String jobName; private JobLauncher jobLauncher; private JobLocator jobLocator; public String getJobName() { return jobName; } public void setJobName(String jobName) { this.jobName = jobName; } @Override protected void executeInternal(JobExecutionContext context) throws JobExecutionException { try { ApplicationContext applicationContext = (ApplicationContext) context.getScheduler().getContext().get("applicationContext"); jobLocator = (JobLocator) applicationContext.getBean(JobLocator.class); jobLauncher = (JobLauncher) applicationContext.getBean(JobLauncher.class); Job job = jobLocator.getJob(jobName); JobParameters params = new JobParametersBuilder() .addString("JobID", String.valueOf(System.currentTimeMillis())) .toJobParameters(); jobLauncher.run(job, params); } catch (Exception e) { e.printStackTrace(); } } }
Now when you will run quartz job, you will get the jobLocator
and jobLauncher
instances in executeInternal()
method.
Drop me your questions in comments section.
Happy Learning !!