Wednesday, March 12, 2008

Spring + Quartz

I have started to use Quartz within Spring last night after thinking about why I cannot run away from using a scheduler and how I could avoid using one.... in the end, I ran out of options, so I started to design the job and stick out a few lines of configuration.

There were two interesting lessons that I have learnt.

1. The cron expression for the org.springframework.scheduling.quartz.CronTriggerBean is not a standard unix cron expression. It is only "cron-like" definition (as written in the javadoc for CronTrigger).

This one bites me a few hours. Reading the documentation at first glance gave me the impression that the expression used to setup the cron job is the standard unix crontab expression. Oh, how wrong I was!!! In the end, I was battling with a strange error message (a snapshot shown below):

Invocation of init method failed; nested exception is java.lang.NoSuchMethodError: org.quartz.SchedulerException: method (Ljava/lang/String;Ljava/lang/Throwable;)V not found
Caused by:
java.lang.NoSuchMethodError: org.quartz.SchedulerException: method (Ljava/lang/String;Ljava/lang/Throwable;)V not found
at org.springframework.scheduling.quartz.SchedulerFactoryBean.registerJobsAndTriggers(SchedulerFactoryBean.java:795)
at org.springframework.scheduling.quartz.SchedulerFactoryBean.afterPropertiesSet(SchedulerFactoryBean.java:599)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1118)

Of course, when you read this blog you already have the wisdom it is due to the cron expression. But that's hindsight. Looking at the error message gives you a few misleading indicators. It was actually saying something really different. The underlying class have a mismatch method signature or using one that does not exists. So, I try other Quartz library... 1.5.1, 1.5.2 or even 1.6.0 which ships with the Spring that I am using. Nothing works until I changed the cron expression to the one that follows EXACTLY as in the documentation, then my unit tests start to fire up again.

Actually, a hint that there might be something wrong with the crontrigger bean happens when I commented out the portion of loading of triggers to the SchedulerFactoryBean. The error message is no longer showing up, ... and of course, neither was the job firing up.... but it was hinting something to me...

This is when I started to go back to the javadoc for CronTrigger and discover to my horror that the cron expression IS NOT the standard cron expression. Perhaps, Spring could put a liner of warning to the documentation too (not just the javadoc). Not their fault, I should have better known this.

2. Strangely, Quartz 1.6.0 that ships with my Spring 2.0.8 did not work on runtime. It works on compile time.

Well.... there is a strange liner when the Spring's javadoc for SchedulerFactoryBean have this liner:

This version of Spring's SchedulerFactoryBean requires Quartz 1.5 or higher.

So, I resort to Quartz 1.5.2 and it works again.

So, just make sure that all these are out of the way and ... enjoy the fun of firing up your jobs.