1 /*
2 * Copyright James House (c) 2001-2004
3 *
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are met: 1.
8 * Redistributions of source code must retain the above copyright notice, this
9 * list of conditions and the following disclaimer. 2. Redistributions in
10 * binary form must reproduce the above copyright notice, this list of
11 * conditions and the following disclaimer in the documentation and/or other
12 * materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
15 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY
18 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
19 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
20 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
21 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 *
25 */
26 package org.quartz.examples;
27
28 import java.util.Date;
29
30 import org.quartz.JobDetail;
31 import org.quartz.Scheduler;
32 import org.quartz.SchedulerFactory;
33 import org.quartz.SchedulerMetaData;
34 import org.quartz.SimpleTrigger;
35 import org.quartz.helpers.TriggerUtils;
36
37 import org.apache.commons.logging.LogFactory;
38 import org.apache.commons.logging.Log;
39
40 /**
41 * Demonstrates the behavior of <code>StatefulJob</code>s, as well as how
42 * misfire instructions affect the firings of triggers of <code>StatefulJob</code>
43 * s - when the jobs take longer to execute that the frequency of the trigger's
44 * repitition.
45 *
46 * <p>
47 * While the example is running, you should note that there are two triggers
48 * with identical schedules, firing identical jobs. The triggers "want" to fire
49 * every 3 seconds, but the jobs take 10 seconds to execute. Therefore, by the
50 * time the jobs complete their execution, the triggers have already "misfired"
51 * (unless the scheduler's "misfire threshold" has been set to more than 7
52 * seconds). You should see that one of the jobs has its misfire instruction
53 * set to <code>SimpleTrigger.MISFIRE_INSTRUCTION_RESCHEDULE_NOW_WITH_EXISTING_REPEAT_COUNT</code>-
54 * which causes it to fire immediately, when the misfire is detected. The other
55 * trigger uses the default "smart policy" misfire instruction, which causes
56 * the trigger to advance to its next fire time (skipping those that it has
57 * missed) - so that it does not refire immediately, but rather at the next
58 * scheduled time.
59 * </p>
60 *
61 * @author James House
62 */
63 public class StatefulJobTest {
64
65 public static void schedTest(SchedulerFactory sf) throws Exception {
66 Log lg = LogFactory.getLog(StatefulJobTest.class);
67
68 lg.info("------- Initializing -------------------");
69
70 Scheduler sched = sf.getScheduler();
71
72 lg.info("------- Initializing 2 -------------------");
73
74 // remove job/trigger entries that may be lingering in a JDBCJobStore
75 // from
76 // previous run of this example... (obviously this doesn't matter for
77 // RAMJobStore -- but is necessary for JDBCJobStore because this
78 // example
79 // program is 'dumb' - it blindly inserts the same jobs every time it
80 // executes - even though they may still be in the JobStore)
81 String[] groups = sched.getTriggerGroupNames();
82 for (int i = 0; i < groups.length; i++) {
83 String[] names = sched.getTriggerNames(groups[i]);
84 for (int j = 0; j < names.length; j++)
85 sched.unscheduleJob(names[j], groups[i]);
86 }
87 groups = sched.getJobGroupNames();
88 for (int i = 0; i < groups.length; i++) {
89 String[] names = sched.getJobNames(groups[i]);
90 for (int j = 0; j < names.length; j++)
91 sched.deleteJob(names[j], groups[i]);
92 }
93
94 lg.info("------- Initialization Complete -----------");
95
96 lg.info("------- Scheduling Jobs -----------");
97
98 // jobs can be scheduled before start() has been called
99
100 long ts = TriggerUtils.getNextGivenSecondDate(null, 5).getTime(); // get
101 // a
102 // 'nice
103 // round'
104 // time
105 // a
106 // few
107 // seconds
108 // in
109 // the
110 // future...
111
112 JobDetail job = new JobDetail("statefulJob1", "group1",
113 StatefulDumbJob.class);
114 job.getJobDataMap().put(StatefulDumbJob.EXECUTION_DELAY, 10000l);
115 SimpleTrigger trigger = new SimpleTrigger("trigg1", "group1", new Date(
116 ts), null, SimpleTrigger.REPEAT_INDEFINITELY, 3000l);
117 Date ft = sched.scheduleJob(job, trigger);
118 lg.info(job.getFullName() + " will run at: " + ft + " & repeat: "
119 + trigger.getRepeatCount() + "/" + trigger.getRepeatInterval());
120
121 job = new JobDetail("statefulJob2", "group1", StatefulDumbJob.class);
122 job.getJobDataMap().put(StatefulDumbJob.EXECUTION_DELAY, 10000l);
123 trigger = new SimpleTrigger("trigg2", "group1", new Date(ts), null,
124 SimpleTrigger.REPEAT_INDEFINITELY, 3000l);
125 trigger
126 .setMisfireInstruction(SimpleTrigger.MISFIRE_INSTRUCTION_RESCHEDULE_NOW_WITH_EXISTING_REPEAT_COUNT);
127 ft = sched.scheduleJob(job, trigger);
128 lg.info(job.getFullName() + " will run at: " + ft + " & repeat: "
129 + trigger.getRepeatCount() + "/" + trigger.getRepeatInterval());
130
131 lg.info("------- Starting Scheduler ----------------");
132
133 // jobs don't start firing until start() has been called...
134
135 sched.start();
136
137 lg.info("------- Started Scheduler -----------------");
138
139 try {
140 Thread.sleep(600l * 1000l); // sleep 10 minutes for triggers to
141 // fire....
142 } catch (Exception e) {
143 }
144
145 lg.info("------- Shutting Down ---------------------");
146
147 sched.shutdown(true);
148
149 lg.info("------- Shutdown Complete -----------------");
150 SchedulerMetaData metaData = sched.getMetaData();
151 lg.info("Executed " + metaData.numJobsExecuted() + " jobs.");
152
153 }
154
155 public static void main(String[] args) throws Exception {
156
157 // Configure Log4J
158 // org.apache.log4j.PropertyConfigurator.configure(System.getProperty("log4jConfigFile",
159 // "log4j.properties"));
160
161 try {
162 schedTest(new org.quartz.impl.StdSchedulerFactory());
163 } catch (Exception e) {
164 e.printStackTrace();
165 }
166 }
167
168 }