Java, XML, and cron driven scheduling made easy.
Projects here and there often need some kind of mechanism to schedule jobs at odd hours, or intervals. Quartz is a robust, flexible tool you can use to accomplish simple to complex job scheduling. There are a number of ways to use/configure quartz, but I’ve grown accustomed to using it with an xml based configuration. There are a few things we need to set up unfortunately, so there is a certain amount of plumbing we need to work out, but once that infrastructure is set up, its much less work to set up additional jobs.
web.xml
Originally, I went on about writing a custom quartz servlet to initialize the engine, but theres an even easier way to set this up as Sibz has pointed out in a comment:
<servlet> <servlet-name> QuartzInitializer </servlet-name> <display-name> Quartz Initializer Servlet </display-name> <servlet-class> org.quartz.ee.servlet.QuartzInitializerServlet </servlet-class> <load-on-startup>1</load-on-startup> <init-param> <param-name>config-file</param-name> <param-value>/some/path/my_quartz.properties</param-value> </init-param> <init-param> <param-name>shutdown-on-unload</param-name> <param-value>true</param-value> </init-param> <init-param> <param-name>start-scheduler-on-load</param-name> <param-value>true</param-value> </init-param> </servlet>
This xml snippet was blatanlty hijacked from quartz’ documentation page. As you might have guessed, this xml configuration goes in your web.xml. No need to write your own initializer servlet, just plug and play.
We’ll need to add 2 property files. The one that fine tunes the engine in our example is quartz.properties..
quartz.properties
If you noticed in the web.xml (the init param named “config-file” is set to the path
org.quartz.plugin.jobInitializer.class=org.quartz.plugins.xml.JobInitializationPlugin org.quartz.plugin.jobInitializer.fileNames = quartz-config.xml org.quartz.plugin.jobInitializer.overWriteExistingJobs = true org.quartz.plugin.jobInitializer.failOnFileNotFound =true org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool org.quartz.threadPool.threadCount = 5 org.quartz.threadPool.threadPriority = 5
The first half of the settings is pretty straight forward, but the second half is all about tuning. Setting a class other than SimpleThreadPool means you’ve written your own implementation for quartz thread management. You probably really know what you’re doing and you can stop reading. Threadcount controls the number of quartz threads dedicated to the engine. One is plenty for a job that fires off once or a few times a day. If you plan on running thousands a day, with heavy loads you’ll want something like 50 threads and up towards about 100. Threadpriority 5 means normal priority, while priority 1 is highest priority. For the most part, 5 is plenty, if you have cpu intensive processing going on, you can tune this to make sure your jobs fire off when they’re supposed
The second file we need to set up is the xml that configures your quartz job…
quartz-config.xml
<quartz>
<job>
<job-detail>
<name>scheduler</name>
<group>schedulers</group>
<description>schedule a nightly job</description>
<job-class>com.examples.quartz.Scheduler</job-class>
<volatility>false</volatility>
<durability>false</durability>
<recover>false</recover>
<job-data-map>
<entry>
<key>username</key>
<value>someUser</value>
</entry>
<entry>
<key>password</key>
<value>somePassword</value>
</entry>
</job-data-map>
</job-detail>
<trigger>
<cron>
<name>scheduler-trigger</name>
<group>scheduler-triggers</group>
<job-name>scheduler</job-name>
<job-group>schedulers</job-group>
<cron-expression>0 0/5 * * * ?</cron-expression>
</cron>
</trigger>
</job>
</quartz>
This file is made up of two main sections. Job-Detail configures the job’s metadata, while trigger defines the configuration and cron expression that fires off the job. Stuff like the name, and mappings needed to configure the matching trigger, or the xml parser will complain. Parameters can be added in
Scheduler.java
Scheduler is the job implementing class that defines the unit of work preformed by the quartz job. JobExecutionContext contains all the job metadata defined in the configuring xml, and the data map is the object that contains all the name/value pairs listed in the xml we just wrote up. Here’s the full class:
package com.examples.quartz;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.quartz.Job;
import org.quartz.JobDataMap;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
public class Scheduler implements Job {
protected static final Log log = LogFactory.getLog(Scheduler.class);
public void execute(JobExecutionContext jobContext)
throws JobExecutionException {
log.info("entering the quartz config");
JobDataMap map = jobContext.getJobDetail().getJobDataMap();
String username = (String) map.get("username");
String password = (String) map.get("password");
log.info("mapped data: " + username + "/" + password);
}
}
.. And that’s all there is to setting up a quartz jobs. If we want to add additional quartz jobs, all we would need to do is add another job node in our
Related posts:
on February 5, 2010 at 6:36 am
Permalink
Dude. You guys so need Spring.
[Reply]
Ant Reply:
February 5th, 2010 at 10:14 am
Ah yea, spring’s definately sexy with its support for TimerTasks , and easier quartz configs. We’re using spring mvc in one of the newer projects, but it’s hard to justify a major refactor like that on the existing projects. Something I’ve been trying to get around to comparing is how ejb3 Timers stack up vs quartz. I like how you can set dedicated threads in quartz, but in ejb3 timers you give that up afaik and let the container handle it.
[Reply]
on February 5, 2010 at 9:11 am
Permalink
[...] introduction to Quartz Scheduled Jobs. Quartz is Java framework for sophisticated jobs [...]
on February 9, 2010 at 8:30 am
Permalink
Quartz has moved to http://www.quartz-scheduler.com. Not at Open Symphony anymore.
[Reply]
Ant Reply:
February 9th, 2010 at 8:43 am
You’re right – I’ll update. My bad!
[Reply]
on February 9, 2010 at 8:47 am
Permalink
Thanks! And thanks for the blog!
[Reply]
on February 11, 2010 at 4:33 pm
Permalink
I have used quartz recently in one of my projects that I was working on. And what I did was to use the org.quartz.ee.servlet.QuartzInitializerServlet that came by default with the quartz jar file instead of writing a custom initializer servlet and added that entry to the web.xml. As long as “quartz.properties is the classpath” it would get picked up. FYI
[Reply]
on February 11, 2010 at 5:02 pm
Permalink
Sibz – I didn’t know about that Quartz servlet, I’ve updated the article with the new info. Thanks for the tip!
[Reply]
on February 11, 2010 at 11:30 pm
Permalink
[...] Technobabble » Quartz Scheduled Jobs [...]