/* * Copyright 2002-2008 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.scheduling.quartz; import java.util.Arrays; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; import junit.framework.TestCase; import org.easymock.MockControl; import org.quartz.CronTrigger; import org.quartz.Job; import org.quartz.JobDetail; import org.quartz.JobExecutionContext; import org.quartz.JobExecutionException; import org.quartz.JobListener; import org.quartz.ObjectAlreadyExistsException; import org.quartz.Scheduler; import org.quartz.SchedulerContext; import org.quartz.SchedulerException; import org.quartz.SchedulerFactory; import org.quartz.SchedulerListener; import org.quartz.SimpleTrigger; import org.quartz.Trigger; import org.quartz.TriggerListener; import org.quartz.impl.SchedulerRepository; import org.quartz.spi.JobFactory; import org.springframework.beans.TestBean; import org.springframework.beans.factory.support.StaticListableBeanFactory; import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.context.support.StaticApplicationContext; import org.springframework.core.io.FileSystemResourceLoader; import org.springframework.core.task.TaskExecutor; import org.springframework.scheduling.TestMethodInvokingTask; /** * @author Juergen Hoeller * @author Alef Arendsen * @author Rob Harrop * @since 20.02.2004 */ public class QuartzSupportTests extends TestCase { public void testSchedulerFactoryBean() throws Exception { doTestSchedulerFactoryBean(false, false); } public void testSchedulerFactoryBeanWithExplicitJobDetail() throws Exception { doTestSchedulerFactoryBean(true, false); } public void testSchedulerFactoryBeanWithPrototypeJob() throws Exception { doTestSchedulerFactoryBean(false, true); } private void doTestSchedulerFactoryBean(boolean explicitJobDetail, boolean prototypeJob) throws Exception { TestBean tb = new TestBean("tb", 99); JobDetailBean jobDetail0 = new JobDetailBean(); jobDetail0.setJobClass(Job.class); jobDetail0.setBeanName("myJob0"); Map jobData = new HashMap(); jobData.put("testBean", tb); jobDetail0.setJobDataAsMap(jobData); jobDetail0.afterPropertiesSet(); assertEquals(tb, jobDetail0.getJobDataMap().get("testBean")); CronTriggerBean trigger0 = new CronTriggerBean(); trigger0.setBeanName("myTrigger0"); trigger0.setJobDetail(jobDetail0); trigger0.setCronExpression("0/1 * * * * ?"); trigger0.afterPropertiesSet(); TestMethodInvokingTask task1 = new TestMethodInvokingTask(); MethodInvokingJobDetailFactoryBean mijdfb = new MethodInvokingJobDetailFactoryBean(); mijdfb.setBeanName("myJob1"); if (prototypeJob) { StaticListableBeanFactory beanFactory = new StaticListableBeanFactory(); beanFactory.addBean("task", task1); mijdfb.setTargetBeanName("task"); mijdfb.setBeanFactory(beanFactory); } else { mijdfb.setTargetObject(task1); } mijdfb.setTargetMethod("doSomething"); mijdfb.afterPropertiesSet(); JobDetail jobDetail1 = (JobDetail) mijdfb.getObject(); SimpleTriggerBean trigger1 = new SimpleTriggerBean(); trigger1.setBeanName("myTrigger1"); trigger1.setJobDetail(jobDetail1); trigger1.setStartDelay(0); trigger1.setRepeatInterval(20); trigger1.afterPropertiesSet(); MockControl schedulerControl = MockControl.createControl(Scheduler.class); final Scheduler scheduler = (Scheduler) schedulerControl.getMock(); scheduler.getContext(); schedulerControl.setReturnValue(new SchedulerContext()); scheduler.getJobDetail("myJob0", Scheduler.DEFAULT_GROUP); schedulerControl.setReturnValue(null); scheduler.getJobDetail("myJob1", Scheduler.DEFAULT_GROUP); schedulerControl.setReturnValue(null); scheduler.getTrigger("myTrigger0", Scheduler.DEFAULT_GROUP); schedulerControl.setReturnValue(null); scheduler.getTrigger("myTrigger1", Scheduler.DEFAULT_GROUP); schedulerControl.setReturnValue(null); scheduler.addJob(jobDetail0, true); schedulerControl.setVoidCallable(); scheduler.scheduleJob(trigger0); schedulerControl.setReturnValue(new Date()); scheduler.addJob(jobDetail1, true); schedulerControl.setVoidCallable(); scheduler.scheduleJob(trigger1); schedulerControl.setReturnValue(new Date()); scheduler.start(); schedulerControl.setVoidCallable(); scheduler.shutdown(false); schedulerControl.setVoidCallable(); schedulerControl.replay(); SchedulerFactoryBean schedulerFactoryBean = new SchedulerFactoryBean() { protected Scheduler createScheduler(SchedulerFactory schedulerFactory, String schedulerName) { return scheduler; } }; schedulerFactoryBean.setJobFactory(null); Map schedulerContext = new HashMap(); schedulerContext.put("otherTestBean", tb); schedulerFactoryBean.setSchedulerContextAsMap(schedulerContext); if (explicitJobDetail) { schedulerFactoryBean.setJobDetails(new JobDetail[] {jobDetail0}); } schedulerFactoryBean.setTriggers(new Trigger[] {trigger0, trigger1}); try { schedulerFactoryBean.afterPropertiesSet(); } finally { schedulerFactoryBean.destroy(); } schedulerControl.verify(); } public void testSchedulerFactoryBeanWithExistingJobs() throws Exception { doTestSchedulerFactoryBeanWithExistingJobs(false); } public void testSchedulerFactoryBeanWithOverwriteExistingJobs() throws Exception { doTestSchedulerFactoryBeanWithExistingJobs(true); } private void doTestSchedulerFactoryBeanWithExistingJobs(boolean overwrite) throws Exception { TestBean tb = new TestBean("tb", 99); JobDetailBean jobDetail0 = new JobDetailBean(); jobDetail0.setJobClass(Job.class); jobDetail0.setBeanName("myJob0"); Map jobData = new HashMap(); jobData.put("testBean", tb); jobDetail0.setJobDataAsMap(jobData); jobDetail0.afterPropertiesSet(); assertEquals(tb, jobDetail0.getJobDataMap().get("testBean")); CronTriggerBean trigger0 = new CronTriggerBean(); trigger0.setBeanName("myTrigger0"); trigger0.setJobDetail(jobDetail0); trigger0.setCronExpression("0/1 * * * * ?"); trigger0.afterPropertiesSet(); TestMethodInvokingTask task1 = new TestMethodInvokingTask(); MethodInvokingJobDetailFactoryBean mijdfb = new MethodInvokingJobDetailFactoryBean(); mijdfb.setBeanName("myJob1"); mijdfb.setTargetObject(task1); mijdfb.setTargetMethod("doSomething"); mijdfb.afterPropertiesSet(); JobDetail jobDetail1 = (JobDetail) mijdfb.getObject(); SimpleTriggerBean trigger1 = new SimpleTriggerBean(); trigger1.setBeanName("myTrigger1"); trigger1.setJobDetail(jobDetail1); trigger1.setStartDelay(0); trigger1.setRepeatInterval(20); trigger1.afterPropertiesSet(); MockControl schedulerControl = MockControl.createControl(Scheduler.class); final Scheduler scheduler = (Scheduler) schedulerControl.getMock(); scheduler.getContext(); schedulerControl.setReturnValue(new SchedulerContext()); scheduler.getTrigger("myTrigger0", Scheduler.DEFAULT_GROUP); schedulerControl.setReturnValue(null); scheduler.getTrigger("myTrigger1", Scheduler.DEFAULT_GROUP); schedulerControl.setReturnValue(new SimpleTrigger()); if (overwrite) { scheduler.addJob(jobDetail1, true); schedulerControl.setVoidCallable(); scheduler.rescheduleJob("myTrigger1", Scheduler.DEFAULT_GROUP, trigger1); schedulerControl.setReturnValue(new Date()); } else { scheduler.getJobDetail("myJob0", Scheduler.DEFAULT_GROUP); schedulerControl.setReturnValue(null); } scheduler.addJob(jobDetail0, true); schedulerControl.setVoidCallable(); scheduler.scheduleJob(trigger0); schedulerControl.setReturnValue(new Date()); scheduler.start(); schedulerControl.setVoidCallable(); scheduler.shutdown(false); schedulerControl.setVoidCallable(); schedulerControl.replay(); SchedulerFactoryBean schedulerFactoryBean = new SchedulerFactoryBean() { protected Scheduler createScheduler(SchedulerFactory schedulerFactory, String schedulerName) { return scheduler; } }; schedulerFactoryBean.setJobFactory(null); Map schedulerContext = new HashMap(); schedulerContext.put("otherTestBean", tb); schedulerFactoryBean.setSchedulerContextAsMap(schedulerContext); schedulerFactoryBean.setTriggers(new Trigger[] {trigger0, trigger1}); if (overwrite) { schedulerFactoryBean.setOverwriteExistingJobs(true); } try { schedulerFactoryBean.afterPropertiesSet(); } finally { schedulerFactoryBean.destroy(); } schedulerControl.verify(); } public void testSchedulerFactoryBeanWithExistingJobsAndRaceCondition() throws Exception { doTestSchedulerFactoryBeanWithExistingJobsAndRaceCondition(false); } public void testSchedulerFactoryBeanWithOverwriteExistingJobsAndRaceCondition() throws Exception { doTestSchedulerFactoryBeanWithExistingJobsAndRaceCondition(true); } private void doTestSchedulerFactoryBeanWithExistingJobsAndRaceCondition(boolean overwrite) throws Exception { TestBean tb = new TestBean("tb", 99); JobDetailBean jobDetail0 = new JobDetailBean(); jobDetail0.setJobClass(Job.class); jobDetail0.setBeanName("myJob0"); Map jobData = new HashMap(); jobData.put("testBean", tb); jobDetail0.setJobDataAsMap(jobData); jobDetail0.afterPropertiesSet(); assertEquals(tb, jobDetail0.getJobDataMap().get("testBean")); CronTriggerBean trigger0 = new CronTriggerBean(); trigger0.setBeanName("myTrigger0"); trigger0.setJobDetail(jobDetail0); trigger0.setCronExpression("0/1 * * * * ?"); trigger0.afterPropertiesSet(); TestMethodInvokingTask task1 = new TestMethodInvokingTask(); MethodInvokingJobDetailFactoryBean mijdfb = new MethodInvokingJobDetailFactoryBean(); mijdfb.setBeanName("myJob1"); mijdfb.setTargetObject(task1); mijdfb.setTargetMethod("doSomething"); mijdfb.afterPropertiesSet(); JobDetail jobDetail1 = (JobDetail) mijdfb.getObject(); SimpleTriggerBean trigger1 = new SimpleTriggerBean(); trigger1.setBeanName("myTrigger1"); trigger1.setJobDetail(jobDetail1); trigger1.setStartDelay(0); trigger1.setRepeatInterval(20); trigger1.afterPropertiesSet(); MockControl schedulerControl = MockControl.createControl(Scheduler.class); final Scheduler scheduler = (Scheduler) schedulerControl.getMock(); scheduler.getContext(); schedulerControl.setReturnValue(new SchedulerContext()); scheduler.getTrigger("myTrigger0", Scheduler.DEFAULT_GROUP); schedulerControl.setReturnValue(null); scheduler.getTrigger("myTrigger1", Scheduler.DEFAULT_GROUP); schedulerControl.setReturnValue(new SimpleTrigger()); if (overwrite) { scheduler.addJob(jobDetail1, true); schedulerControl.setVoidCallable(); scheduler.rescheduleJob("myTrigger1", Scheduler.DEFAULT_GROUP, trigger1); schedulerControl.setReturnValue(new Date()); } else { scheduler.getJobDetail("myJob0", Scheduler.DEFAULT_GROUP); schedulerControl.setReturnValue(null); } scheduler.addJob(jobDetail0, true); schedulerControl.setVoidCallable(); scheduler.scheduleJob(trigger0); schedulerControl.setThrowable(new ObjectAlreadyExistsException("")); if (overwrite) { scheduler.rescheduleJob("myTrigger0", Scheduler.DEFAULT_GROUP, trigger0); schedulerControl.setReturnValue(new Date()); } scheduler.start(); schedulerControl.setVoidCallable(); scheduler.shutdown(false); schedulerControl.setVoidCallable(); schedulerControl.replay(); SchedulerFactoryBean schedulerFactoryBean = new SchedulerFactoryBean() { protected Scheduler createScheduler(SchedulerFactory schedulerFactory, String schedulerName) { return scheduler; } }; schedulerFactoryBean.setJobFactory(null); Map schedulerContext = new HashMap(); schedulerContext.put("otherTestBean", tb); schedulerFactoryBean.setSchedulerContextAsMap(schedulerContext); schedulerFactoryBean.setTriggers(new Trigger[] {trigger0, trigger1}); if (overwrite) { schedulerFactoryBean.setOverwriteExistingJobs(true); } try { schedulerFactoryBean.afterPropertiesSet(); } finally { schedulerFactoryBean.destroy(); } schedulerControl.verify(); } public void testSchedulerFactoryBeanWithListeners() throws Exception { JobFactory jobFactory = new AdaptableJobFactory(); MockControl schedulerControl = MockControl.createControl(Scheduler.class); final Scheduler scheduler = (Scheduler) schedulerControl.getMock(); SchedulerListener schedulerListener = new TestSchedulerListener(); JobListener globalJobListener = new TestJobListener(); JobListener jobListener = new TestJobListener(); TriggerListener globalTriggerListener = new TestTriggerListener(); TriggerListener triggerListener = new TestTriggerListener(); scheduler.setJobFactory(jobFactory); schedulerControl.setVoidCallable(); scheduler.addSchedulerListener(schedulerListener); schedulerControl.setVoidCallable(); scheduler.addGlobalJobListener(globalJobListener); schedulerControl.setVoidCallable(); scheduler.addJobListener(jobListener); schedulerControl.setVoidCallable(); scheduler.addGlobalTriggerListener(globalTriggerListener); schedulerControl.setVoidCallable(); scheduler.addTriggerListener(triggerListener); schedulerControl.setVoidCallable(); scheduler.start(); schedulerControl.setVoidCallable(); scheduler.shutdown(false); schedulerControl.setVoidCallable(); schedulerControl.replay(); SchedulerFactoryBean schedulerFactoryBean = new SchedulerFactoryBean() { protected Scheduler createScheduler(SchedulerFactory schedulerFactory, String schedulerName) { return scheduler; } }; schedulerFactoryBean.setJobFactory(jobFactory); schedulerFactoryBean.setSchedulerListeners(new SchedulerListener[] {schedulerListener}); schedulerFactoryBean.setGlobalJobListeners(new JobListener[] {globalJobListener}); schedulerFactoryBean.setJobListeners(new JobListener[] {jobListener}); schedulerFactoryBean.setGlobalTriggerListeners(new TriggerListener[] {globalTriggerListener}); schedulerFactoryBean.setTriggerListeners(new TriggerListener[] {triggerListener}); try { schedulerFactoryBean.afterPropertiesSet(); } finally { schedulerFactoryBean.destroy(); } schedulerControl.verify(); } /*public void testMethodInvocationWithConcurrency() throws Exception { methodInvokingConcurrency(true); }*/ // We can't test both since Quartz somehow seems to keep things in memory // enable both and one of them will fail (order doesn't matter). /*public void testMethodInvocationWithoutConcurrency() throws Exception { methodInvokingConcurrency(false); }*/ private void methodInvokingConcurrency(boolean concurrent) throws Exception { // Test the concurrency flag. // Method invoking job with two triggers. // If the concurrent flag is false, the triggers are NOT allowed // to interfere with each other. TestMethodInvokingTask task1 = new TestMethodInvokingTask(); MethodInvokingJobDetailFactoryBean mijdfb = new MethodInvokingJobDetailFactoryBean(); // set the concurrency flag! mijdfb.setConcurrent(concurrent); mijdfb.setBeanName("myJob1"); mijdfb.setTargetObject(task1); mijdfb.setTargetMethod("doWait"); mijdfb.afterPropertiesSet(); JobDetail jobDetail1 = (JobDetail) mijdfb.getObject(); SimpleTriggerBean trigger0 = new SimpleTriggerBean(); trigger0.setBeanName("myTrigger1"); trigger0.setJobDetail(jobDetail1); trigger0.setStartDelay(0); trigger0.setRepeatInterval(1); trigger0.setRepeatCount(1); trigger0.afterPropertiesSet(); SimpleTriggerBean trigger1 = new SimpleTriggerBean(); trigger1.setBeanName("myTrigger1"); trigger1.setJobDetail(jobDetail1); trigger1.setStartDelay(1000L); trigger1.setRepeatInterval(1); trigger1.setRepeatCount(1); trigger1.afterPropertiesSet(); SchedulerFactoryBean schedulerFactoryBean = new SchedulerFactoryBean(); schedulerFactoryBean.setJobDetails(new JobDetail[] {jobDetail1}); schedulerFactoryBean.setTriggers(new Trigger[] {trigger1, trigger0}); schedulerFactoryBean.afterPropertiesSet(); // ok scheduler is set up... let's wait for like 4 seconds try { Thread.sleep(4000); } catch (InterruptedException ex) { // fall through } if (concurrent) { assertEquals(2, task1.counter); task1.stop(); // we're done, both jobs have ran, let's call it a day return; } else { assertEquals(1, task1.counter); task1.stop(); // we need to check whether or not the test succeed with non-concurrent jobs } try { Thread.sleep(4000); } catch (InterruptedException ex) { // fall through } task1.stop(); assertEquals(2, task1.counter); // Although we're destroying the scheduler, it does seem to keep things in memory: // When executing both tests (concurrent and non-concurrent), the second test always // fails. schedulerFactoryBean.destroy(); } public void testSchedulerFactoryBeanWithPlainQuartzObjects() throws Exception { JobFactory jobFactory = new AdaptableJobFactory(); TestBean tb = new TestBean("tb", 99); JobDetail jobDetail0 = new JobDetail(); jobDetail0.setJobClass(Job.class); jobDetail0.setName("myJob0"); jobDetail0.setGroup(Scheduler.DEFAULT_GROUP); jobDetail0.getJobDataMap().put("testBean", tb); assertEquals(tb, jobDetail0.getJobDataMap().get("testBean")); CronTrigger trigger0 = new CronTrigger(); trigger0.setName("myTrigger0"); trigger0.setGroup(Scheduler.DEFAULT_GROUP); trigger0.setJobName("myJob0"); trigger0.setJobGroup(Scheduler.DEFAULT_GROUP); trigger0.setStartTime(new Date()); trigger0.setCronExpression("0/1 * * * * ?"); TestMethodInvokingTask task1 = new TestMethodInvokingTask(); MethodInvokingJobDetailFactoryBean mijdfb = new MethodInvokingJobDetailFactoryBean(); mijdfb.setName("myJob1"); mijdfb.setGroup(Scheduler.DEFAULT_GROUP); mijdfb.setTargetObject(task1); mijdfb.setTargetMethod("doSomething"); mijdfb.afterPropertiesSet(); JobDetail jobDetail1 = (JobDetail) mijdfb.getObject(); SimpleTrigger trigger1 = new SimpleTrigger(); trigger1.setName("myTrigger1"); trigger1.setGroup(Scheduler.DEFAULT_GROUP); trigger1.setJobName("myJob1"); trigger1.setJobGroup(Scheduler.DEFAULT_GROUP); trigger1.setStartTime(new Date()); trigger1.setRepeatCount(SimpleTrigger.REPEAT_INDEFINITELY); trigger1.setRepeatInterval(20); MockControl schedulerControl = MockControl.createControl(Scheduler.class); final Scheduler scheduler = (Scheduler) schedulerControl.getMock(); scheduler.setJobFactory(jobFactory); schedulerControl.setVoidCallable(); scheduler.getJobDetail("myJob0", Scheduler.DEFAULT_GROUP); schedulerControl.setReturnValue(null); scheduler.getJobDetail("myJob1", Scheduler.DEFAULT_GROUP); schedulerControl.setReturnValue(null); scheduler.getTrigger("myTrigger0", Scheduler.DEFAULT_GROUP); schedulerControl.setReturnValue(null); scheduler.getTrigger("myTrigger1", Scheduler.DEFAULT_GROUP); schedulerControl.setReturnValue(null); scheduler.addJob(jobDetail0, true); schedulerControl.setVoidCallable(); scheduler.addJob(jobDetail1, true); schedulerControl.setVoidCallable(); scheduler.scheduleJob(trigger0); schedulerControl.setReturnValue(new Date()); scheduler.scheduleJob(trigger1); schedulerControl.setReturnValue(new Date()); scheduler.start(); schedulerControl.setVoidCallable(); scheduler.shutdown(false); schedulerControl.setVoidCallable(); schedulerControl.replay(); SchedulerFactoryBean schedulerFactoryBean = new SchedulerFactoryBean() { protected Scheduler createScheduler(SchedulerFactory schedulerFactory, String schedulerName) { return scheduler; } }; schedulerFactoryBean.setJobFactory(jobFactory); schedulerFactoryBean.setJobDetails(new JobDetail[] {jobDetail0, jobDetail1}); schedulerFactoryBean.setTriggers(new Trigger[] {trigger0, trigger1}); try { schedulerFactoryBean.afterPropertiesSet(); } finally { schedulerFactoryBean.destroy(); } schedulerControl.verify(); } public void testSchedulerFactoryBeanWithApplicationContext() throws Exception { TestBean tb = new TestBean("tb", 99); StaticApplicationContext ac = new StaticApplicationContext(); MockControl schedulerControl = MockControl.createControl(Scheduler.class); final Scheduler scheduler = (Scheduler) schedulerControl.getMock(); SchedulerContext schedulerContext = new SchedulerContext(); scheduler.getContext(); schedulerControl.setReturnValue(schedulerContext, 4); scheduler.start(); schedulerControl.setVoidCallable(); scheduler.shutdown(false); schedulerControl.setVoidCallable(); schedulerControl.replay(); SchedulerFactoryBean schedulerFactoryBean = new SchedulerFactoryBean() { protected Scheduler createScheduler(SchedulerFactory schedulerFactory, String schedulerName) { return scheduler; } }; schedulerFactoryBean.setJobFactory(null); Map schedulerContextMap = new HashMap(); schedulerContextMap.put("testBean", tb); schedulerFactoryBean.setSchedulerContextAsMap(schedulerContextMap); schedulerFactoryBean.setApplicationContext(ac); schedulerFactoryBean.setApplicationContextSchedulerContextKey("appCtx"); try { schedulerFactoryBean.afterPropertiesSet(); Scheduler returnedScheduler = (Scheduler) schedulerFactoryBean.getObject(); assertEquals(tb, returnedScheduler.getContext().get("testBean")); assertEquals(ac, returnedScheduler.getContext().get("appCtx")); } finally { schedulerFactoryBean.destroy(); } schedulerControl.verify(); } public void testJobDetailBeanWithApplicationContext() throws Exception { TestBean tb = new TestBean("tb", 99); StaticApplicationContext ac = new StaticApplicationContext(); JobDetailBean jobDetail = new JobDetailBean(); jobDetail.setJobClass(Job.class); jobDetail.setBeanName("myJob0"); Map jobData = new HashMap(); jobData.put("testBean", tb); jobDetail.setJobDataAsMap(jobData); jobDetail.setApplicationContext(ac); jobDetail.setApplicationContextJobDataKey("appCtx"); jobDetail.afterPropertiesSet(); assertEquals(tb, jobDetail.getJobDataMap().get("testBean")); assertEquals(ac, jobDetail.getJobDataMap().get("appCtx")); } public void testMethodInvokingJobDetailFactoryBeanWithListenerNames() throws Exception { TestMethodInvokingTask task = new TestMethodInvokingTask(); MethodInvokingJobDetailFactoryBean mijdfb = new MethodInvokingJobDetailFactoryBean(); String[] names = new String[] {"test1", "test2"}; mijdfb.setName("myJob1"); mijdfb.setGroup(Scheduler.DEFAULT_GROUP); mijdfb.setTargetObject(task); mijdfb.setTargetMethod("doSomething"); mijdfb.setJobListenerNames(names); mijdfb.afterPropertiesSet(); JobDetail jobDetail = (JobDetail) mijdfb.getObject(); List result = Arrays.asList(jobDetail.getJobListenerNames()); assertEquals(Arrays.asList(names), result); } public void testJobDetailBeanWithListenerNames() { JobDetailBean jobDetail = new JobDetailBean(); String[] names = new String[] {"test1", "test2"}; jobDetail.setJobListenerNames(names); List result = Arrays.asList(jobDetail.getJobListenerNames()); assertEquals(Arrays.asList(names), result); } public void testCronTriggerBeanWithListenerNames() { CronTriggerBean trigger = new CronTriggerBean(); String[] names = new String[] {"test1", "test2"}; trigger.setTriggerListenerNames(names); List result = Arrays.asList(trigger.getTriggerListenerNames()); assertEquals(Arrays.asList(names), result); } public void testSimpleTriggerBeanWithListenerNames() { SimpleTriggerBean trigger = new SimpleTriggerBean(); String[] names = new String[] {"test1", "test2"}; trigger.setTriggerListenerNames(names); List result = Arrays.asList(trigger.getTriggerListenerNames()); assertEquals(Arrays.asList(names), result); } public void testSchedulerWithTaskExecutor() throws Exception { CountingTaskExecutor taskExecutor = new CountingTaskExecutor(); DummyJob.count = 0; JobDetail jobDetail = new JobDetail(); jobDetail.setJobClass(DummyJob.class); jobDetail.setName("myJob"); SimpleTriggerBean trigger = new SimpleTriggerBean(); trigger.setName("myTrigger"); trigger.setJobDetail(jobDetail); trigger.setStartDelay(1); trigger.setRepeatInterval(500); trigger.setRepeatCount(1); trigger.afterPropertiesSet(); SchedulerFactoryBean bean = new SchedulerFactoryBean(); bean.setTaskExecutor(taskExecutor); bean.setTriggers(new Trigger[] {trigger}); bean.setJobDetails(new JobDetail[] {jobDetail}); bean.afterPropertiesSet(); Thread.sleep(500); assertTrue(DummyJob.count > 0); assertEquals(DummyJob.count, taskExecutor.count); bean.destroy(); } public void testSchedulerWithRunnable() throws Exception { DummyRunnable.count = 0; JobDetail jobDetail = new JobDetailBean(); jobDetail.setJobClass(DummyRunnable.class); jobDetail.setName("myJob"); SimpleTriggerBean trigger = new SimpleTriggerBean(); trigger.setName("myTrigger"); trigger.setJobDetail(jobDetail); trigger.setStartDelay(1); trigger.setRepeatInterval(500); trigger.setRepeatCount(1); trigger.afterPropertiesSet(); SchedulerFactoryBean bean = new SchedulerFactoryBean(); bean.setTriggers(new Trigger[] {trigger}); bean.setJobDetails(new JobDetail[] {jobDetail}); bean.afterPropertiesSet(); Thread.sleep(500); assertTrue(DummyRunnable.count > 0); bean.destroy(); } public void testSchedulerWithQuartzJobBean() throws Exception { DummyJob.param = 0; DummyJob.count = 0; JobDetail jobDetail = new JobDetail(); jobDetail.setJobClass(DummyJobBean.class); jobDetail.setName("myJob"); jobDetail.getJobDataMap().put("param", "10"); SimpleTriggerBean trigger = new SimpleTriggerBean(); trigger.setName("myTrigger"); trigger.setJobDetail(jobDetail); trigger.setStartDelay(1); trigger.setRepeatInterval(500); trigger.setRepeatCount(1); trigger.afterPropertiesSet(); SchedulerFactoryBean bean = new SchedulerFactoryBean(); bean.setTriggers(new Trigger[] {trigger}); bean.setJobDetails(new JobDetail[] {jobDetail}); bean.afterPropertiesSet(); Thread.sleep(500); assertEquals(10, DummyJobBean.param); assertTrue(DummyJobBean.count > 0); bean.destroy(); } public void testSchedulerWithSpringBeanJobFactory() throws Exception { DummyJob.param = 0; DummyJob.count = 0; JobDetail jobDetail = new JobDetail(); jobDetail.setJobClass(DummyJob.class); jobDetail.setName("myJob"); jobDetail.getJobDataMap().put("param", "10"); jobDetail.getJobDataMap().put("ignoredParam", "10"); SimpleTriggerBean trigger = new SimpleTriggerBean(); trigger.setName("myTrigger"); trigger.setJobDetail(jobDetail); trigger.setStartDelay(1); trigger.setRepeatInterval(500); trigger.setRepeatCount(1); trigger.afterPropertiesSet(); SchedulerFactoryBean bean = new SchedulerFactoryBean(); bean.setJobFactory(new SpringBeanJobFactory()); bean.setTriggers(new Trigger[] {trigger}); bean.setJobDetails(new JobDetail[] {jobDetail}); bean.afterPropertiesSet(); Thread.sleep(500); assertEquals(10, DummyJob.param); assertTrue(DummyJob.count > 0); bean.destroy(); } public void testSchedulerWithSpringBeanJobFactoryAndParamMismatchNotIgnored() throws Exception { DummyJob.param = 0; DummyJob.count = 0; JobDetail jobDetail = new JobDetail(); jobDetail.setJobClass(DummyJob.class); jobDetail.setName("myJob"); jobDetail.getJobDataMap().put("para", "10"); jobDetail.getJobDataMap().put("ignoredParam", "10"); SimpleTriggerBean trigger = new SimpleTriggerBean(); trigger.setName("myTrigger"); trigger.setJobDetail(jobDetail); trigger.setStartDelay(1); trigger.setRepeatInterval(500); trigger.setRepeatCount(1); trigger.afterPropertiesSet(); SchedulerFactoryBean bean = new SchedulerFactoryBean(); SpringBeanJobFactory jobFactory = new SpringBeanJobFactory(); jobFactory.setIgnoredUnknownProperties(new String[] {"ignoredParam"}); bean.setJobFactory(jobFactory); bean.setTriggers(new Trigger[] {trigger}); bean.setJobDetails(new JobDetail[] {jobDetail}); bean.afterPropertiesSet(); Thread.sleep(500); assertEquals(0, DummyJob.param); assertTrue(DummyJob.count == 0); bean.destroy(); } public void testSchedulerWithSpringBeanJobFactoryAndRunnable() throws Exception { DummyRunnable.param = 0; DummyRunnable.count = 0; JobDetail jobDetail = new JobDetailBean(); jobDetail.setJobClass(DummyRunnable.class); jobDetail.setName("myJob"); jobDetail.getJobDataMap().put("param", "10"); SimpleTriggerBean trigger = new SimpleTriggerBean(); trigger.setName("myTrigger"); trigger.setJobDetail(jobDetail); trigger.setStartDelay(1); trigger.setRepeatInterval(500); trigger.setRepeatCount(1); trigger.afterPropertiesSet(); SchedulerFactoryBean bean = new SchedulerFactoryBean(); bean.setJobFactory(new SpringBeanJobFactory()); bean.setTriggers(new Trigger[] {trigger}); bean.setJobDetails(new JobDetail[] {jobDetail}); bean.afterPropertiesSet(); Thread.sleep(500); assertEquals(10, DummyRunnable.param); assertTrue(DummyRunnable.count > 0); bean.destroy(); } public void testSchedulerWithSpringBeanJobFactoryAndQuartzJobBean() throws Exception { DummyJobBean.param = 0; DummyJobBean.count = 0; JobDetail jobDetail = new JobDetail(); jobDetail.setJobClass(DummyJobBean.class); jobDetail.setName("myJob"); jobDetail.getJobDataMap().put("param", "10"); SimpleTriggerBean trigger = new SimpleTriggerBean(); trigger.setName("myTrigger"); trigger.setJobDetail(jobDetail); trigger.setStartDelay(1); trigger.setRepeatInterval(500); trigger.setRepeatCount(1); trigger.afterPropertiesSet(); SchedulerFactoryBean bean = new SchedulerFactoryBean(); bean.setJobFactory(new SpringBeanJobFactory()); bean.setTriggers(new Trigger[] {trigger}); bean.setJobDetails(new JobDetail[] {jobDetail}); bean.afterPropertiesSet(); Thread.sleep(500); assertEquals(10, DummyJobBean.param); assertTrue(DummyJobBean.count > 0); bean.destroy(); } public void testSchedulerWithSpringBeanJobFactoryAndJobSchedulingData() throws Exception { DummyJob.param = 0; DummyJob.count = 0; SchedulerFactoryBean bean = new SchedulerFactoryBean(); bean.setJobFactory(new SpringBeanJobFactory()); bean.setJobSchedulingDataLocation("org/springframework/scheduling/quartz/job-scheduling-data.xml"); bean.setResourceLoader(new FileSystemResourceLoader()); bean.afterPropertiesSet(); Thread.sleep(500); assertEquals(10, DummyJob.param); assertTrue(DummyJob.count > 0); bean.destroy(); } /** * Tests the creation of multiple schedulers (SPR-772) */ public void testMultipleSchedulers() throws Exception { ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("/org/springframework/scheduling/quartz/multipleSchedulers.xml"); try { Scheduler scheduler1 = (Scheduler) ctx.getBean("scheduler1"); Scheduler scheduler2 = (Scheduler) ctx.getBean("scheduler2"); assertNotSame(scheduler1, scheduler2); assertEquals("quartz1", scheduler1.getSchedulerName()); assertEquals("quartz2", scheduler2.getSchedulerName()); ClassPathXmlApplicationContext ctx2 = new ClassPathXmlApplicationContext("/org/springframework/scheduling/quartz/multipleSchedulers.xml"); try { Scheduler scheduler1a = (Scheduler) ctx2.getBean("scheduler1"); Scheduler scheduler2a = (Scheduler) ctx2.getBean("scheduler2"); assertNotSame(scheduler1a, scheduler2a); assertNotSame(scheduler1a, scheduler1); assertNotSame(scheduler2a, scheduler2); assertEquals("quartz1", scheduler1a.getSchedulerName()); assertEquals("quartz2", scheduler2a.getSchedulerName()); } finally { ctx2.close(); } } finally { ctx.close(); } } public void testWithTwoAnonymousMethodInvokingJobDetailFactoryBeans() throws InterruptedException { ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("/org/springframework/scheduling/quartz/multipleAnonymousMethodInvokingJobDetailFB.xml"); Thread.sleep(3000); try { QuartzTestBean exportService = (QuartzTestBean) ctx.getBean("exportService"); QuartzTestBean importService = (QuartzTestBean) ctx.getBean("importService"); assertEquals("doImport called exportService", 0, exportService.getImportCount()); assertEquals("doExport not called on exportService", 2, exportService.getExportCount()); assertEquals("doImport not called on importService", 2, importService.getImportCount()); assertEquals("doExport called on importService", 0, importService.getExportCount()); } finally { ctx.close(); } } public void testSchedulerAccessorBean() throws InterruptedException { ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("/org/springframework/scheduling/quartz/schedulerAccessorBean.xml"); Thread.sleep(3000); try { QuartzTestBean exportService = (QuartzTestBean) ctx.getBean("exportService"); QuartzTestBean importService = (QuartzTestBean) ctx.getBean("importService"); assertEquals("doImport called exportService", 0, exportService.getImportCount()); assertEquals("doExport not called on exportService", 2, exportService.getExportCount()); assertEquals("doImport not called on importService", 2, importService.getImportCount()); assertEquals("doExport called on importService", 0, importService.getExportCount()); } finally { ctx.close(); } } public void testSchedulerRepositoryExposure() throws InterruptedException { ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("/org/springframework/scheduling/quartz/schedulerRepositoryExposure.xml"); assertSame(SchedulerRepository.getInstance().lookup("myScheduler"), ctx.getBean("scheduler")); ctx.close(); } private static class TestSchedulerListener implements 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() { } } private static class TestJobListener implements JobListener { public String getName() { return null; } public void jobToBeExecuted(JobExecutionContext context) { } public void jobExecutionVetoed(JobExecutionContext context) { } public void jobWasExecuted(JobExecutionContext context, JobExecutionException jobException) { } } private static class TestTriggerListener implements TriggerListener { public String getName() { return null; } public void triggerFired(Trigger trigger, JobExecutionContext context) { } public boolean vetoJobExecution(Trigger trigger, JobExecutionContext context) { return false; } public void triggerMisfired(Trigger trigger) { } public void triggerComplete(Trigger trigger, JobExecutionContext context, int triggerInstructionCode) { } } public static class CountingTaskExecutor implements TaskExecutor { private int count; public void execute(Runnable task) { this.count++; task.run(); } } public static class DummyJob implements Job { private static int param; private static int count; public void setParam(int value) { if (param > 0) { throw new IllegalStateException("Param already set"); } param = value; } public synchronized void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException { count++; } } public static class DummyJobBean extends QuartzJobBean { private static int param; private static int count; public void setParam(int value) { if (param > 0) { throw new IllegalStateException("Param already set"); } param = value; } protected synchronized void executeInternal(JobExecutionContext jobExecutionContext) throws JobExecutionException { count++; } } public static class DummyRunnable implements Runnable { private static int param; private static int count; public void setParam(int value) { if (param > 0) { throw new IllegalStateException("Param already set"); } param = value; } public void run() { count++; } } }