Questions About Triggers
How do I chain Job execution? Or, how do I create a workflow?
There currently is no direct or free way to chain triggers with Quartz. However, there are several ways you can accomplish it without much effort. Below is an outline of a couple approaches:
One way is to use a listener (a TriggerListener, JobListener or SchedulerListener) that can notice the completion of a job/trigger and then immediately schedule a new trigger to fire. This approach can get a bit involved, since you will have to inform the listener which job follows which. Additionally, you might need to worry about the persistence of this information. See the listener org.quartz.listeners.JobChainingJobListener, which ships with Quartz, as it already has some of this functionality.
Another way is to build a Job that contains within its JobDataMap the name of the next job to fire, and as the job completes (the last step in its execute( ) method), have the job schedule the next job.
Several users are doing this and have had good luck. Most have made a base (abstract) class that is a Job that knows how to get the job name and group out of the JobDataMap using pre-defined keys (constants) and contains code to schedule the identified job. This abstract Job's implementation of execute( ) delegates to an abstract template method such as "doWork( )" (where the extending Job class's real work goes) and then it contains the code for scheduling the follow-up job. Then they simply make extensions of this class that included the work the job should do. The usage of 'durable' jobs, or the overloaded addJob(JobDetail, boolean, boolean) method helps the application define all the jobs at once with their proper data, without creating triggers to fire them (other than one trigger to fire the first job in the chain).
In the future, Quartz will provide a much cleaner way to do this, but until then, you'll have to use one of the above approaches, or perhaps devise another way that works better for you.
Why isn't my trigger firing?
The most common reason for this is not having called Scheduler.start( ), which tells the scheduler to start firing triggers.
The second most common reason is that the trigger or trigger group has been paused.
Daylight Saving Time and Triggers
CronTrigger and SimpleTrigger each handle daylight savings time in their own way.
First, as a review of what daylight savings time is, please read this resource:
https://secure.wikimedia.org/wikipedia/en/wiki/Daylight_saving_time_around_the_world. Some readers may be unaware that the rules are different for different nations. For example, the 2005 daylight savings time started in the United States on April 3, but in Egypt on April 29. It is also important to know that not only are the starting dates different for different locals, but the time of the shift is different as well. Many places shift at 2:00 am, but others shift time at 1:00 am, others at 3:00 am, and still others right at midnight.
SimpleTrigger allows you to schedule jobs to fire every n milliseconds. As such, it has to do nothing in particular with respect to daylight savings time in order to "stay on schedule." It simply keeps firing every n milliseconds. Regardless your SimpleTrigger is firing every 10 seconds, or every 15 minutes, or every hour or every 24 hours it will continue to do so. However the implication of this which confuses some users is that if your SimpleTrigger is firing say every 12 hours, before daylight savings switches it may be firing at what appears to be 3:00 am and 3:00 pm, but after daylight savings 4:00 am and 4:00 pm. This is not actually a bug. The trigger has kept firing exactly every n milliseconds, it just that the "name" of that time that humans impose on that moment has changed.
CronTrigger allows you to schedule jobs to fire at certain moments with respect to a Gregorian calendar. Hence, if you create a trigger to fire every day at 10:00 am, before and after daylight savings time switches it will continue to do so. However, depending on whether it was the Spring or Autumn daylight savings event, for that particular Sunday, the actual time interval between the firing of the trigger on Sunday morning at 10:00 am since its firing on Saturday morning at 10:00 am will not be 24 hours, but will instead be 23 or 25 hours, respectively.
There is one additional point to understand about CronTrigger with respect to daylight savings. This is that you should think carefully about creating schedules that fire between midnight and 3:00 am (the critical window of time depends on your trigger's locale, as explained above). The reason is that depending on your trigger's schedule, and the particular daylight event, the trigger may be skipped or may appear to not fire for an hour or two. As examples, say you are in the United States, where daylight savings events occur at 2:00 am. If you have a CronTrigger that fires every day at 2:15 am, then on the day of the beginning of daylight savings time the trigger will be skipped, since, 2:15 am never occurs that day. If you have a CronTrigger that fires every 15 minutes of every hour of every day, then on the day daylight savings time ends you will have an hour of time for which no triggerings occur, because when 2:00 am arrives, it will become 1:00 am again, however all of the firings during the one o'clock hour have already occurred, and the trigger's next fire time was set to 2:00 am. Hence, for the next hour, no triggerings will occur.
In summary, all of this makes perfect sense, and should be easy to remember if you keep these two rules in mind:
SimpleTrigger
always fires exactly every
n seconds, with no relation to the time of day.
CronTrigger
n fires at a given time of day and then computes its next time to fire. If that time does not occur on a given day, the trigger will be skipped. If the time occurs twice in a given day, it only fires once, because after firing on that time the first time, it computes the next time of day to fire on.
Other trigger types that are based on sliding along a calendar (rather than exact amounts of time), such as CalenderIntervalTrigger, will be similarly affected. However, rather than missing a firing, or firing twice, it might end up having its fire time shifted by an hour.