1 /*
2  * Copyright 2002-2009 the original author or authors.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package org.springframework.scheduling.quartz;
18 
19 import static org.junit.Assert.assertEquals;
20 import static org.junit.Assert.assertFalse;
21 import static org.junit.Assert.assertNotSame;
22 import static org.junit.Assert.assertSame;
23 import static org.junit.Assert.assertTrue;
24 
25 import java.util.Arrays;
26 import java.util.Date;
27 import java.util.HashMap;
28 import java.util.List;
29 import java.util.Map;
30 
31 import javax.sql.DataSource;
32 
33 import org.easymock.MockControl;
34 import org.junit.Test;
35 import org.quartz.CronTrigger;
36 import org.quartz.Job;
37 import org.quartz.JobDetail;
38 import org.quartz.JobExecutionContext;
39 import org.quartz.JobExecutionException;
40 import org.quartz.JobListener;
41 import org.quartz.ObjectAlreadyExistsException;
42 import org.quartz.Scheduler;
43 import org.quartz.SchedulerContext;
44 import org.quartz.SchedulerException;
45 import org.quartz.SchedulerFactory;
46 import org.quartz.SchedulerListener;
47 import org.quartz.SimpleTrigger;
48 import org.quartz.Trigger;
49 import org.quartz.TriggerListener;
50 import org.quartz.impl.SchedulerRepository;
51 import org.quartz.spi.JobFactory;
52 
53 import org.springframework.beans.TestBean;
54 import org.springframework.beans.factory.config.BeanDefinition;
55 import org.springframework.beans.factory.support.BeanDefinitionBuilder;
56 import org.springframework.beans.factory.support.RootBeanDefinition;
57 import org.springframework.beans.factory.support.StaticListableBeanFactory;
58 import org.springframework.context.support.ClassPathXmlApplicationContext;
59 import org.springframework.context.support.StaticApplicationContext;
60 import org.springframework.core.io.FileSystemResourceLoader;
61 import org.springframework.core.task.TaskExecutor;
62 import org.springframework.jdbc.core.simple.SimpleJdbcTemplate;
63 import org.springframework.scheduling.TestMethodInvokingTask;
64 
65 /**
66  * @author Juergen Hoeller
67  * @author Alef Arendsen
68  * @author Rob Harrop
69  * @author Dave Syer
70  * @author Mark Fisher
71  * @since 20.02.2004
72  */
73 public class QuartzSupportTests {
74 
75 	@Test
testSchedulerFactoryBean()76 	public void testSchedulerFactoryBean() throws Exception {
77 		doTestSchedulerFactoryBean(false, false);
78 	}
79 
80 	@Test
testSchedulerFactoryBeanWithExplicitJobDetail()81 	public void testSchedulerFactoryBeanWithExplicitJobDetail() throws Exception {
82 		doTestSchedulerFactoryBean(true, false);
83 	}
84 
85 	@Test
testSchedulerFactoryBeanWithPrototypeJob()86 	public void testSchedulerFactoryBeanWithPrototypeJob() throws Exception {
87 		doTestSchedulerFactoryBean(false, true);
88 	}
89 
doTestSchedulerFactoryBean(boolean explicitJobDetail, boolean prototypeJob)90 	private void doTestSchedulerFactoryBean(boolean explicitJobDetail, boolean prototypeJob) throws Exception {
91 		TestBean tb = new TestBean("tb", 99);
92 		JobDetailBean jobDetail0 = new JobDetailBean();
93 		jobDetail0.setJobClass(Job.class);
94 		jobDetail0.setBeanName("myJob0");
95 		Map jobData = new HashMap();
96 		jobData.put("testBean", tb);
97 		jobDetail0.setJobDataAsMap(jobData);
98 		jobDetail0.afterPropertiesSet();
99 		assertEquals(tb, jobDetail0.getJobDataMap().get("testBean"));
100 
101 		CronTriggerBean trigger0 = new CronTriggerBean();
102 		trigger0.setBeanName("myTrigger0");
103 		trigger0.setJobDetail(jobDetail0);
104 		trigger0.setCronExpression("0/1 * * * * ?");
105 		trigger0.afterPropertiesSet();
106 
107 		TestMethodInvokingTask task1 = new TestMethodInvokingTask();
108 		MethodInvokingJobDetailFactoryBean mijdfb = new MethodInvokingJobDetailFactoryBean();
109 		mijdfb.setBeanName("myJob1");
110 		if (prototypeJob) {
111 			StaticListableBeanFactory beanFactory = new StaticListableBeanFactory();
112 			beanFactory.addBean("task", task1);
113 			mijdfb.setTargetBeanName("task");
114 			mijdfb.setBeanFactory(beanFactory);
115 		}
116 		else {
117 			mijdfb.setTargetObject(task1);
118 		}
119 		mijdfb.setTargetMethod("doSomething");
120 		mijdfb.afterPropertiesSet();
121 		JobDetail jobDetail1 = (JobDetail) mijdfb.getObject();
122 
123 		SimpleTriggerBean trigger1 = new SimpleTriggerBean();
124 		trigger1.setBeanName("myTrigger1");
125 		trigger1.setJobDetail(jobDetail1);
126 		trigger1.setStartDelay(0);
127 		trigger1.setRepeatInterval(20);
128 		trigger1.afterPropertiesSet();
129 
130 		MockControl schedulerControl = MockControl.createControl(Scheduler.class);
131 		final Scheduler scheduler = (Scheduler) schedulerControl.getMock();
132 		scheduler.getContext();
133 		schedulerControl.setReturnValue(new SchedulerContext());
134 		scheduler.getJobDetail("myJob0", Scheduler.DEFAULT_GROUP);
135 		schedulerControl.setReturnValue(null);
136 		scheduler.getJobDetail("myJob1", Scheduler.DEFAULT_GROUP);
137 		schedulerControl.setReturnValue(null);
138 		scheduler.getTrigger("myTrigger0", Scheduler.DEFAULT_GROUP);
139 		schedulerControl.setReturnValue(null);
140 		scheduler.getTrigger("myTrigger1", Scheduler.DEFAULT_GROUP);
141 		schedulerControl.setReturnValue(null);
142 		scheduler.addJob(jobDetail0, true);
143 		schedulerControl.setVoidCallable();
144 		scheduler.scheduleJob(trigger0);
145 		schedulerControl.setReturnValue(new Date());
146 		scheduler.addJob(jobDetail1, true);
147 		schedulerControl.setVoidCallable();
148 		scheduler.scheduleJob(trigger1);
149 		schedulerControl.setReturnValue(new Date());
150 		scheduler.start();
151 		schedulerControl.setVoidCallable();
152 		scheduler.shutdown(false);
153 		schedulerControl.setVoidCallable();
154 		schedulerControl.replay();
155 
156 		SchedulerFactoryBean schedulerFactoryBean = new SchedulerFactoryBean() {
157 			protected Scheduler createScheduler(SchedulerFactory schedulerFactory, String schedulerName) {
158 				return scheduler;
159 			}
160 		};
161 		schedulerFactoryBean.setJobFactory(null);
162 		Map schedulerContext = new HashMap();
163 		schedulerContext.put("otherTestBean", tb);
164 		schedulerFactoryBean.setSchedulerContextAsMap(schedulerContext);
165 		if (explicitJobDetail) {
166 			schedulerFactoryBean.setJobDetails(new JobDetail[] {jobDetail0});
167 		}
168 		schedulerFactoryBean.setTriggers(new Trigger[] {trigger0, trigger1});
169 		try {
170 			schedulerFactoryBean.afterPropertiesSet();
171 			schedulerFactoryBean.start();
172 		}
173 		finally {
174 			schedulerFactoryBean.destroy();
175 		}
176 
177 		schedulerControl.verify();
178 	}
179 
180 	@Test
testSchedulerFactoryBeanWithExistingJobs()181 	public void testSchedulerFactoryBeanWithExistingJobs() throws Exception {
182 		doTestSchedulerFactoryBeanWithExistingJobs(false);
183 	}
184 
185 	@Test
testSchedulerFactoryBeanWithOverwriteExistingJobs()186 	public void testSchedulerFactoryBeanWithOverwriteExistingJobs() throws Exception {
187 		doTestSchedulerFactoryBeanWithExistingJobs(true);
188 	}
189 
doTestSchedulerFactoryBeanWithExistingJobs(boolean overwrite)190 	private void doTestSchedulerFactoryBeanWithExistingJobs(boolean overwrite) throws Exception {
191 		TestBean tb = new TestBean("tb", 99);
192 		JobDetailBean jobDetail0 = new JobDetailBean();
193 		jobDetail0.setJobClass(Job.class);
194 		jobDetail0.setBeanName("myJob0");
195 		Map jobData = new HashMap();
196 		jobData.put("testBean", tb);
197 		jobDetail0.setJobDataAsMap(jobData);
198 		jobDetail0.afterPropertiesSet();
199 		assertEquals(tb, jobDetail0.getJobDataMap().get("testBean"));
200 
201 		CronTriggerBean trigger0 = new CronTriggerBean();
202 		trigger0.setBeanName("myTrigger0");
203 		trigger0.setJobDetail(jobDetail0);
204 		trigger0.setCronExpression("0/1 * * * * ?");
205 		trigger0.afterPropertiesSet();
206 
207 		TestMethodInvokingTask task1 = new TestMethodInvokingTask();
208 		MethodInvokingJobDetailFactoryBean mijdfb = new MethodInvokingJobDetailFactoryBean();
209 		mijdfb.setBeanName("myJob1");
210 		mijdfb.setTargetObject(task1);
211 		mijdfb.setTargetMethod("doSomething");
212 		mijdfb.afterPropertiesSet();
213 		JobDetail jobDetail1 = (JobDetail) mijdfb.getObject();
214 
215 		SimpleTriggerBean trigger1 = new SimpleTriggerBean();
216 		trigger1.setBeanName("myTrigger1");
217 		trigger1.setJobDetail(jobDetail1);
218 		trigger1.setStartDelay(0);
219 		trigger1.setRepeatInterval(20);
220 		trigger1.afterPropertiesSet();
221 
222 		MockControl schedulerControl = MockControl.createControl(Scheduler.class);
223 		final Scheduler scheduler = (Scheduler) schedulerControl.getMock();
224 		scheduler.getContext();
225 		schedulerControl.setReturnValue(new SchedulerContext());
226 		scheduler.getTrigger("myTrigger0", Scheduler.DEFAULT_GROUP);
227 		schedulerControl.setReturnValue(null);
228 		scheduler.getTrigger("myTrigger1", Scheduler.DEFAULT_GROUP);
229 		schedulerControl.setReturnValue(new SimpleTrigger());
230 		if (overwrite) {
231 			scheduler.addJob(jobDetail1, true);
232 			schedulerControl.setVoidCallable();
233 			scheduler.rescheduleJob("myTrigger1", Scheduler.DEFAULT_GROUP, trigger1);
234 			schedulerControl.setReturnValue(new Date());
235 		}
236 		else {
237 			scheduler.getJobDetail("myJob0", Scheduler.DEFAULT_GROUP);
238 			schedulerControl.setReturnValue(null);
239 		}
240 		scheduler.addJob(jobDetail0, true);
241 		schedulerControl.setVoidCallable();
242 		scheduler.scheduleJob(trigger0);
243 		schedulerControl.setReturnValue(new Date());
244 		scheduler.start();
245 		schedulerControl.setVoidCallable();
246 		scheduler.shutdown(false);
247 		schedulerControl.setVoidCallable();
248 		schedulerControl.replay();
249 
250 		SchedulerFactoryBean schedulerFactoryBean = new SchedulerFactoryBean() {
251 			protected Scheduler createScheduler(SchedulerFactory schedulerFactory, String schedulerName) {
252 				return scheduler;
253 			}
254 		};
255 		schedulerFactoryBean.setJobFactory(null);
256 		Map schedulerContext = new HashMap();
257 		schedulerContext.put("otherTestBean", tb);
258 		schedulerFactoryBean.setSchedulerContextAsMap(schedulerContext);
259 		schedulerFactoryBean.setTriggers(new Trigger[] {trigger0, trigger1});
260 		if (overwrite) {
261 			schedulerFactoryBean.setOverwriteExistingJobs(true);
262 		}
263 		try {
264 			schedulerFactoryBean.afterPropertiesSet();
265 			schedulerFactoryBean.start();
266 		}
267 		finally {
268 			schedulerFactoryBean.destroy();
269 		}
270 
271 		schedulerControl.verify();
272 	}
273 
274 	@Test
testSchedulerFactoryBeanWithExistingJobsAndRaceCondition()275 	public void testSchedulerFactoryBeanWithExistingJobsAndRaceCondition() throws Exception {
276 		doTestSchedulerFactoryBeanWithExistingJobsAndRaceCondition(false);
277 	}
278 
279 	@Test
testSchedulerFactoryBeanWithOverwriteExistingJobsAndRaceCondition()280 	public void testSchedulerFactoryBeanWithOverwriteExistingJobsAndRaceCondition() throws Exception {
281 		doTestSchedulerFactoryBeanWithExistingJobsAndRaceCondition(true);
282 	}
283 
doTestSchedulerFactoryBeanWithExistingJobsAndRaceCondition(boolean overwrite)284 	private void doTestSchedulerFactoryBeanWithExistingJobsAndRaceCondition(boolean overwrite) throws Exception {
285 		TestBean tb = new TestBean("tb", 99);
286 		JobDetailBean jobDetail0 = new JobDetailBean();
287 		jobDetail0.setJobClass(Job.class);
288 		jobDetail0.setBeanName("myJob0");
289 		Map jobData = new HashMap();
290 		jobData.put("testBean", tb);
291 		jobDetail0.setJobDataAsMap(jobData);
292 		jobDetail0.afterPropertiesSet();
293 		assertEquals(tb, jobDetail0.getJobDataMap().get("testBean"));
294 
295 		CronTriggerBean trigger0 = new CronTriggerBean();
296 		trigger0.setBeanName("myTrigger0");
297 		trigger0.setJobDetail(jobDetail0);
298 		trigger0.setCronExpression("0/1 * * * * ?");
299 		trigger0.afterPropertiesSet();
300 
301 		TestMethodInvokingTask task1 = new TestMethodInvokingTask();
302 		MethodInvokingJobDetailFactoryBean mijdfb = new MethodInvokingJobDetailFactoryBean();
303 		mijdfb.setBeanName("myJob1");
304 		mijdfb.setTargetObject(task1);
305 		mijdfb.setTargetMethod("doSomething");
306 		mijdfb.afterPropertiesSet();
307 		JobDetail jobDetail1 = (JobDetail) mijdfb.getObject();
308 
309 		SimpleTriggerBean trigger1 = new SimpleTriggerBean();
310 		trigger1.setBeanName("myTrigger1");
311 		trigger1.setJobDetail(jobDetail1);
312 		trigger1.setStartDelay(0);
313 		trigger1.setRepeatInterval(20);
314 		trigger1.afterPropertiesSet();
315 
316 		MockControl schedulerControl = MockControl.createControl(Scheduler.class);
317 		final Scheduler scheduler = (Scheduler) schedulerControl.getMock();
318 		scheduler.getContext();
319 		schedulerControl.setReturnValue(new SchedulerContext());
320 		scheduler.getTrigger("myTrigger0", Scheduler.DEFAULT_GROUP);
321 		schedulerControl.setReturnValue(null);
322 		scheduler.getTrigger("myTrigger1", Scheduler.DEFAULT_GROUP);
323 		schedulerControl.setReturnValue(new SimpleTrigger());
324 		if (overwrite) {
325 			scheduler.addJob(jobDetail1, true);
326 			schedulerControl.setVoidCallable();
327 			scheduler.rescheduleJob("myTrigger1", Scheduler.DEFAULT_GROUP, trigger1);
328 			schedulerControl.setReturnValue(new Date());
329 		}
330 		else {
331 			scheduler.getJobDetail("myJob0", Scheduler.DEFAULT_GROUP);
332 			schedulerControl.setReturnValue(null);
333 		}
334 		scheduler.addJob(jobDetail0, true);
335 		schedulerControl.setVoidCallable();
336 		scheduler.scheduleJob(trigger0);
337 		schedulerControl.setThrowable(new ObjectAlreadyExistsException(""));
338 		if (overwrite) {
339 			scheduler.rescheduleJob("myTrigger0", Scheduler.DEFAULT_GROUP, trigger0);
340 			schedulerControl.setReturnValue(new Date());
341 		}
342 		scheduler.start();
343 		schedulerControl.setVoidCallable();
344 		scheduler.shutdown(false);
345 		schedulerControl.setVoidCallable();
346 		schedulerControl.replay();
347 
348 		SchedulerFactoryBean schedulerFactoryBean = new SchedulerFactoryBean() {
349 			protected Scheduler createScheduler(SchedulerFactory schedulerFactory, String schedulerName) {
350 				return scheduler;
351 			}
352 		};
353 		schedulerFactoryBean.setJobFactory(null);
354 		Map schedulerContext = new HashMap();
355 		schedulerContext.put("otherTestBean", tb);
356 		schedulerFactoryBean.setSchedulerContextAsMap(schedulerContext);
357 		schedulerFactoryBean.setTriggers(new Trigger[] {trigger0, trigger1});
358 		if (overwrite) {
359 			schedulerFactoryBean.setOverwriteExistingJobs(true);
360 		}
361 		try {
362 			schedulerFactoryBean.afterPropertiesSet();
363 			schedulerFactoryBean.start();
364 		}
365 		finally {
366 			schedulerFactoryBean.destroy();
367 		}
368 
369 		schedulerControl.verify();
370 	}
371 
372 	@Test
testSchedulerFactoryBeanWithListeners()373 	public void testSchedulerFactoryBeanWithListeners() throws Exception {
374 		JobFactory jobFactory = new AdaptableJobFactory();
375 
376 		MockControl schedulerControl = MockControl.createControl(Scheduler.class);
377 		final Scheduler scheduler = (Scheduler) schedulerControl.getMock();
378 
379 		SchedulerListener schedulerListener = new TestSchedulerListener();
380 		JobListener globalJobListener = new TestJobListener();
381 		JobListener jobListener = new TestJobListener();
382 		TriggerListener globalTriggerListener = new TestTriggerListener();
383 		TriggerListener triggerListener = new TestTriggerListener();
384 
385 		scheduler.setJobFactory(jobFactory);
386 		schedulerControl.setVoidCallable();
387 		scheduler.addSchedulerListener(schedulerListener);
388 		schedulerControl.setVoidCallable();
389 		scheduler.addGlobalJobListener(globalJobListener);
390 		schedulerControl.setVoidCallable();
391 		scheduler.addJobListener(jobListener);
392 		schedulerControl.setVoidCallable();
393 		scheduler.addGlobalTriggerListener(globalTriggerListener);
394 		schedulerControl.setVoidCallable();
395 		scheduler.addTriggerListener(triggerListener);
396 		schedulerControl.setVoidCallable();
397 		scheduler.start();
398 		schedulerControl.setVoidCallable();
399 		scheduler.shutdown(false);
400 		schedulerControl.setVoidCallable();
401 		schedulerControl.replay();
402 
403 		SchedulerFactoryBean schedulerFactoryBean = new SchedulerFactoryBean() {
404 			protected Scheduler createScheduler(SchedulerFactory schedulerFactory, String schedulerName) {
405 				return scheduler;
406 			}
407 		};
408 		schedulerFactoryBean.setJobFactory(jobFactory);
409 		schedulerFactoryBean.setSchedulerListeners(new SchedulerListener[] {schedulerListener});
410 		schedulerFactoryBean.setGlobalJobListeners(new JobListener[] {globalJobListener});
411 		schedulerFactoryBean.setJobListeners(new JobListener[] {jobListener});
412 		schedulerFactoryBean.setGlobalTriggerListeners(new TriggerListener[] {globalTriggerListener});
413 		schedulerFactoryBean.setTriggerListeners(new TriggerListener[] {triggerListener});
414 		try {
415 			schedulerFactoryBean.afterPropertiesSet();
416 			schedulerFactoryBean.start();
417 		}
418 		finally {
419 			schedulerFactoryBean.destroy();
420 		}
421 
422 		schedulerControl.verify();
423 	}
424 
425 	/*public void testMethodInvocationWithConcurrency() throws Exception {
426 		methodInvokingConcurrency(true);
427 	}*/
428 
429 	// We can't test both since Quartz somehow seems to keep things in memory
430 	// enable both and one of them will fail (order doesn't matter).
431 	/*public void testMethodInvocationWithoutConcurrency() throws Exception {
432 		methodInvokingConcurrency(false);
433 	}*/
434 
methodInvokingConcurrency(boolean concurrent)435 	private void methodInvokingConcurrency(boolean concurrent) throws Exception {
436 		// Test the concurrency flag.
437 		// Method invoking job with two triggers.
438 		// If the concurrent flag is false, the triggers are NOT allowed
439 		// to interfere with each other.
440 
441 		TestMethodInvokingTask task1 = new TestMethodInvokingTask();
442 		MethodInvokingJobDetailFactoryBean mijdfb = new MethodInvokingJobDetailFactoryBean();
443 		// set the concurrency flag!
444 		mijdfb.setConcurrent(concurrent);
445 		mijdfb.setBeanName("myJob1");
446 		mijdfb.setTargetObject(task1);
447 		mijdfb.setTargetMethod("doWait");
448 		mijdfb.afterPropertiesSet();
449 		JobDetail jobDetail1 = (JobDetail) mijdfb.getObject();
450 
451 		SimpleTriggerBean trigger0 = new SimpleTriggerBean();
452 		trigger0.setBeanName("myTrigger1");
453 		trigger0.setJobDetail(jobDetail1);
454 		trigger0.setStartDelay(0);
455 		trigger0.setRepeatInterval(1);
456 		trigger0.setRepeatCount(1);
457 		trigger0.afterPropertiesSet();
458 
459 		SimpleTriggerBean trigger1 = new SimpleTriggerBean();
460 		trigger1.setBeanName("myTrigger1");
461 		trigger1.setJobDetail(jobDetail1);
462 		trigger1.setStartDelay(1000L);
463 		trigger1.setRepeatInterval(1);
464 		trigger1.setRepeatCount(1);
465 		trigger1.afterPropertiesSet();
466 
467 		SchedulerFactoryBean schedulerFactoryBean = new SchedulerFactoryBean();
468 		schedulerFactoryBean.setJobDetails(new JobDetail[] {jobDetail1});
469 		schedulerFactoryBean.setTriggers(new Trigger[] {trigger1, trigger0});
470 		schedulerFactoryBean.afterPropertiesSet();
471 
472 		// ok scheduler is set up... let's wait for like 4 seconds
473 		try {
474 			Thread.sleep(4000);
475 		}
476 		catch (InterruptedException ex) {
477 			// fall through
478 		}
479 
480 		if (concurrent) {
481 			assertEquals(2, task1.counter);
482 			task1.stop();
483 			// we're done, both jobs have ran, let's call it a day
484 			return;
485 		}
486 		else {
487 			assertEquals(1, task1.counter);
488 			task1.stop();
489 			// we need to check whether or not the test succeed with non-concurrent jobs
490 		}
491 
492 		try {
493 			Thread.sleep(4000);
494 		}
495 		catch (InterruptedException ex) {
496 			// fall through
497 		}
498 
499 		task1.stop();
500 		assertEquals(2, task1.counter);
501 
502 		// Although we're destroying the scheduler, it does seem to keep things in memory:
503 		// When executing both tests (concurrent and non-concurrent), the second test always
504 		// fails.
505 		schedulerFactoryBean.destroy();
506 	}
507 
508 	@Test
testSchedulerFactoryBeanWithPlainQuartzObjects()509 	public void testSchedulerFactoryBeanWithPlainQuartzObjects() throws Exception {
510 		JobFactory jobFactory = new AdaptableJobFactory();
511 
512 		TestBean tb = new TestBean("tb", 99);
513 		JobDetail jobDetail0 = new JobDetail();
514 		jobDetail0.setJobClass(Job.class);
515 		jobDetail0.setName("myJob0");
516 		jobDetail0.setGroup(Scheduler.DEFAULT_GROUP);
517 		jobDetail0.getJobDataMap().put("testBean", tb);
518 		assertEquals(tb, jobDetail0.getJobDataMap().get("testBean"));
519 
520 		CronTrigger trigger0 = new CronTrigger();
521 		trigger0.setName("myTrigger0");
522 		trigger0.setGroup(Scheduler.DEFAULT_GROUP);
523 		trigger0.setJobName("myJob0");
524 		trigger0.setJobGroup(Scheduler.DEFAULT_GROUP);
525 		trigger0.setStartTime(new Date());
526 		trigger0.setCronExpression("0/1 * * * * ?");
527 
528 		TestMethodInvokingTask task1 = new TestMethodInvokingTask();
529 		MethodInvokingJobDetailFactoryBean mijdfb = new MethodInvokingJobDetailFactoryBean();
530 		mijdfb.setName("myJob1");
531 		mijdfb.setGroup(Scheduler.DEFAULT_GROUP);
532 		mijdfb.setTargetObject(task1);
533 		mijdfb.setTargetMethod("doSomething");
534 		mijdfb.afterPropertiesSet();
535 		JobDetail jobDetail1 = (JobDetail) mijdfb.getObject();
536 
537 		SimpleTrigger trigger1 = new SimpleTrigger();
538 		trigger1.setName("myTrigger1");
539 		trigger1.setGroup(Scheduler.DEFAULT_GROUP);
540 		trigger1.setJobName("myJob1");
541 		trigger1.setJobGroup(Scheduler.DEFAULT_GROUP);
542 		trigger1.setStartTime(new Date());
543 		trigger1.setRepeatCount(SimpleTrigger.REPEAT_INDEFINITELY);
544 		trigger1.setRepeatInterval(20);
545 
546 		MockControl schedulerControl = MockControl.createControl(Scheduler.class);
547 		final Scheduler scheduler = (Scheduler) schedulerControl.getMock();
548 		scheduler.setJobFactory(jobFactory);
549 		schedulerControl.setVoidCallable();
550 		scheduler.getJobDetail("myJob0", Scheduler.DEFAULT_GROUP);
551 		schedulerControl.setReturnValue(null);
552 		scheduler.getJobDetail("myJob1", Scheduler.DEFAULT_GROUP);
553 		schedulerControl.setReturnValue(null);
554 		scheduler.getTrigger("myTrigger0", Scheduler.DEFAULT_GROUP);
555 		schedulerControl.setReturnValue(null);
556 		scheduler.getTrigger("myTrigger1", Scheduler.DEFAULT_GROUP);
557 		schedulerControl.setReturnValue(null);
558 		scheduler.addJob(jobDetail0, true);
559 		schedulerControl.setVoidCallable();
560 		scheduler.addJob(jobDetail1, true);
561 		schedulerControl.setVoidCallable();
562 		scheduler.scheduleJob(trigger0);
563 		schedulerControl.setReturnValue(new Date());
564 		scheduler.scheduleJob(trigger1);
565 		schedulerControl.setReturnValue(new Date());
566 		scheduler.start();
567 		schedulerControl.setVoidCallable();
568 		scheduler.shutdown(false);
569 		schedulerControl.setVoidCallable();
570 		schedulerControl.replay();
571 
572 		SchedulerFactoryBean schedulerFactoryBean = new SchedulerFactoryBean() {
573 			protected Scheduler createScheduler(SchedulerFactory schedulerFactory, String schedulerName) {
574 				return scheduler;
575 			}
576 		};
577 		schedulerFactoryBean.setJobFactory(jobFactory);
578 		schedulerFactoryBean.setJobDetails(new JobDetail[] {jobDetail0, jobDetail1});
579 		schedulerFactoryBean.setTriggers(new Trigger[] {trigger0, trigger1});
580 		try {
581 			schedulerFactoryBean.afterPropertiesSet();
582 			schedulerFactoryBean.start();
583 		}
584 		finally {
585 			schedulerFactoryBean.destroy();
586 		}
587 
588 		schedulerControl.verify();
589 	}
590 
591 	@Test
testSchedulerFactoryBeanWithApplicationContext()592 	public void testSchedulerFactoryBeanWithApplicationContext() throws Exception {
593 		TestBean tb = new TestBean("tb", 99);
594 		StaticApplicationContext ac = new StaticApplicationContext();
595 
596 		MockControl schedulerControl = MockControl.createControl(Scheduler.class);
597 		final Scheduler scheduler = (Scheduler) schedulerControl.getMock();
598 		SchedulerContext schedulerContext = new SchedulerContext();
599 		scheduler.getContext();
600 		schedulerControl.setReturnValue(schedulerContext, 4);
601 		scheduler.start();
602 		schedulerControl.setVoidCallable();
603 		scheduler.shutdown(false);
604 		schedulerControl.setVoidCallable();
605 		schedulerControl.replay();
606 
607 		SchedulerFactoryBean schedulerFactoryBean = new SchedulerFactoryBean() {
608 			protected Scheduler createScheduler(SchedulerFactory schedulerFactory, String schedulerName) {
609 				return scheduler;
610 			}
611 		};
612 		schedulerFactoryBean.setJobFactory(null);
613 		Map schedulerContextMap = new HashMap();
614 		schedulerContextMap.put("testBean", tb);
615 		schedulerFactoryBean.setSchedulerContextAsMap(schedulerContextMap);
616 		schedulerFactoryBean.setApplicationContext(ac);
617 		schedulerFactoryBean.setApplicationContextSchedulerContextKey("appCtx");
618 		try {
619 			schedulerFactoryBean.afterPropertiesSet();
620 			schedulerFactoryBean.start();
621 			Scheduler returnedScheduler = (Scheduler) schedulerFactoryBean.getObject();
622 			assertEquals(tb, returnedScheduler.getContext().get("testBean"));
623 			assertEquals(ac, returnedScheduler.getContext().get("appCtx"));
624 		}
625 		finally {
626 			schedulerFactoryBean.destroy();
627 		}
628 
629 		schedulerControl.verify();
630 	}
631 
632 	@Test
testJobDetailBeanWithApplicationContext()633 	public void testJobDetailBeanWithApplicationContext() throws Exception {
634 		TestBean tb = new TestBean("tb", 99);
635 		StaticApplicationContext ac = new StaticApplicationContext();
636 
637 		JobDetailBean jobDetail = new JobDetailBean();
638 		jobDetail.setJobClass(Job.class);
639 		jobDetail.setBeanName("myJob0");
640 		Map jobData = new HashMap();
641 		jobData.put("testBean", tb);
642 		jobDetail.setJobDataAsMap(jobData);
643 		jobDetail.setApplicationContext(ac);
644 		jobDetail.setApplicationContextJobDataKey("appCtx");
645 		jobDetail.afterPropertiesSet();
646 
647 		assertEquals(tb, jobDetail.getJobDataMap().get("testBean"));
648 		assertEquals(ac, jobDetail.getJobDataMap().get("appCtx"));
649 	}
650 
651 	@Test
testMethodInvokingJobDetailFactoryBeanWithListenerNames()652 	public void testMethodInvokingJobDetailFactoryBeanWithListenerNames() throws Exception {
653 		TestMethodInvokingTask task = new TestMethodInvokingTask();
654 		MethodInvokingJobDetailFactoryBean mijdfb = new MethodInvokingJobDetailFactoryBean();
655 		String[] names = new String[] {"test1", "test2"};
656 		mijdfb.setName("myJob1");
657 		mijdfb.setGroup(Scheduler.DEFAULT_GROUP);
658 		mijdfb.setTargetObject(task);
659 		mijdfb.setTargetMethod("doSomething");
660 		mijdfb.setJobListenerNames(names);
661 		mijdfb.afterPropertiesSet();
662 		JobDetail jobDetail = (JobDetail) mijdfb.getObject();
663 		List result = Arrays.asList(jobDetail.getJobListenerNames());
664 		assertEquals(Arrays.asList(names), result);
665 	}
666 
667 	@Test
testJobDetailBeanWithListenerNames()668 	public void testJobDetailBeanWithListenerNames() {
669 		JobDetailBean jobDetail = new JobDetailBean();
670 		String[] names = new String[] {"test1", "test2"};
671 		jobDetail.setJobListenerNames(names);
672 		List result = Arrays.asList(jobDetail.getJobListenerNames());
673 		assertEquals(Arrays.asList(names), result);
674 	}
675 
676 	@Test
testCronTriggerBeanWithListenerNames()677 	public void testCronTriggerBeanWithListenerNames() {
678 		CronTriggerBean trigger = new CronTriggerBean();
679 		String[] names = new String[] {"test1", "test2"};
680 		trigger.setTriggerListenerNames(names);
681 		List result = Arrays.asList(trigger.getTriggerListenerNames());
682 		assertEquals(Arrays.asList(names), result);
683 	}
684 
685 	@Test
testSimpleTriggerBeanWithListenerNames()686 	public void testSimpleTriggerBeanWithListenerNames() {
687 		SimpleTriggerBean trigger = new SimpleTriggerBean();
688 		String[] names = new String[] {"test1", "test2"};
689 		trigger.setTriggerListenerNames(names);
690 		List result = Arrays.asList(trigger.getTriggerListenerNames());
691 		assertEquals(Arrays.asList(names), result);
692 	}
693 
694 	@Test
testSchedulerWithTaskExecutor()695 	public void testSchedulerWithTaskExecutor() throws Exception {
696 		CountingTaskExecutor taskExecutor = new CountingTaskExecutor();
697 		DummyJob.count = 0;
698 
699 		JobDetail jobDetail = new JobDetail();
700 		jobDetail.setJobClass(DummyJob.class);
701 		jobDetail.setName("myJob");
702 
703 		SimpleTriggerBean trigger = new SimpleTriggerBean();
704 		trigger.setName("myTrigger");
705 		trigger.setJobDetail(jobDetail);
706 		trigger.setStartDelay(1);
707 		trigger.setRepeatInterval(500);
708 		trigger.setRepeatCount(1);
709 		trigger.afterPropertiesSet();
710 
711 		SchedulerFactoryBean bean = new SchedulerFactoryBean();
712 		bean.setTaskExecutor(taskExecutor);
713 		bean.setTriggers(new Trigger[] {trigger});
714 		bean.setJobDetails(new JobDetail[] {jobDetail});
715 		bean.afterPropertiesSet();
716 		bean.start();
717 
718 		Thread.sleep(500);
719 		assertTrue(DummyJob.count > 0);
720 		assertEquals(DummyJob.count, taskExecutor.count);
721 
722 		bean.destroy();
723 	}
724 
725 	@Test
testSchedulerWithRunnable()726 	public void testSchedulerWithRunnable() throws Exception {
727 		DummyRunnable.count = 0;
728 
729 		JobDetail jobDetail = new JobDetailBean();
730 		jobDetail.setJobClass(DummyRunnable.class);
731 		jobDetail.setName("myJob");
732 
733 		SimpleTriggerBean trigger = new SimpleTriggerBean();
734 		trigger.setName("myTrigger");
735 		trigger.setJobDetail(jobDetail);
736 		trigger.setStartDelay(1);
737 		trigger.setRepeatInterval(500);
738 		trigger.setRepeatCount(1);
739 		trigger.afterPropertiesSet();
740 
741 		SchedulerFactoryBean bean = new SchedulerFactoryBean();
742 		bean.setTriggers(new Trigger[] {trigger});
743 		bean.setJobDetails(new JobDetail[] {jobDetail});
744 		bean.afterPropertiesSet();
745 		bean.start();
746 
747 		Thread.sleep(500);
748 		assertTrue(DummyRunnable.count > 0);
749 
750 		bean.destroy();
751 	}
752 
753 	@Test
testSchedulerWithQuartzJobBean()754 	public void testSchedulerWithQuartzJobBean() throws Exception {
755 		DummyJob.param = 0;
756 		DummyJob.count = 0;
757 
758 		JobDetail jobDetail = new JobDetail();
759 		jobDetail.setJobClass(DummyJobBean.class);
760 		jobDetail.setName("myJob");
761 		jobDetail.getJobDataMap().put("param", "10");
762 
763 		SimpleTriggerBean trigger = new SimpleTriggerBean();
764 		trigger.setName("myTrigger");
765 		trigger.setJobDetail(jobDetail);
766 		trigger.setStartDelay(1);
767 		trigger.setRepeatInterval(500);
768 		trigger.setRepeatCount(1);
769 		trigger.afterPropertiesSet();
770 
771 		SchedulerFactoryBean bean = new SchedulerFactoryBean();
772 		bean.setTriggers(new Trigger[] {trigger});
773 		bean.setJobDetails(new JobDetail[] {jobDetail});
774 		bean.afterPropertiesSet();
775 		bean.start();
776 
777 		Thread.sleep(500);
778 		assertEquals(10, DummyJobBean.param);
779 		assertTrue(DummyJobBean.count > 0);
780 
781 		bean.destroy();
782 	}
783 
784 	@Test
testSchedulerWithSpringBeanJobFactory()785 	public void testSchedulerWithSpringBeanJobFactory() throws Exception {
786 		DummyJob.param = 0;
787 		DummyJob.count = 0;
788 
789 		JobDetail jobDetail = new JobDetail();
790 		jobDetail.setJobClass(DummyJob.class);
791 		jobDetail.setName("myJob");
792 		jobDetail.getJobDataMap().put("param", "10");
793 		jobDetail.getJobDataMap().put("ignoredParam", "10");
794 
795 		SimpleTriggerBean trigger = new SimpleTriggerBean();
796 		trigger.setName("myTrigger");
797 		trigger.setJobDetail(jobDetail);
798 		trigger.setStartDelay(1);
799 		trigger.setRepeatInterval(500);
800 		trigger.setRepeatCount(1);
801 		trigger.afterPropertiesSet();
802 
803 		SchedulerFactoryBean bean = new SchedulerFactoryBean();
804 		bean.setJobFactory(new SpringBeanJobFactory());
805 		bean.setTriggers(new Trigger[] {trigger});
806 		bean.setJobDetails(new JobDetail[] {jobDetail});
807 		bean.afterPropertiesSet();
808 		bean.start();
809 
810 		Thread.sleep(500);
811 		assertEquals(10, DummyJob.param);
812 		assertTrue(DummyJob.count > 0);
813 
814 		bean.destroy();
815 	}
816 
817 	@Test
testSchedulerWithSpringBeanJobFactoryAndParamMismatchNotIgnored()818 	public void testSchedulerWithSpringBeanJobFactoryAndParamMismatchNotIgnored() throws Exception {
819 		DummyJob.param = 0;
820 		DummyJob.count = 0;
821 
822 		JobDetail jobDetail = new JobDetail();
823 		jobDetail.setJobClass(DummyJob.class);
824 		jobDetail.setName("myJob");
825 		jobDetail.getJobDataMap().put("para", "10");
826 		jobDetail.getJobDataMap().put("ignoredParam", "10");
827 
828 		SimpleTriggerBean trigger = new SimpleTriggerBean();
829 		trigger.setName("myTrigger");
830 		trigger.setJobDetail(jobDetail);
831 		trigger.setStartDelay(1);
832 		trigger.setRepeatInterval(500);
833 		trigger.setRepeatCount(1);
834 		trigger.afterPropertiesSet();
835 
836 		SchedulerFactoryBean bean = new SchedulerFactoryBean();
837 		SpringBeanJobFactory jobFactory = new SpringBeanJobFactory();
838 		jobFactory.setIgnoredUnknownProperties(new String[] {"ignoredParam"});
839 		bean.setJobFactory(jobFactory);
840 		bean.setTriggers(new Trigger[] {trigger});
841 		bean.setJobDetails(new JobDetail[] {jobDetail});
842 		bean.afterPropertiesSet();
843 
844 		Thread.sleep(500);
845 		assertEquals(0, DummyJob.param);
846 		assertTrue(DummyJob.count == 0);
847 
848 		bean.destroy();
849 	}
850 
851 	@Test
testSchedulerWithSpringBeanJobFactoryAndRunnable()852 	public void testSchedulerWithSpringBeanJobFactoryAndRunnable() throws Exception {
853 		DummyRunnable.param = 0;
854 		DummyRunnable.count = 0;
855 
856 		JobDetail jobDetail = new JobDetailBean();
857 		jobDetail.setJobClass(DummyRunnable.class);
858 		jobDetail.setName("myJob");
859 		jobDetail.getJobDataMap().put("param", "10");
860 
861 		SimpleTriggerBean trigger = new SimpleTriggerBean();
862 		trigger.setName("myTrigger");
863 		trigger.setJobDetail(jobDetail);
864 		trigger.setStartDelay(1);
865 		trigger.setRepeatInterval(500);
866 		trigger.setRepeatCount(1);
867 		trigger.afterPropertiesSet();
868 
869 		SchedulerFactoryBean bean = new SchedulerFactoryBean();
870 		bean.setJobFactory(new SpringBeanJobFactory());
871 		bean.setTriggers(new Trigger[] {trigger});
872 		bean.setJobDetails(new JobDetail[] {jobDetail});
873 		bean.afterPropertiesSet();
874 		bean.start();
875 
876 		Thread.sleep(500);
877 		assertEquals(10, DummyRunnable.param);
878 		assertTrue(DummyRunnable.count > 0);
879 
880 		bean.destroy();
881 	}
882 
883 	@Test
testSchedulerWithSpringBeanJobFactoryAndQuartzJobBean()884 	public void testSchedulerWithSpringBeanJobFactoryAndQuartzJobBean() throws Exception {
885 		DummyJobBean.param = 0;
886 		DummyJobBean.count = 0;
887 
888 		JobDetail jobDetail = new JobDetail();
889 		jobDetail.setJobClass(DummyJobBean.class);
890 		jobDetail.setName("myJob");
891 		jobDetail.getJobDataMap().put("param", "10");
892 
893 		SimpleTriggerBean trigger = new SimpleTriggerBean();
894 		trigger.setName("myTrigger");
895 		trigger.setJobDetail(jobDetail);
896 		trigger.setStartDelay(1);
897 		trigger.setRepeatInterval(500);
898 		trigger.setRepeatCount(1);
899 		trigger.afterPropertiesSet();
900 
901 		SchedulerFactoryBean bean = new SchedulerFactoryBean();
902 		bean.setJobFactory(new SpringBeanJobFactory());
903 		bean.setTriggers(new Trigger[] {trigger});
904 		bean.setJobDetails(new JobDetail[] {jobDetail});
905 		bean.afterPropertiesSet();
906 		bean.start();
907 
908 		Thread.sleep(500);
909 		assertEquals(10, DummyJobBean.param);
910 		assertTrue(DummyJobBean.count > 0);
911 
912 		bean.destroy();
913 	}
914 
915 	@Test
testSchedulerWithSpringBeanJobFactoryAndJobSchedulingData()916 	public void testSchedulerWithSpringBeanJobFactoryAndJobSchedulingData() throws Exception {
917 		DummyJob.param = 0;
918 		DummyJob.count = 0;
919 
920 		SchedulerFactoryBean bean = new SchedulerFactoryBean();
921 		bean.setJobFactory(new SpringBeanJobFactory());
922 		bean.setJobSchedulingDataLocation("org/springframework/scheduling/quartz/job-scheduling-data.xml");
923 		bean.setResourceLoader(new FileSystemResourceLoader());
924 		bean.afterPropertiesSet();
925 		bean.start();
926 
927 		Thread.sleep(500);
928 		assertEquals(10, DummyJob.param);
929 		assertTrue(DummyJob.count > 0);
930 
931 		bean.destroy();
932 	}
933 
934 	/**
935 	 * Tests the creation of multiple schedulers (SPR-772)
936 	 */
937 	@Test
testMultipleSchedulers()938 	public void testMultipleSchedulers() throws Exception {
939 		ClassPathXmlApplicationContext ctx =
940 				new ClassPathXmlApplicationContext("/org/springframework/scheduling/quartz/multipleSchedulers.xml");
941 		try {
942 			Scheduler scheduler1 = (Scheduler) ctx.getBean("scheduler1");
943 			Scheduler scheduler2 = (Scheduler) ctx.getBean("scheduler2");
944 			assertNotSame(scheduler1, scheduler2);
945 			assertEquals("quartz1", scheduler1.getSchedulerName());
946 			assertEquals("quartz2", scheduler2.getSchedulerName());
947 		}
948 		finally {
949 			ctx.close();
950 		}
951 	}
952 
953 	@Test
testWithTwoAnonymousMethodInvokingJobDetailFactoryBeans()954 	public void testWithTwoAnonymousMethodInvokingJobDetailFactoryBeans() throws InterruptedException {
955 		ClassPathXmlApplicationContext ctx =
956 				new ClassPathXmlApplicationContext("/org/springframework/scheduling/quartz/multipleAnonymousMethodInvokingJobDetailFB.xml");
957 		Thread.sleep(3000);
958 		try {
959 			QuartzTestBean exportService = (QuartzTestBean) ctx.getBean("exportService");
960 			QuartzTestBean importService = (QuartzTestBean) ctx.getBean("importService");
961 
962 			assertEquals("doImport called exportService", 0, exportService.getImportCount());
963 			assertEquals("doExport not called on exportService", 2, exportService.getExportCount());
964 			assertEquals("doImport not called on importService", 2, importService.getImportCount());
965 			assertEquals("doExport called on importService", 0, importService.getExportCount());
966 		}
967 		finally {
968 			ctx.close();
969 		}
970 	}
971 
972 	@Test
testSchedulerAccessorBean()973 	public void testSchedulerAccessorBean() throws InterruptedException {
974 		ClassPathXmlApplicationContext ctx =
975 				new ClassPathXmlApplicationContext("/org/springframework/scheduling/quartz/schedulerAccessorBean.xml");
976 		Thread.sleep(3000);
977 		try {
978 			QuartzTestBean exportService = (QuartzTestBean) ctx.getBean("exportService");
979 			QuartzTestBean importService = (QuartzTestBean) ctx.getBean("importService");
980 
981 			assertEquals("doImport called exportService", 0, exportService.getImportCount());
982 			assertEquals("doExport not called on exportService", 2, exportService.getExportCount());
983 			assertEquals("doImport not called on importService", 2, importService.getImportCount());
984 			assertEquals("doExport called on importService", 0, importService.getExportCount());
985 		}
986 		finally {
987 			ctx.close();
988 		}
989 	}
990 
991 	@Test
testSchedulerAutoStartsOnContextRefreshedEventByDefault()992 	public void testSchedulerAutoStartsOnContextRefreshedEventByDefault() throws Exception {
993 		StaticApplicationContext context = new StaticApplicationContext();
994 		context.registerBeanDefinition("scheduler", new RootBeanDefinition(SchedulerFactoryBean.class));
995 		Scheduler bean = context.getBean("scheduler", Scheduler.class);
996 		assertFalse(bean.isStarted());
997 		context.refresh();
998 		assertTrue(bean.isStarted());
999 	}
1000 
1001 	@Test
testSchedulerAutoStartupFalse()1002 	public void testSchedulerAutoStartupFalse() throws Exception {
1003 		StaticApplicationContext context = new StaticApplicationContext();
1004 		BeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition(
1005 				SchedulerFactoryBean.class).addPropertyValue("autoStartup", false).getBeanDefinition();
1006 		context.registerBeanDefinition("scheduler", beanDefinition);
1007 		Scheduler bean = context.getBean("scheduler", Scheduler.class);
1008 		assertFalse(bean.isStarted());
1009 		context.refresh();
1010 		assertFalse(bean.isStarted());
1011 	}
1012 
1013 	@Test
testSchedulerRepositoryExposure()1014 	public void testSchedulerRepositoryExposure() throws InterruptedException {
1015 		ClassPathXmlApplicationContext ctx =
1016 				new ClassPathXmlApplicationContext("/org/springframework/scheduling/quartz/schedulerRepositoryExposure.xml");
1017 		assertSame(SchedulerRepository.getInstance().lookup("myScheduler"), ctx.getBean("scheduler"));
1018 		ctx.close();
1019 	}
1020 
1021 	// SPR-6038: detect HSQL and stop illegal locks being taken
1022 	@Test
testSchedulerWithHsqlDataSource()1023 	public void testSchedulerWithHsqlDataSource() throws Exception {
1024 		DummyJob.param = 0;
1025 		DummyJob.count = 0;
1026 
1027 		ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext(
1028 				"/org/springframework/scheduling/quartz/databasePersistence.xml");
1029 		SimpleJdbcTemplate jdbcTemplate = new SimpleJdbcTemplate(ctx.getBean(DataSource.class));
1030 		assertTrue("No triggers were persisted", jdbcTemplate.queryForList("SELECT * FROM qrtz_triggers").size()>0);
1031 		Thread.sleep(3000);
1032 		try {
1033 			// assertEquals(10, DummyJob.param);
1034 			assertTrue(DummyJob.count > 0);
1035 		} finally {
1036 			ctx.close();
1037 		}
1038 
1039 	}
1040 
1041 	private static class TestSchedulerListener implements SchedulerListener {
1042 
jobScheduled(Trigger trigger)1043 		public void jobScheduled(Trigger trigger) {
1044 		}
1045 
jobUnscheduled(String triggerName, String triggerGroup)1046 		public void jobUnscheduled(String triggerName, String triggerGroup) {
1047 		}
1048 
triggerFinalized(Trigger trigger)1049 		public void triggerFinalized(Trigger trigger) {
1050 		}
1051 
triggersPaused(String triggerName, String triggerGroup)1052 		public void triggersPaused(String triggerName, String triggerGroup) {
1053 		}
1054 
triggersResumed(String triggerName, String triggerGroup)1055 		public void triggersResumed(String triggerName, String triggerGroup) {
1056 		}
1057 
jobsPaused(String jobName, String jobGroup)1058 		public void jobsPaused(String jobName, String jobGroup) {
1059 		}
1060 
jobsResumed(String jobName, String jobGroup)1061 		public void jobsResumed(String jobName, String jobGroup) {
1062 		}
1063 
schedulerError(String msg, SchedulerException cause)1064 		public void schedulerError(String msg, SchedulerException cause) {
1065 		}
1066 
schedulerShutdown()1067 		public void schedulerShutdown() {
1068 		}
1069 	}
1070 
1071 
1072 	private static class TestJobListener implements JobListener {
1073 
getName()1074 		public String getName() {
1075 			return null;
1076 		}
1077 
jobToBeExecuted(JobExecutionContext context)1078 		public void jobToBeExecuted(JobExecutionContext context) {
1079 		}
1080 
jobExecutionVetoed(JobExecutionContext context)1081 		public void jobExecutionVetoed(JobExecutionContext context) {
1082 		}
1083 
jobWasExecuted(JobExecutionContext context, JobExecutionException jobException)1084 		public void jobWasExecuted(JobExecutionContext context, JobExecutionException jobException) {
1085 		}
1086 	}
1087 
1088 
1089 	private static class TestTriggerListener implements TriggerListener {
1090 
getName()1091 		public String getName() {
1092 			return null;
1093 		}
1094 
triggerFired(Trigger trigger, JobExecutionContext context)1095 		public void triggerFired(Trigger trigger, JobExecutionContext context) {
1096 		}
1097 
vetoJobExecution(Trigger trigger, JobExecutionContext context)1098 		public boolean vetoJobExecution(Trigger trigger, JobExecutionContext context) {
1099 			return false;
1100 		}
1101 
triggerMisfired(Trigger trigger)1102 		public void triggerMisfired(Trigger trigger) {
1103 		}
1104 
triggerComplete(Trigger trigger, JobExecutionContext context, int triggerInstructionCode)1105 		public void triggerComplete(Trigger trigger, JobExecutionContext context, int triggerInstructionCode) {
1106 		}
1107 	}
1108 
1109 
1110 	public static class CountingTaskExecutor implements TaskExecutor {
1111 
1112 		private int count;
1113 
execute(Runnable task)1114 		public void execute(Runnable task) {
1115 			this.count++;
1116 			task.run();
1117 		}
1118 	}
1119 
1120 
1121 	public static class DummyJob implements Job {
1122 
1123 		private static int param;
1124 
1125 		private static int count;
1126 
setParam(int value)1127 		public void setParam(int value) {
1128 			if (param > 0) {
1129 				throw new IllegalStateException("Param already set");
1130 			}
1131 			param = value;
1132 		}
1133 
execute(JobExecutionContext jobExecutionContext)1134 		public synchronized void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
1135 			count++;
1136 		}
1137 	}
1138 
1139 
1140 	public static class DummyJobBean extends QuartzJobBean {
1141 
1142 		private static int param;
1143 
1144 		private static int count;
1145 
setParam(int value)1146 		public void setParam(int value) {
1147 			if (param > 0) {
1148 				throw new IllegalStateException("Param already set");
1149 			}
1150 			param = value;
1151 		}
1152 
executeInternal(JobExecutionContext jobExecutionContext)1153 		protected synchronized void executeInternal(JobExecutionContext jobExecutionContext) throws JobExecutionException {
1154 			count++;
1155 		}
1156 	}
1157 
1158 
1159 	public static class DummyRunnable implements Runnable {
1160 
1161 		private static int param;
1162 
1163 		private static int count;
1164 
setParam(int value)1165 		public void setParam(int value) {
1166 			if (param > 0) {
1167 				throw new IllegalStateException("Param already set");
1168 			}
1169 			param = value;
1170 		}
1171 
run()1172 		public void run() {
1173 			count++;
1174 		}
1175 	}
1176 
1177 }
1178