Example 5 - Job Misfires
This example is designed to demonstrate concepts related to trigger misfires.
The program will perform the following actions:
- Start up the Quartz Scheduler
- Schedule two jobs, each job will execute the every three seconds, indefinitely
- The jobs will take ten seconds to run (preventing the execution trigger from firing every three seconds)
- Each job has different misfire instructions
- The program will wait 10 minutes 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/example5 directory. There are two out-of-the-box methods for running this example
- example5.sh - A UNIX/Linux shell script
- example5.bat - A Windows Batch file
The Code
The code for this example resides in the package org.quartz.examples.example5.
The code in this example is made up of the following classes:
Class Name | Description |
---|---|
MisfireExample | The main program |
StatefulDumbJob | A simple job class who's execute method takes 10 seconds to run |
StatefulDumbJob
StatefulDumbJob is a simple job that prints its execution time and then will wait for a period of time before completing.
The amount of wait time is defined by the job parameter EXECUTION_DELAY. If this job parameter is not passed in, the
job will default to a wait time of 5 seconds. The job is also keep its own count of how many times it has executed
using a value in its JobDataMap called NUM_EXECUTIONS. Because the class has the PersistJobDataAfterExecution
annotation, the execution count is preserved between each execution.
@PersistJobDataAfterExecution
@DisallowConcurrentExecution
public class StatefulDumbJob implements Job {
public static final String NUM_EXECUTIONS = "NumExecutions";
public static final String EXECUTION_DELAY = "ExecutionDelay";
public StatefulDumbJob() {
}
public void execute(JobExecutionContext context)
throws JobExecutionException {
System.err.println("---" + context.getJobDetail().getKey()
+ " executing.[" + new Date() + "]");
JobDataMap map = context.getJobDetail().getJobDataMap();
int executeCount = 0;
if (map.containsKey(NUM_EXECUTIONS)) {
executeCount = map.getInt(NUM_EXECUTIONS);
}
executeCount++;
map.put(NUM_EXECUTIONS, executeCount);
long delay = 5000l;
if (map.containsKey(EXECUTION_DELAY)) {
delay = map.getLong(EXECUTION_DELAY);
}
try {
Thread.sleep(delay);
} catch (Exception ignore) {
}
System.err.println(" -" + context.getJobDetail().getKey()
+ " complete (" + executeCount + ").");
}
}
MisfireExample
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 because no specific quartz.properties config file telling it to do otherwise is provided.
SchedulerFactory sf = new StdSchedulerFactory();
Scheduler sched = sf.getScheduler();
Job #1 is scheduled to run every 3 seconds indefinitely. An execution delay of 10 seconds is passed into the job:
JobDetail job = newJob(StatefulDumbJob.class)
.withIdentity("statefulJob1", "group1")
.usingJobData(StatefulDumbJob.EXECUTION_DELAY, 10000L)
.build();
SimpleTrigger trigger = newTrigger()
.withIdentity("trigger1", "group1")
.startAt(startTime)
.withSchedule(simpleSchedule()
.withIntervalInSeconds(3)
.repeatForever())
.build();
sched.scheduleJob(job, trigger);
Job #2 is scheduled to run every 3 seconds indefinitely. An execution delay of 10 seconds is passed into the job:
job = newJob(StatefulDumbJob.class)
.withIdentity("statefulJob2", "group1")
.usingJobData(StatefulDumbJob.EXECUTION_DELAY, 10000L)
.build();
trigger = newTrigger()
.withIdentity("trigger2", "group1")
.startAt(startTime)
.withSchedule(simpleSchedule()
.withIntervalInSeconds(3)
.repeatForever()
.withMisfireHandlingInstructionNowWithExistingCount()) // set misfire instruction
.build();
Note: The trigger for job #2 is set with a misfire instruction that will cause it to reschedule with the existing repeat count. This policy forces quartz to refire the trigger as soon as possible. Job #1 uses the default “smart” misfire policy for simple triggers, which causes the trigger to fire at it’s next normal execution time.
The scheduler is then started.
sched.start();
To let the program have an opportunity to run the job, we then sleep for ten minutes (600 seconds)
Thread.sleep(600L * 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.