Scheduling a Quartz Job Declaratively

As discussed earlier, we would like to handle configuring our software declaratively rather than programmatically as much as possible. Looking back at Listing 3.6, if we needed to change the time or frequency at which the jobs started, we would have to modify the source and recompile. This is fine for small example applications, but with a system that is large and complex, this quickly becomes a problem. So if there's a way to schedule Quartz jobs declaratively and your requirements allow for it, you should choose that approach every time.

Before we can discuss how to schedule your jobs declaratively, we need to talk about the quartz.properties file. This properties file enables you to configure the runtime environment of Quartz and, more important, tell Quartz to get the job and trigger information from an external resource, such as an XML file.

Configuring the quartz.properties File

The quartz.properties file defines the runtime behavior of the Quartz application and contains many properties that can be set to control how Quartz behaves. Only the basics are covered within this chapter; we save the more advanced settings for later. We also do not go into detail about the valid values for each setting at this point.

Let's look at a bare-bones quartz.properties file and discuss some of the settings. Listing 3.7 shows a stripped-down version of the quartz.properties file.

Note

The Quartz framework sets defaults for almost all of these properties.

 

Listing 3.7. Basic Quartz Properties File

#===============================================================
#Configure Main Scheduler Properties
#===============================================================
org.quartz.scheduler.instanceName = QuartzScheduler
org.quartz.scheduler.instanceId = AUTO

#===============================================================
#Configure ThreadPool
#===============================================================
org.quartz.threadPool.threadCount = 5
org.quartz.threadPool.threadPriority = 5
org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool

#===============================================================
#Configure JobStore
#===============================================================
org.quartz.jobStore.class = org.quartz.simpl.RAMJobStore

#===============================================================
#Configure Plugins
#===============================================================
org.quartz.plugin.jobInitializer.class =
org.quartz.plugins.xml.JobInitializationPlugin

org.quartz.plugin.jobInitializer.overWriteExistingJobs = true
org.quartz.plugin.jobInitializer.failOnFileNotFound = true
org.quartz.plugin.jobInitializer.validating=false

In the quartz.properties file in Listing 3.7, the properties are logically separated into four sections. The properties don't have to be grouped or listed in any order. The lines with the # are comments.

Note

This discussion does not list every possible setting. Here we discuss only the basic settings that you need to be familiar or that are necessary to get the declarative example working. These properties are discussed throughout the book in the chapters that pertain to the relevant sections of the properties file.

 

Scheduler Properties

The first section contains two lines and sets the instanceName and instanceId for the Scheduler. The value for the property org.quartz.scheduler.instanceName can be any string that you like. It's used to distinguish a particular scheduler instance when multiple schedulers are being used. Multiple schedulers are normally used within a clustered environment. (Quartz clustering is discussed in Chapter 11, "Clustering Quartz.") For now, a string such as this one is fine:

org.quartz.scheduler.instanceName = QuartzScheduler

In fact, that is the default when none is provided in the properties file.

The second Scheduler property shown in Listing 3.7 is org.quartz.scheduler.instanceId. As with the instanceName property, the instanceId property can be any string value you want. The value should be unique across all Scheduler instances, especially within a cluster. You may use the value AUTO if you want the value to be generated for you. The generated value will be NON_CLUSTERED if this is running in a nonclustered Quartz environment. If you're using Quartz in a clustered environment, the value will be the hostname of the machine plus the current date and time. For most situations, setting the value to AUTO is fine.

Threadpool Properties

The next section sets the necessary values for the threads that run in the background and do the heavy lifting in Quartz. The tHReadCount property controls how many worker threads are created and available to process jobs. In principal, the more jobs that you have to process, the more worker threads you'll need. The number for the tHReadCount must be at least 1. Quartz imposes no maximum on the number of worker threads, but setting this value to greater than 100 on most machines becomes quite unwieldy, especially if your jobs have long-running logic in them. There is no default, so you must specify a value for this property.

