Example 4 - Job Parameters and Job State
This example is designed to demonstrate how you can pass run-time parameters into quartz jobs and how you can maintain state in a job.
The program will perform the following actions:
- Start up the Quartz Scheduler
- Schedule two jobs, each job will execute the every ten seconds for a total of times
- The scheduler will pass a run-time job parameter of “Green” to the first job instance
- The scheduler will pass a run-time job parameter of “Red” to the second job instance
- The program will wait 60 seconds so that the two jobs have plenty of time to run
- Shut down the Scheduler
Running the Example
This example can be executed from the examples/example4 directory. There are two out-of-the-box methods for running this example
- example4.sh - A UNIX/Linux shell script
- example4.bat - A Windows Batch file
The Code
The code for this example resides in the package org.quartz.examples.example4.
The code in this example is made up of the following classes:
Class Name | Description |
---|---|
JobStateExample | The main program |
ColorJob | A simple job that prints a favorite color (passed in as a run-time parameter) and displays its execution count. |
ColorJob
ColorJob is a simple class that implement the Job interface, and is annotated as such:
@PersistJobDataAfterExecution
@DisallowConcurrentExecution
public class ColorJob implements Job {
The annotations cause behavior just as their names describe - multiple instances of the job will not be allowed to run concurrently (consider a case where a job has code in its execute() method that takes 34 seconds to run, but it is scheduled with a trigger that repeats every 30 seconds), and will have its JobDataMap contents re-persisted in the scheduler’s JobStore after each execution. For the purposes of this example, only @PersistJobDataAfterExecution annotation is truly relevant, but it’s always wise to use the @DisallowConcurrentExecution annotation with it, to prevent race-conditions on saved data.
ColorJob logs the following information when the job is executed:
- The job’s identification key (name and group) and time/date of execution
- The job’s favorite color (which is passed in as a run-time parameter)
- The job’s execution count calculated from a member variable
- The job’s execution count maintained as a job map parameter
_log.info("ColorJob: " + jobKey + " executing at " + new Date() + "\n" +
" favorite color is " + favoriteColor + "\n" +
" execution count (from job map) is " + count + "\n" +
" execution count (from job member variable) is " + _counter);
The variable favoriteColor is passed in as a job parameter. It is retrieved as follows from the JobDataMap:
JobDataMap data = context.getJobDetail().getJobDataMap();
String favoriteColor = data.getString(FAVORITE_COLOR);
The variable count is stored in the job data map as well:
JobDataMap data = context.getJobDetail().getJobDataMap();
int count = data.getInt(EXECUTION_COUNT);
The variable is later incremented and stored back into the job data map so that job state can be preserved:
count++;
data.put(EXECUTION_COUNT, count);
There is also a member variable named counter. This variable is defined as a member variable to the class:
private int _counter = 1;
This variable is also incremented and displayed. However, its count will always be displayed as “1” because Quartz will always instantiate a new instance of the class during each execution - which prevents member variables from being used to maintain state.
JobStateExample
The program starts by getting an instance of the Scheduler. This is done by creating a StdSchedulerFactory and then using it to create a scheduler. This will create a simple, RAM-based scheduler.
SchedulerFactory sf = new StdSchedulerFactory();
Scheduler sched = sf.getScheduler();
Job #1 is scheduled to run every 10 seconds, for a total of five times:
JobDetail job1 = newJob(ColorJob.class)
.withIdentity("job1", "group1")
.build();
SimpleTrigger trigger1 = newTrigger()
.withIdentity("trigger1", "group1")
.startAt(startTime)
.withSchedule(simpleSchedule()
.withIntervalInSeconds(10)
.withRepeatCount(4))
.build();
Job #1 is passed in two job parameters. One is a favorite color, with a value of “Green”. The other is an execution count, which is initialized with a value of 1.
job1.getJobDataMap().put(ColorJob.FAVORITE_COLOR, "Green");
job1.getJobDataMap().put(ColorJob.EXECUTION_COUNT, 1);
Job #2 is also scheduled to run every 10 seconds, for a total of five times:
JobDetail job2 = newJob(ColorJob.class)
.withIdentity("job2", "group1")
.build();
SimpleTrigger trigger2 = newTrigger()
.withIdentity("trigger2", "group1")
.startAt(startTime)
.withSchedule(simpleSchedule()
.withIntervalInSeconds(10)
.withRepeatCount(4))
.build();
Job #2 is also passed in two job parameters. One is a favorite color, with a value of “Red”. The other is an execution count, which is initialized with a value of 1.
job2.getJobDataMap().put(ColorJob.FAVORITE_COLOR, "Red");
job2.getJobDataMap().put(ColorJob.EXECUTION_COUNT, 1);
The scheduler is then started.
sched.start();
To let the program have an opportunity to run the job, we then sleep for one minute (60 seconds)
Thread.sleep(60L * 1000L);
Finally, we will gracefully shutdown the scheduler:
sched.shutdown(true);
Note: passing true into the shutdown message tells the Quartz Scheduler to wait until all jobs have completed running before returning from the method call.