Software AG's Apache-licensed Quartz Job Scheduler can be used to run a wide range of tasks at predefined intervals. This tutorial shows how to use Quartz to schedule Apache CXF SOAP calls at recurring intervals, for example, to provide ongoing reports or to refresh cached data in a database with the latest information.
If you're unfamiliar with Quartz its tutorial does a good job of explaining its architecture. As illustrated in the sample, a schedule consists of a job (providing Java class and property settings for the task each time it is run) and one or more triggers (a scheduled time or sequence of times for the job to be activated.) Task-specific parameters called job data maps can be tied to both the job and the trigger, with values on the latter appended to (or overriding, if the same key name) those on the former. For example, if you have jobs which involve loading business data per ZIP code, you might wish to set up two jobs with different job data maps, assigning ZIPs 00000-49999 to one job and 50000-99999 to the other. Further, the job data maps attached to the triggers for those jobs could call for loading stock market data at one time of day and banking data at another, while still filtering by ZIP code as defined by the job data maps attached to the job.
Although Quartz can be used in many ways, for this example I'll be installing it as a Tomcat-hosted servlet bundled with the jobs it will be running. The time(s) a job is to run will be defined using cron expressions within an XML configuration file kept in the web application's classpath. Here, I'll be using Quartz to make recurring calls against the DoubleIt web service, which will need to be running prior to activating the Quartz scheduling. The tutorial source code can be obtained from GitHub by using the "Clone or Download" button on the project site.
Create the Java webapp to hold the scheduler and its associated jobs. We'll use the Maven Archetype Plugin for this. From a console window, enter this command:
mvn archetype:generate -DarchetypeArtifactId=maven-archetype-webapp and provide the configuration parameters it asks for. This tutorial uses the below values:
groupId: org.gmazza.blog-samples.quartz_scheduled_soap_calls artifactId: quartz_scheduled_soap_calls version: 1.0 package: myscheduler
Once done, create the folder structure under
src/main to hold the Java classes, in this case
java/myscheduler will do.
Update the MyScheduler pom file with needed dependencies. The default myscheduler/pom.xml created by the Archetype Plugin above will need the Quartz and CXF dependencies added. Replace that pom.xml with the one below. Important: For deployment, you will need to have a "myTomcat" server entry configured within Maven, or rename the server entry in the pom with the one you already have configured.
Note: If you're not using Tomcat but instead one of the specific application containers listed in the Maven Repository, you will also need to change the
quartz dependency to the container-specific version (i.e.,
quartz-jboss instead of
quartz). For non-Maven usage, the README file in the root of the standard Quartz download provides more information on the JARs needed.
Save the web service provider's WSDL locally. Save the DoubleIt.wsdl file into the
src/main/resources folder. This file is referenced in the Maven pom above for creating the necessary JAX-WS/JAXB artifacts.
Create the DoubleItJob class. This class is activated by Quartz each time a trigger defined in schedule.xml for this class is fired, and it reads in configuration information (here, the numbers to double) from the schedule.xml file. Real production use would more likely involve saving information to a database or report generation but for this tutorial we'll just have it output information to the console (normally viewable from Tomcat's
logs/catalina.out file). Place the below source file in src/java/myscheduler.
Create configuration files for the Quartz webapp. Below is a series of files needed in the Quartz WAR that will be hosted on Tomcat:
web.xml: Replace the web.xml in the webapp/WEB-INF folder with this one. It holds Quartz's servlet used for the scheduling of jobs and identifies its configuration file (quartz.properties).
quartz.properties: This file holds Quartz Scheduler-specific configuration information, including the name of the job definition file (schedule.xml). Place this file in the src/main/resources folder.
schedule.xml: This file holds the scheduling information (see the Quartz docs or XSD for more information.) Modify the cron expressions below to activate the job when desired (simple format here: "seconds minutes 24hour day month ?") and place it in the src/main/resources folder. Note this file can hold multiple jobs and multiple triggers attached to each job, with job data maps optional for both the job and its triggers.
log4j.properties: This file, which should be placed in the same resources folder as above, defines the Quartz output log information (which is different from the console output of the jobs, which as mentioned earlier will still be in Tomcat's logs/catalina.out file.) You'll rely on the output log to make sure Quartz has successfully loaded upon deployment. Make sure to modify the
log4j.appender.LOGFILE.File value within this properties file to indicate your desired folder location for the logging files.
Deploy the webapp on Tomcat to activate the scheduler. Providing Maven has been configured for Tomcat usage, running
mvn clean install tomcat7:deploy should install the Quartz webapp on Tomcat. After deploying, always check the Quartz log file as configured in log4j.properties above to make sure everything loaded properly so your batch jobs will later run at the times you specified. Here's the Quartz output from my log file showing a successful loading (and two subsequent execution of the job):
This job output results from Tomcat's logs/catalina.out is shown below. Since the job's job data map has a JNumberToDouble (value 25) defined it is available for both triggered executions of the job, along with a trigger-specific TNumberToDouble value (value 12 and -12) for each run. Using the same key name for both job and trigger can be used if it is desired to have values in the latter override those in the former instead of being appended as additional values.
The number 25 doubled is 50 The number 12 doubled is 24 The number 25 doubled is 50 The number 25 doubled is 50 The number 12 doubled is 24 The number -12 doubled is -24
As you add jobs and/or triggers to the schedule.xml file, make sure the
name element of every
trigger is unique--triggers may overwrite each other and/or fail to activate if you use duplicate names.
In addition to the times specified in schedule.xml for the SOAP calls to be made, with additional coding (perhaps a simple UI in the WAR), jobs can be manually triggered.
To make changes to the execution times without redeploying the WAR you can alter the classes/schedule.xml file within the expanded WAR file on Tomcat, and then either restart Tomcat or save a meaningless change to your expanded Quartz webapp's web.xml file (such as adding a space and then removing it.) As web.xml is normally Tomcat's watched resource, the servlet container will detect that it has changed and will reload the webapp with the updated schedule.xml as a consequence. However, you'll need to make sure the expanded war directory isn't overwritten by any zipped war archive (that would not have your modification) in the webapps folder -- after redeploying check the Quartz log file to make sure it has successfully loaded with your new configuration.