Lately i've needed to run a background task every 10 seconds in a Java web-app (servlet) and found Quartz Scheduler to be great. It's just that their documentation doesn't really cover servlets much. So here we are: I'm using Struts2, Spring, and Hibernate, but most of this will apply regardless of framework you choose. Firstly, download and unzip Quartz and copy the quartz-all-*.jar to your WebContent\WEB-INF\lib folder. Then copy all the jar's from the unzipped quartz lib folder in as well. Edit your web.xml and add the following inside the web-app section:
<listener>
  <listener-class>org.quartz.ee.servlet.QuartzInitializerListener</listener-class>
</listener>
Next create a \src\quartz.properties with contents like the below:
# Generic configuration - probably not needed, most of this is just the defaults
org.quartz.scheduler.instanceName = MyScheduler
org.quartz.scheduler.instanceId = 1
org.quartz.scheduler.rmi.export = false
org.quartz.scheduler.rmi.proxy = false
org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool
org.quartz.threadPool.threadCount = 10
org.quartz.jobStore.class = org.quartz.simpl.RAMJobStore

# Configure it to look in the quartz.xml for the job schedules
org.quartz.plugin.jobInitializer.class = org.quartz.plugins.xml.XMLSchedulingDataProcessorPlugin
org.quartz.plugin.jobInitializer.fileNames = quartz.xml
org.quartz.plugin.jobInitializer.failOnFileNotFound = true
org.quartz.plugin.jobInitializer.scanInterval = 120
Then create a \src\quartz.xml similarly to below. Of course your xml will be different, but what i've got here is a single job that repeats every 10 seconds forever, the class being 'background.jobs.MyJob':
<?xml version="1.0" encoding="UTF-8"?>
<job-scheduling-data
        xmlns="http://www.quartz-scheduler.org/xml/JobSchedulingData"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://www.quartz-scheduler.org/xml/JobSchedulingData http://www.quartz-scheduler.org/xml/job_scheduling_data_1_8.xsd"
        version="1.8">

        <!--
                See: http://www.quartz-scheduler.org/docs/cookbook/JobInitPlugin.html
        -->

        <pre-processing-commands>
                <delete-jobs-in-group>*</delete-jobs-in-group>  <!-- clear all jobs in scheduler -->
                <delete-triggers-in-group>*</delete-triggers-in-group> <!-- clear all triggers in scheduler -->
        </pre-processing-commands>

        <processing-directives>
                <!--
                        if there are any jobs/trigger in scheduler of same name (as in this
                        file), overwrite them
                -->
                <overwrite-existing-data>true</overwrite-existing-data>
                <!--
                        if there are any jobs/trigger in scheduler of same name (as in this
                        file), and over-write is false, ignore them rather then generating an
                        error
                -->
                <ignore-duplicates>false</ignore-duplicates>
        </processing-directives>

        <!-- Ok this is where all the jobs are created: -->

        <schedule>
                <job>
                        <name>MyJob</name>
                        <job-class>background.jobs.MyJob</job-class>
                </job>
                <trigger>
                        <simple>
                                <name>TenSecondIntervals</name>
                                <job-name>MyJob</job-name>
                                <repeat-count>-1</repeat-count> <!-- repeat forever  -->
                                <repeat-interval>10000</repeat-interval>  <!--  every 10 seconds -->
                        </simple>
                </trigger>

        </schedule>
</job-scheduling-data>
Finally, you want to create the actual job class with the code to be called periodically. Here's MyJob.java below. You'll notice that i'm implementing StatefulJob instead of plain Job - this is so that if the job is still running when it is due to start again, Quartz won't start another instance of it:
package background.jobs;

import org.quartz.*;
import org.slf4j.*;

public class MyJob implements StatefulJob {

  @Override
  public void execute(JobExecutionContext context) throws JobExecutionException {
    try {

      // Do all my stuff here
      

    } catch (Exception ex) {
      LoggerFactory.getLogger(getClass()).error(ex.getMessage());
    }
  }
}
Good luck!

Thanks for reading! And if you want to get in touch, I'd love to hear from you: chris.hulbert at gmail.

Chris Hulbert

(Comp Sci, Hons - UTS)

iOS Developer in Sydney.

I have worked at places such as Google, Cochlear, News Corp, Fox Sports, NineMSN, FetchTV, Woolworths, and Westpac, among others. If you're looking for a good iOS developer, drop me a line!

Get in touch:
[email protected]
github.com/chrishulbert
linkedin
my resume



 Subscribe via RSS