The tHReadPriority property sets the priority that the worker threads run with. Threads with higher priorities are typically given preference over threads with a lower priority. The minimum value for the tHReadPriority is the constant java.lang.Thread.MAX_PRIORITY, which equates to 10. The minimum value is java.lang.Thread.MIN_PRIORITY, which equals 1. The typical value for this property is Thread.NORM_PRIORITY, which is 5. For most situations, you'll want to set this to the value of 5, which is the default if the property isn't specified.

The final threadpool setting is for the property org.quartz.threadPool.class. The value for this class should be a fully qualified name of the class that implements the org.quartz.spi.ThreadPool interface. The threadpool that ships with Quartz is org.quartz.simpl.SimpleThreadPool, and it should meet the needs of most users. This threadpool has simple behavior and is well tested. It provides a fixed-size pool of threads that survive the lifetime of the Scheduler. You can create your own threadpool class, if you want. For example, you might need to do this if you want a threadpool that grows and shrinks with demand. There is no default specified, so you must provide a value for this property.

Jobstore Settings

The properties within the JobStore section describe how job and trigger information is stored during the lifetime of the Scheduler instance. We haven't yet talked about the JobStore and its purpose; we save that for later because it's not necessary for the current example. For now, all you need to know is that we are storing Scheduler information in memory instead of a relational database.

Storing Scheduler information in memory is fast and the easiest to configure. When the Scheduler process is halted, however, all job and trigger state is lost. Job storage in memory is accomplished by setting the org.quartz.jobStore.class property to org.quartz.simpl.RAMJobStore, as we've done in Listing 3.7. If we don't want to lose our Scheduler state when the JVM is halted, we could use a relational database to store that information. This requires a different JobStore implementation that we discuss later. Chapters 5, "Cron Triggers and More," and 6, "JobStores and Persistence," cover the various types of JobStores and when you should use them.

Plug-In Settings

