Inject Spring dependencies in Quartz Job

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.

  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;
    }
    
  2. 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 !!

Was this post helpful?

Join 8000+ Awesome Developers, Like YOU!

Leave a Comment

About HowToDoInJava

This blog provides tutorials and how-to guides on Java and related technologies.

It also shares the best practices, algorithms & solutions, and frequently asked interview questions.