Spring-enabled Quartz jobs: the right way!

So we’ve been using Spring and Quartz together at my company for a couple of years and I finally had one of those face-palm moments where I realized… we’d been doing it wrong. We needed to make Spring-managed beans accessible to our Quartz jobs that were being instantiated at run-time by the Quartz scheduler. Our solution was to create a “holder bean” that provided static access to our Spring-managed services. It always seemed wrong and I was sure Spring had to have a more elegant way of doing it, but couldn’t find it in specifically mentioned in their documentation about Quartz integration. Thanks Alex Marshall for this post which prompted me to read the JavaDocs of the SchedulerFactoryBean and figure out how to pass Spring beans to Jobs not with the JobDetail (which in our case is serialized to a database) but with the Scheduler context using SchedulerFactoryBean’s “schedulerContextAsMap” property. So with a quick addition to the SchedulerFactoryBean configuration in our Spring applicationContext file:

<bean id="sched"
  <property name="schedulerContextAsMap">
      <entry key="<springBeanName>" value-ref="<springBean>" />

we can now access this Spring bean from a Quart job instantiated by the Scheduler during runtime:

/* (non-Javadoc)
 * @see org.quartz.Job#execute(org.quartz.JobExecutionContext)
public void execute(JobExecutionContext context) throws JobExecutionException 
  try {
    SchedulerContext cxt = context.getScheduler.getContext();
    SpringBean bean = (ServiceBean) cxt.get("beanName");
    ...do stuff with Spring bean...
  } catch (SchedulerException e) {
   throw new JobExecutionException(e);

You can do this more holistically by adding the entire Spring ApplicationContext object to the Scheduler context using the SchedulerFactoryBean’s “setApplicationContextSchedulerContextKey” property. That’s a mouthful!