- Use EJB timers: Due to the nature of the tasks (e.g. interdependencies) this mechanism is not suitable - it's simply just not sophisticated enough.
- Use the Quartz functionality provided along with the JBoss distribution: While this may do exactly what we need, it wouldn't be portable to app servers from other vendors.
- "Another way to use Quartz in JBoss"
- "JBoss Quartz tutorial"
- "Scheduling a job using Jboss-5.1.0.GA and Quartz"
We use provided scope here since we won't be including Quartz in our project's deliverables; instead we put such dependencies on our server explicitly. Either approach would work, though.org.quartz-scheduler quartz-jboss 2.0.2 provided
1) Clean up your installation.
So, the first job at hand is to remove the Quartz artifacts from our JBoss installation. I guess it makes sense to prevent different versions from showing up in your classpath. The files to be removed are:
- ${jboss.home.dir}/common/lib/quartz.jar
- ${jboss.home.dir}/server/[SERVER_NAME]/deploy/quartz-ra.rar (in EAP this is an exploded RAR, so remove the directory)
2) Add the required Quartz libraries to you server.
The following file should be in place after this step:
- ${jboss.home.dir}/server/[SERVER_NAME]/lib/quartz-all-2.0.2.jar
Note that this file is not downloaded if you include the dependencies through Maven as indicated above, you have to download the full distribution to get it.
3) Add an MBean to the JBoss configuration.
The following is a simple example of a Quartz MBean configuration:
If you use this, no extra DataSource needs to be configured and Quartz keeps its jobs in memory. For more specifics on the configuration possibilities (there are a lot!), see http://www.quartz-scheduler.org/docs/configuration/.Quartz org.quartz.scheduler.instanceName = DefaultQuartzScheduler org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool org.quartz.threadPool.threadCount = 5 org.quartz.threadPool.threadPriority = 4 org.quartz.jobStore.class = org.quartz.simpl.RAMJobStore
Put the XML above in a x-service.xml file in your server's deploy dir, like e.g.:
- ${jboss.home.dir}/server/[SERVER_NAME]/deploy/quartz-service.xml
Obviously it now is possible to use Quartz from code inside deployed applications. Just retrieve the scheduler from JNDI like so:
InitialContext ctx = new InitialContext(); Scheduler scheduler = (Scheduler) ctx.lookup("Quartz");But for our purpose this just isn't good enough, we want to be able to schedule tasks from configuration files. To accomplish that, we need to perform a number of steps:
a) Enable the Quartz plugin that reads jobs and triggers from an indicated XML file. This is done by adding the following properties to the configuration shown in step 3):
org.quartz.plugin.jobInitializer.class = org.quartz.plugins.xml.XMLSchedulingDataProcessorPlugin org.quartz.plugin.jobInitializer.fileNames = ${jboss.server.home.dir}/conf/quartz-jobs.xml org.quartz.plugin.jobInitializer.scanInterval = 120For details on this plugin see http://www.quartz-scheduler.org/api/2.0.0/org/quartz/plugins/xml/XMLSchedulingDataProcessorPlugin.html.
b) Create a class that implements the org.quartz.Job interface for each such a task. This interface exposes exactly one method, void execute(JobExecutionContext ctx), which is called when the job is triggered.
c) Provide the quartz-jobs.xml file that is indicated in the extra configuration in step a) (the file name and path can be adjusted to your liking) with the appropriate timing to start your jobs. For our tasks we use Cron-like jobs, with the Quartz CronTrigger (see http://www.quartz-scheduler.org/api/2.0.0/org/quartz/CronTrigger.html). An example configuration is:
In this example the task executed by the com.acme.quartz.TestJob class is triggered at 3:00 AM on weekdays.* * true false TestJob com.acme.quartz.TestJob TestCronTrigger TestJob 0 0 3 ? * MON-FRI
One last CAVEAT: On Windows, the ${jboss.server.home.dir} expression resolves to a String that contains backward slashes ('\') instead of forward slashes as path delimiter. The way the Quartz extension for JBoss reads in the properties is not able to cope with that, so you may need to provide a full path explicitly for any file names.