Listening for Scheduler Events
The org.quartz.SchedulerListener interface contains a set of callback methods that the Scheduler invokes when key events take place during the life cycle of a Scheduler. Listing 7.9 shows the methods that are included in the SchedulerListener interface.
Listing 7.9. The Methods in the org.quartz.SchedulerListener Interface
public interface SchedulerListener { public void jobScheduled(Trigger trigger); public void jobUnscheduled(String triggerName, String triggerGroup); public void triggerFinalized(Trigger trigger); public void triggersPaused(String triggerName, String triggerGroup); public void triggersResumed(String triggerName,String triggerGroup); public void jobsPaused(String jobName, String jobGroup); public void jobsResumed(String jobName, String jobGroup); public void schedulerError(String msg, SchedulerException cause); public void schedulerShutdown(); } |
As you can see from the methods listed in Listing 7.9, the SchedulerListener is notified when events occur at the Scheduler level, whether it's the addition or removal of a job in the Scheduler or if the Scheduler encounters a serious error. These events are more about the management of the Scheduler than a particular job or trigger.
The jobScheduled() and jobUnscheduled() Methods
The Scheduler calls these methods when a new JobDetail is scheduled or unscheduled, respectively.
The TRiggerFinalized() Method
The Scheduler calls this method when a trigger has reached the state that it will never fire again. Unless the job has been set up as durable, it will be removed from the Scheduler.
The triggersPaused() Method
The Scheduler calls this method when a trigger or group of triggers has been paused. If it's a trigger group, the triggerName parameter will be null.
The triggersResumed() Method
The Scheduler calls this method when a trigger or group of triggers has been unpaused (or resumed). If it's a trigger group, the triggerName parameter will be null.
The jobsPaused() Method
The Scheduler calls this method when a JobDetail or a group of JobDetails has been paused.
The jobsResumed() Method
The Scheduler calls this method when a job or a group of jobs has been unpaused (or resumed). If it's a job group, the jobName parameter will be null.
The schedulerError() Method
The Scheduler calls this method when a serious error has occurred during the normal runtime of the Scheduler. The type of error can vary, but a few examples are listed here:
- Problems instantiating a job class
- Problems trying to find the next trigger
- Repeated problems with the JobStore
- DataStore connection problems
You can use the getErrorCode() or getUnderlyingException() methods of the SchedulerException to get more information about the specific error.
The schedulerShutdown() Method
The Scheduler calls this method to inform the SchedulerListener that the Scheduler is shutting down.
Listing 7.10 shows a simple SchedulerListener implementation.
Listing 7.10. A Simplified SchedulerListener Implementation
package org.cavaness.quartzbook.chapter7; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.quartz.SchedulerException; import org.quartz.SchedulerListener; import org.quartz.Trigger; public class SimpleSchedulerListener implements SchedulerListener { Log logger = LogFactory.getLog(SimpleSchedulerListener.class); public void jobScheduled(Trigger trigger) { String jobName = trigger.getJobName(); logger.info(jobName + " has been scheduled"); } public void jobUnscheduled(String triggerName, String triggerGroup) { if (triggerName == null) { // triggerGroup is being unscheduled logger.info(triggerGroup + " is being unscheduled"); } else { logger.info(triggerName + " is being unscheduled"); } } public void triggerFinalized(Trigger trigger) { String jobName = trigger.getJobName(); logger.info("Trigger is finished for " + jobName); } public void triggersPaused(String triggerName, String triggerGroup) { if (triggerName == null) { // triggerGroup is being unscheduled logger.info(triggerGroup + " is being paused"); } else { logger.info(triggerName + " is being paused"); } } public void triggersResumed(String triggerName, String triggerGroup) { if (triggerName == null) { // triggerGroup is being unscheduled logger.info(triggerGroup + " is now resuming"); } else { logger.info(triggerName + " is now resuming"); } } public void jobsPaused(String jobName, String jobGroup) { if (jobName == null) { // triggerGroup is being unscheduled logger.info(jobGroup + " is pausing"); } else { logger.info(jobName + " is pausing"); } } public void jobsResumed(String jobName, String jobGroup) { if (jobName == null) { // triggerGroup is being unscheduled logger.info(jobGroup + " is now resuming"); } else { logger.info(jobName + " is now resuming"); } } public void schedulerError(String msg, SchedulerException cause) { logger.error(msg, cause.getUnderlyingException()); } public void schedulerShutdown() { logger.info("Scheduler is being shutdown"); } } |
As with the previous examples, the SimpleSchedulerListener in Listing 7.10 provides simple implementations for the listener methods. Listing 7.11 uses the SimpleSchedulerListener class.
Listing 7.11. Using the SimpleSchedulerListener
package org.cavaness.quartzbook.chapter7; import java.util.Date; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.cavaness.quartzbook.common.PrintInfoJob; import org.quartz.JobDetail; import org.quartz.Scheduler; import org.quartz.SchedulerException; import org.quartz.SchedulerListener; import org.quartz.Trigger; import org.quartz.TriggerUtils; import org.quartz.impl.StdSchedulerFactory; public class Listing_7_11 { static Log logger = LogFactory.getLog(Listing_7_11.class); public static void main(String[] args) { Listing_7_11 example = new Listing_7_11(); try { example.startScheduler(); } catch (SchedulerException ex) { logger.error(ex); } } public void startScheduler() throws SchedulerException { // Create an instance of the factory Scheduler scheduler = null; // Create the scheduler and JobDetail scheduler = StdSchedulerFactory.getDefaultScheduler(); // Create and register the scheduler listener SchedulerListener schedulerListener = new SimpleSchedulerListener(); scheduler.addSchedulerListener(schedulerListener); // Start the scheduler scheduler.start(); logger.info("Scheduler was started at " + new Date()); // Create the JobDetail JobDetail jobDetail = new JobDetail("PrintInfoJob", Scheduler.DEFAULT_GROUP, PrintInfoJob.class); /* * Set up a trigger to start firing now, with no end * date/time, repeat forever and have 5 secs * between each firing. */ Trigger trigger = TriggerUtils.makeSecondlyTrigger(5); trigger.setName("SimpleTrigger"); trigger.setStartTime(new Date()); // Register the JobDetail and Trigger scheduler.scheduleJob(jobDetail, trigger); } } |
We changed some things in Listing 7.11 from the previous examples, to actually cause more of the SchedulerListener methods to be called. In Listing 7.11, the Scheduler is created and started before the job is registered. This is so the jobScheduled() method gets called when the job is scheduled. We also changed the trigger to repeat two times instead of running indefinitely. This forces the triggerFinalized() method to be called because there were no more firing times for the trigger. Other than these contrived conditions, using the SchedulerListener is the same as using the job or trigger listeners.