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)

Software Developer (Freelancer / Contractor) in Australia.

I have worked at places such as Google, Cochlear, Assembly Payments, News Corp, Fox Sports, NineMSN, FetchTV, Coles, Woolworths, Trust Bank, and Westpac, among others. If you're looking for help developing an iOS app, drop me a line!

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



 Subscribe via RSS