The final section in the simple quartz.properties file is the one that specifies any Quartz plug-ins that you want to configure. A plug-in is used by many other open source frameworks, such as Struts from Apache (see http://struts.apache.org).

The idea is to declaratively extend the framework by adding classes that implement the org.quartz.spi.SchedulerPlugin interface. The SchedulerPlugin interface has three methods that are called by the Scheduler.

Note

Plug-ins for Quartz are discussed in detail in Chapter 8, "Using Quartz Plug-Ins."

To declaratively configure the Scheduler information for our example, we will be using a plug-in called org.quartz.plugins.xml.JobInitializationPlugin that comes with Quartz.

By default, this plug-in searches for a file called quartz_jobs.xml in the classpath and loads job and trigger information from the XML file.

The next section discusses the quartz_jobs.xml file, which we informally refer to as the job definition file.

Note

By default, the JobInitializationPlugin looks for a file called quartz_jobs.xml on your classpath. You can override this and force it to look for and use a file with a different name. To do this, you must set the filename in the quartz.properties file that we discussed in the previous section. For now, we are going to just rely on the default filename quartz_jobs.xml and show you how to modify the quartz.properties file later in this chapter.

 

Using the quartz_jobs.xml File

Listing 3.8 shows the job-definition XML file for the Scan Directory example. It configures job and trigger information using a declarative approach exactly like the example from Listing 3.5.

Listing 3.8. The quartz_ jobs.xml file for the ScanDirectory Job





 
 
 ScanDirectory
 DEFAULT
 
 A job that scans a directory for files
 
 
 org.cavaness.quartzbook.chapter3.ScanDirectoryJob
 
 false
 false
 false
 
 
 SCAN_DIR
 c:quartz-bookinput
 
 
 

 
 
 scanTrigger
 DEFAULT
 ScanDirectory
 DEFAULT
 2005-06-10 6:10:00 PM
 
 -1
 10000
 
 

 

The element represents a job that you want to register with the Scheduler, just as we did earlier in the chapter with the scheduleJob() method. You can see the and elements, which we programmatically passed into the schedulerJob() method in Listings 3.5. This is essentially what is happening here, but in a declarative fashion. You can also see in Listing 3.8 that we set the SCAN_DIR property into the JobDataMap, as we also did in the Listing 3.5 example.

The element is also very intuitive: It simply sets up a SimpleTrigger with the same properties as before. So Listing 3.8 is just a different (arguably, better) way of doing what we did in Listing 3.5. You obviously can support multiple jobs as well. We did this in Listing 3.6 programmatically, and we can also support it declaratively. Listing 3.9 shows the comparable version of Listing 3.6.

Listing 3.9. You Can Specify Multiple Jobs in the quartz_jobs.xml File




 
 
 ScanDirectory1
 DEFAULT
 
 A job that scans a directory for files
 
 
 org.cavaness.quartzbook.chapter3.ScanDirectoryJob
 
 false
 false
 false

 
 
 SCAN_DIR
 c:quartz-bookinput1
 
 
 

 
 
 scanTrigger1
 DEFAULT
 ScanDirectory1
 DEFAULT
 2005-07-19 8:31:00 PM
 
 -1
 10000
 
 



 
 ScanDirectory2
 DEFAULT
 
 A job that scans a directory for files
 
 
 org.cavaness.quartzbook.chapter3.ScanDirectoryJob
 
 false
 false
 false

 
 
 SCAN_DIR
 c:quartz-bookinput2
 
 
 

 
 
 scanTrigger2
 DEFAULT
 ScanDirectory2
 DEFAULT
 2005-06-10 6:10:00 PM
 
 -1
 15000
 
 
 

Modifying the quartz.properties File for the Plug-In

Earlier in this chapter, you were told that the JobInitializationPlugin looks for the file quartz_jobs.xml to get the declarative job information. If you want to change that file, you need to modify the quartz.properties file and tell the plug-in which file to load. For example, if you wanted Quartz to load job information from an XML file called my_quartz_jobs.xml, you would have to give the plug-in that filename. Listing 3.10 shows how this can be accomplished; we are only repeating the plug-in section here.

Listing 3.10. Modifying quartz.properties for JobInitializationPlugin

org.quartz.plugin.jobInitializer.class =
org.quartz.plugins.xml.JobInitializationPlugin

org.quartz.plugin.jobInitializer.fileName = my_quartz_jobs.xml

org.quartz.plugin.jobInitializer.overWriteExistingJobs = true
org.quartz.plugin.jobInitializer.validating = false
org.quartz.plugin.jobInitializer.overWriteExistingJobs = false
org.quartz.plugin.jobInitializer.failOnFileNotFound = true

In Listing 3.10, we add the property org.quartz.plugin.jobInitializer.fileName and set the value to the name of our file. It must be available to the classloader, which means somewhere on the classpath.

When Quartz starts up and reads the quartz.properties file, it initializes the plug-in. It passes all of these properties to the plug-in, and the plug-in gets notified to look for a different file.


Packaging the Quartz Application

Scheduling in the Enterprise

Getting Started with Quartz

Hello, Quartz

Scheduling Jobs

Cron Triggers and More

JobStores and Persistence

Implementing Quartz Listeners

Using Quartz Plug-Ins

Using Quartz Remotely

Using Quartz with J2EE

Clustering Quartz

Quartz Cookbook

Quartz and Web Applications

Using Quartz with Workflow

Appendix A. Quartz Configuration Reference



Quartz Job Scheduling Framework(c) Building Open Source Enterprise Applications
Quartz Job Scheduling Framework: Building Open Source Enterprise Applications
ISBN: 0131886703
EAN: 2147483647
Year: N/A
Pages: 148

Flylib.com © 2008-2020.
If you may any questions please contact us: flylib@qtcs.net