By default, Quartz does not recognize Spring beans configured in applicationContext.xml
or with @Bean
annotation. If we try to @Autowired
these beans in Quartz Job
or QuartzJobBean
, we will get NullPointerException
.
1. Injecting Spring ApplicationContext to QuartzJobBean
The solution is to inject Spring’s ApplicationContext
instance to org.quartz.SchedulerContext
which is available using org.quartz.JobExecutionContext
parameter to executeInternal()
method.
1.1. Inject ApplicationContext to SchedulerContext
This is typical SchedulerFactoryBean
bean entry. Use setApplicationContextSchedulerContextKey()
method. This method set the key of an ApplicationContext
reference to expose in the SchedulerContext
.
@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;
}
1.2. Access Injected Beans in 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 run quartz job, you will get the jobLocator
and jobLauncher
instances in executeInternal()
method.
2. Conclusion
In this tutorial, we learned to inject the Spring context beans into QuartzJobBean instance so we can get or set the quartz properties in the runtime.
Drop me your questions in the comments section.
Happy Learning !!
Leave a Reply