Tuesday, July 09, 2013

Configuring Quartz 2 with Spring in clustered mode


Aligning the stars to configure Quartz 2.1.7 to work with Spring 3.1.3 in a cluster was surprisingly complicated. The main idea is to run jobs to fire only once per cluster, not once per server, while still providing beans from the Spring managed context and using the latest version of Quartz. The documentation consists essentially of a number of blog posts and stackoverflow answers. So here is one final and (hopefully) more comprehensive summary of the process.

For the TL;DR version, just see the full github gist.

In Quartz.properties we'll want to set useProperties=true so that data persisted to the DB is in String form instead of Serialized Java objects. But unfortunately the Spring 3.1.x CronTriggerFactoryBean sets a jobDetails property as a Java object, so Quartz will complain that the data is not a String. We'll need to create our own PersistableCronTriggerFactoryBean to get around this issue (similar to this blog post and forum discussion).

Additionally, in our Spring config the SchedulerFactoryBean will need to set both the triggers and the jobDetails objects. We also setup the scheduler to use Spring's dataSource and transactionManager. And notice that durability=true must be set on each JobDetailFactoryBean.

By default you cannot use Autowired capabilities in the Quartz Jobs, but this can be easily setup with a AutowiringSpringBeanJobFactory.

You'll also notice that we cannot use MethodInvokingJobDetailFactoryBean because it is not serializable, so we need to create our own Job class that extends QuartzJobBean. If your services are secured by Acegi or Spring Security, you will also need to register an authenticated quartzUser object with the security context.

And finally, we'll want to test that the trigger's Cron expression actually fires when we want it to. Here is an example test case that pulls the cronExpression from configuration and tests that it fires correctly on 2 consecutive days:

Hopefully this helps others in configuring an enterprise-ready Quartz + Spring application to run jobs in a clustered server environment.

Cross-published on the Object Partners blog: https://objectpartners.com/2013/07/09/configuring-quartz-2-with-spring-in-clustered-mode/

No comments: