What is Quartz?
From their site:
How Do I Use Quartz?
"Quartz is a full-featured, open source job scheduling system that can be integrated with, or used along side virtually any J2EE or J2SE application"
Quartz is simple to use. To get started, download the distribution from their site, stick it in your classpath, and you are ready to go. First things first - you need to get your properties file set up. A simple configuration need only include this (or less if you want to fall back to defaults):
#===============================================================
# Configure Main Scheduler Properties
#===============================================================
org.quartz.scheduler.instanceName = QuartzScheduler
org.quartz.scheduler.instanceId = AUTO
#===============================================================
# Configure ThreadPool
#===============================================================
org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool
org.quartz.threadPool.threadCount = 5
org.quartz.threadPool.threadPriority = 5
#===============================================================
# Configure JobStore
#===============================================================
org.quartz.jobStore.misfireThreshold = 60000
org.quartz.jobStore.class = org.quartz.simpl.RAMJobStore
Once you have this going, you need to setup your jobs file. Most of the examples that came with Quartz show how to declare jobs in Java code. This is fine and all, but what if you don't want to have to recompile to change a quick setting? No good. I want to use XML. If you don't agree, feel free to follow one of the many examples they provide. To use XML, there are a couple things to keep in mind. First off - Quartz doesn't want to read these jobs from XML by default - you have to tell it to. In order to do so, you just need to add the following to quartz.properties:
org.quartz.plugin.jobInitializer.class = org.quartz.plugins.xml.JobInitializationPlugin
org.quartz.plugin.jobInitializer.fileName = my-jobs.xml
org.quartz.plugin.jobInitializer.overWriteExistingJobs = false
org.quartz.plugin.jobInitializer.failOnFileNotFound = true
Then just create a file my-jobs.xml:
<?xml version="1.0" encoding="UTF-8"?>
<quartz xmlns="http://www.opensymphony.com/quartz/JobSchedulingData"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
overwrite-existing-jobs="true">
<job>
<job-detail>
<name>AwesomeProcessor</name>
<group>awesome-group</group>
<description>Run the awesome job</description>
<job-class>
com.sportsvite.AwesomeProcessor
</job-class>
<job-data-map allows-transient-data="false">
<entry>
<key>superbad</key>
<value>true</value>
</entry>
</job-data-map>
</job-detail>
<trigger>
<cron>
<name>awesomeTrigger</name>
<group>awesome-trigger-group</group>
<job-name>awesomeProcessor</job-name>
<job-group>awesome-group</job-group>
<!-- trigger every 30 min -->
<cron-expression>0 0/30 * * * ?</cron-expression>
</cron>
</trigger>
</job>
</quartz>
Pretty simple, right? That's all you have to do on the configuration side.
NOTE: When you deploy the code, make sure that these two files end up in WEB-INF/classes so they are picked up in the classpath.
Now you need to kick off the Scheduler somehow. Most of the exercises show you how to do it in the code, but we don't want to rely on that, right? If you are running in a servlet container, they give you a simple servlet, the QuartzInitializerServlet. It is included in the jar file, and all you have to do is add it to the web.xml:
<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>
</servlet>
So we have told the Quartz scheduler to kick off a job called AwesomeProcessor, so we need to code the class. This is simple - you just need a class that implements the Quartz interface Job, and has the following method:
public void execute( JobExecutionContext ctxt )
{
String s = (String) ctxt.getString( "superbad" );
doFoo( s );
}
Note the use of the JobExecutionContext - you can use that to pass a bunch of arguments in a Map-like structure. It corresponds to the job-data element in the my-job.xml file.
Now when you fire up your server, the Quartz scheduler will activate and you'll see a message like this in standard out:
18:27:45,722 INFO [JobSchedulingDataProcessor] Scheduling 1 parsed job.
18:27:45,723 INFO [JobSchedulingDataProcessor] Adding job: awesome-group.AwesomeProcessor
18:27:45,735 INFO [JobSchedulingDataProcessor] 1 scheduled job.
18:27:45,735 INFO [QuartzScheduler] Scheduler QuartzScheduler_$_NON_CLUSTERED started.
18:27:45,736 INFO [Engine] StandardContext[]QuartzInitializer: Scheduler has been started...
18:27:45,736 INFO [Engine] StandardContext[]QuartzInitializer: Storing the Quartz Scheduler Factory in the servlet context at key: org.quartz.impl.StdSchedulerFactory.KEY
That's it! It's going to work now. The best thing about Quartz is that if you have bad XML or some other issue, it gives you a meaningful error message that you can easily remedy. Not all open source products can say the same.
Kudos to Quartz. It made my programming day pretty pleasant. Hope this helps others get up to speed. For a bunch of examples and other helpful information, check out the Quartz Wiki.
