From ab6c6b104d1ad35f99a09537474b3f31258efda8 Mon Sep 17 00:00:00 2001 From: Juergen Hoeller Date: Sun, 5 Jan 2014 17:30:42 +0100 Subject: [PATCH] Consistent support for setStartTime in CronTrigger(Factory)Bean and SimpleTrigger(Factory)Bean, and consistent declaration of varargs in scheduling.quartz package Issue: SPR-10940 (cherry picked from commit b228a06) --- .../scheduling/quartz/CronTriggerBean.java | 20 ++++++------- .../quartz/CronTriggerFactoryBean.java | 16 +++++++---- .../scheduling/quartz/JobDetailBean.java | 12 ++++---- .../MethodInvokingJobDetailFactoryBean.java | 12 ++++---- .../scheduling/quartz/SchedulerAccessor.java | 28 +++++++++---------- .../scheduling/quartz/SimpleTriggerBean.java | 12 +++++--- .../quartz/SimpleTriggerFactoryBean.java | 21 +++++++++----- .../quartz/SpringBeanJobFactory.java | 2 +- 8 files changed, 70 insertions(+), 53 deletions(-) diff --git a/spring-context-support/src/main/java/org/springframework/scheduling/quartz/CronTriggerBean.java b/spring-context-support/src/main/java/org/springframework/scheduling/quartz/CronTriggerBean.java index 3fb77637771..8ca82b49184 100644 --- a/spring-context-support/src/main/java/org/springframework/scheduling/quartz/CronTriggerBean.java +++ b/spring-context-support/src/main/java/org/springframework/scheduling/quartz/CronTriggerBean.java @@ -73,7 +73,7 @@ public class CronTriggerBean extends CronTrigger private String beanName; - private long startDelay; + private long startDelay = 0; /** @@ -108,9 +108,9 @@ public class CronTriggerBean extends CronTrigger * @see SchedulerFactoryBean#setTriggerListeners * @see org.quartz.TriggerListener#getName */ - public void setTriggerListenerNames(String[] names) { - for (int i = 0; i < names.length; i++) { - addTriggerListener(names[i]); + public void setTriggerListenerNames(String... names) { + for (String name : names) { + addTriggerListener(name); } } @@ -148,19 +148,19 @@ public class CronTriggerBean extends CronTrigger } + /** + * Note that this method's declaration of an Exception is deprecated + * and will be removed in the Spring 4.0 line. + */ public void afterPropertiesSet() throws Exception { - if (this.startDelay > 0) { - setStartTime(new Date(System.currentTimeMillis() + this.startDelay)); - } - if (getName() == null) { setName(this.beanName); } if (getGroup() == null) { setGroup(Scheduler.DEFAULT_GROUP); } - if (getStartTime() == null) { - setStartTime(new Date()); + if (this.startDelay > 0 || getStartTime() == null) { + setStartTime(new Date(System.currentTimeMillis() + this.startDelay)); } if (getTimeZone() == null) { setTimeZone(TimeZone.getDefault()); diff --git a/spring-context-support/src/main/java/org/springframework/scheduling/quartz/CronTriggerFactoryBean.java b/spring-context-support/src/main/java/org/springframework/scheduling/quartz/CronTriggerFactoryBean.java index 1e7bc6c0c16..6300ea7219f 100644 --- a/spring-context-support/src/main/java/org/springframework/scheduling/quartz/CronTriggerFactoryBean.java +++ b/spring-context-support/src/main/java/org/springframework/scheduling/quartz/CronTriggerFactoryBean.java @@ -78,7 +78,7 @@ public class CronTriggerFactoryBean implements FactoryBean, BeanNam private Date startTime; - private long startDelay; + private long startDelay = 0; private String cronExpression; @@ -141,6 +141,15 @@ public class CronTriggerFactoryBean implements FactoryBean, BeanNam this.jobDataMap.putAll(jobDataAsMap); } + /** + * Set a specific start time for the trigger. + *

Note that a dynamically computed {@link #setStartDelay} specification + * overrides a static timestamp set here. + */ + public void setStartTime(Date startTime) { + this.startTime = startTime; + } + /** * Set the start delay in milliseconds. *

The start delay is added to the current system time (when the bean starts) @@ -206,12 +215,9 @@ public class CronTriggerFactoryBean implements FactoryBean, BeanNam if (this.jobDetail != null) { this.jobDataMap.put(JobDetailAwareTrigger.JOB_DETAIL_KEY, this.jobDetail); } - if (this.startDelay > 0) { + if (this.startDelay > 0 || this.startTime == null) { this.startTime = new Date(System.currentTimeMillis() + this.startDelay); } - else if (this.startTime == null) { - this.startTime = new Date(); - } if (this.timeZone == null) { this.timeZone = TimeZone.getDefault(); } diff --git a/spring-context-support/src/main/java/org/springframework/scheduling/quartz/JobDetailBean.java b/spring-context-support/src/main/java/org/springframework/scheduling/quartz/JobDetailBean.java index 11afab464b0..7ab2b791663 100644 --- a/spring-context-support/src/main/java/org/springframework/scheduling/quartz/JobDetailBean.java +++ b/spring-context-support/src/main/java/org/springframework/scheduling/quartz/JobDetailBean.java @@ -48,11 +48,11 @@ import org.springframework.context.ApplicationContextAware; * @see org.springframework.beans.factory.BeanNameAware * @see org.quartz.Scheduler#DEFAULT_GROUP */ -@SuppressWarnings("serial") +@SuppressWarnings({"serial", "rawtypes"}) public class JobDetailBean extends JobDetail implements BeanNameAware, ApplicationContextAware, InitializingBean { - private Class actualJobClass; + private Class actualJobClass; private String beanName; @@ -82,7 +82,7 @@ public class JobDetailBean extends JobDetail * to adapt the given job class to the Quartz Job interface. */ @Override - public Class getJobClass() { + public Class getJobClass() { return (this.actualJobClass != null ? this.actualJobClass : super.getJobClass()); } @@ -109,9 +109,9 @@ public class JobDetailBean extends JobDetail * @see SchedulerFactoryBean#setJobListeners * @see org.quartz.JobListener#getName */ - public void setJobListenerNames(String[] names) { - for (int i = 0; i < names.length; i++) { - addJobListener(names[i]); + public void setJobListenerNames(String... names) { + for (String name : names) { + addJobListener(name); } } diff --git a/spring-context-support/src/main/java/org/springframework/scheduling/quartz/MethodInvokingJobDetailFactoryBean.java b/spring-context-support/src/main/java/org/springframework/scheduling/quartz/MethodInvokingJobDetailFactoryBean.java index f0cf75cd014..a271d5f3e49 100644 --- a/spring-context-support/src/main/java/org/springframework/scheduling/quartz/MethodInvokingJobDetailFactoryBean.java +++ b/spring-context-support/src/main/java/org/springframework/scheduling/quartz/MethodInvokingJobDetailFactoryBean.java @@ -92,7 +92,7 @@ public class MethodInvokingJobDetailFactoryBean extends ArgumentConvertingMethod jobDetailImplClass = null; } try { - Class jobExecutionContextClass = + Class jobExecutionContextClass = QuartzJobBean.class.getClassLoader().loadClass("org.quartz.JobExecutionContext"); setResultMethod = jobExecutionContextClass.getMethod("setResult", Object.class); } @@ -172,7 +172,7 @@ public class MethodInvokingJobDetailFactoryBean extends ArgumentConvertingMethod * @see SchedulerFactoryBean#setJobListeners * @see org.quartz.JobListener#getName */ - public void setJobListenerNames(String[] names) { + public void setJobListenerNames(String... names) { this.jobListenerNames = names; } @@ -189,7 +189,7 @@ public class MethodInvokingJobDetailFactoryBean extends ArgumentConvertingMethod } @Override - protected Class resolveClassName(String className) throws ClassNotFoundException { + protected Class resolveClassName(String className) throws ClassNotFoundException { return ClassUtils.forName(className, this.beanClassLoader); } @@ -201,7 +201,7 @@ public class MethodInvokingJobDetailFactoryBean extends ArgumentConvertingMethod String name = (this.name != null ? this.name : this.beanName); // Consider the concurrent flag to choose between stateful and stateless job. - Class jobClass = (this.concurrent ? MethodInvokingJob.class : StatefulMethodInvokingJob.class); + Class jobClass = (this.concurrent ? MethodInvokingJob.class : StatefulMethodInvokingJob.class); // Build JobDetail instance. if (jobDetailImplClass != null) { @@ -249,8 +249,8 @@ public class MethodInvokingJobDetailFactoryBean extends ArgumentConvertingMethod * Overridden to support the {@link #setTargetBeanName "targetBeanName"} feature. */ @Override - public Class getTargetClass() { - Class targetClass = super.getTargetClass(); + public Class getTargetClass() { + Class targetClass = super.getTargetClass(); if (targetClass == null && this.targetBeanName != null) { Assert.state(this.beanFactory != null, "BeanFactory must be set when using 'targetBeanName'"); targetClass = this.beanFactory.getType(this.targetBeanName); diff --git a/spring-context-support/src/main/java/org/springframework/scheduling/quartz/SchedulerAccessor.java b/spring-context-support/src/main/java/org/springframework/scheduling/quartz/SchedulerAccessor.java index 6c261a100f1..fe06917740c 100644 --- a/spring-context-support/src/main/java/org/springframework/scheduling/quartz/SchedulerAccessor.java +++ b/spring-context-support/src/main/java/org/springframework/scheduling/quartz/SchedulerAccessor.java @@ -128,7 +128,7 @@ public abstract class SchedulerAccessor implements ResourceLoaderAware { * to jobs defined directly on this SchedulerFactoryBean. * @see org.quartz.xml.XmlSchedulingDataProcessor */ - public void setJobSchedulingDataLocations(String[] jobSchedulingDataLocations) { + public void setJobSchedulingDataLocations(String... jobSchedulingDataLocations) { this.jobSchedulingDataLocations = jobSchedulingDataLocations; } @@ -142,9 +142,8 @@ public abstract class SchedulerAccessor implements ResourceLoaderAware { * @see org.quartz.JobDetail * @see JobDetailBean * @see JobDetailAwareTrigger - * @see org.quartz.Trigger#setJobName */ - public void setJobDetails(JobDetail[] jobDetails) { + public void setJobDetails(JobDetail... jobDetails) { // Use modifiable ArrayList here, to allow for further adding of // JobDetail objects during autodetection of JobDetailAwareTriggers. this.jobDetails = new ArrayList(Arrays.asList(jobDetails)); @@ -156,7 +155,6 @@ public abstract class SchedulerAccessor implements ResourceLoaderAware { * @param calendars Map with calendar names as keys as Calendar * objects as values * @see org.quartz.Calendar - * @see org.quartz.Trigger#setCalendarName */ public void setCalendars(Map calendars) { this.calendars = calendars; @@ -175,7 +173,7 @@ public abstract class SchedulerAccessor implements ResourceLoaderAware { * @see CronTriggerBean * @see SimpleTriggerBean */ - public void setTriggers(Trigger[] triggers) { + public void setTriggers(Trigger... triggers) { this.triggers = Arrays.asList(triggers); } @@ -183,7 +181,7 @@ public abstract class SchedulerAccessor implements ResourceLoaderAware { /** * Specify Quartz SchedulerListeners to be registered with the Scheduler. */ - public void setSchedulerListeners(SchedulerListener[] schedulerListeners) { + public void setSchedulerListeners(SchedulerListener... schedulerListeners) { this.schedulerListeners = schedulerListeners; } @@ -191,7 +189,7 @@ public abstract class SchedulerAccessor implements ResourceLoaderAware { * Specify global Quartz JobListeners to be registered with the Scheduler. * Such JobListeners will apply to all Jobs in the Scheduler. */ - public void setGlobalJobListeners(JobListener[] globalJobListeners) { + public void setGlobalJobListeners(JobListener... globalJobListeners) { this.globalJobListeners = globalJobListeners; } @@ -199,11 +197,12 @@ public abstract class SchedulerAccessor implements ResourceLoaderAware { * Specify named Quartz JobListeners to be registered with the Scheduler. * Such JobListeners will only apply to Jobs that explicitly activate * them via their name. + *

Note that non-global JobListeners are not supported on Quartz 2.x - + * manually register a Matcher against the Quartz ListenerManager instead. * @see org.quartz.JobListener#getName - * @see org.quartz.JobDetail#addJobListener * @see JobDetailBean#setJobListenerNames */ - public void setJobListeners(JobListener[] jobListeners) { + public void setJobListeners(JobListener... jobListeners) { this.jobListeners = jobListeners; } @@ -211,7 +210,7 @@ public abstract class SchedulerAccessor implements ResourceLoaderAware { * Specify global Quartz TriggerListeners to be registered with the Scheduler. * Such TriggerListeners will apply to all Triggers in the Scheduler. */ - public void setGlobalTriggerListeners(TriggerListener[] globalTriggerListeners) { + public void setGlobalTriggerListeners(TriggerListener... globalTriggerListeners) { this.globalTriggerListeners = globalTriggerListeners; } @@ -219,12 +218,13 @@ public abstract class SchedulerAccessor implements ResourceLoaderAware { * Specify named Quartz TriggerListeners to be registered with the Scheduler. * Such TriggerListeners will only apply to Triggers that explicitly activate * them via their name. + *

Note that non-global TriggerListeners are not supported on Quartz 2.x - + * manually register a Matcher against the Quartz ListenerManager instead. * @see org.quartz.TriggerListener#getName - * @see org.quartz.Trigger#addTriggerListener * @see CronTriggerBean#setTriggerListenerNames * @see SimpleTriggerBean#setTriggerListenerNames */ - public void setTriggerListeners(TriggerListener[] triggerListeners) { + public void setTriggerListeners(TriggerListener... triggerListeners) { this.triggerListeners = triggerListeners; } @@ -251,8 +251,8 @@ public abstract class SchedulerAccessor implements ResourceLoaderAware { if (this.transactionManager != null) { transactionStatus = this.transactionManager.getTransaction(new DefaultTransactionDefinition()); } - try { + try { if (this.jobSchedulingDataLocations != null) { ClassLoadHelper clh = new ResourceLoaderClassLoadHelper(this.resourceLoader); clh.initialize(); @@ -396,7 +396,7 @@ public abstract class SchedulerAccessor implements ResourceLoaderAware { } else { try { - Map jobDataMap = (Map) ReflectionUtils.invokeMethod(Trigger.class.getMethod("getJobDataMap"), trigger); + Map jobDataMap = (Map) ReflectionUtils.invokeMethod(Trigger.class.getMethod("getJobDataMap"), trigger); return (JobDetail) jobDataMap.remove(JobDetailAwareTrigger.JOB_DETAIL_KEY); } catch (NoSuchMethodException ex) { diff --git a/spring-context-support/src/main/java/org/springframework/scheduling/quartz/SimpleTriggerBean.java b/spring-context-support/src/main/java/org/springframework/scheduling/quartz/SimpleTriggerBean.java index d0af74c4cd5..2ab836b5c88 100644 --- a/spring-context-support/src/main/java/org/springframework/scheduling/quartz/SimpleTriggerBean.java +++ b/spring-context-support/src/main/java/org/springframework/scheduling/quartz/SimpleTriggerBean.java @@ -114,9 +114,9 @@ public class SimpleTriggerBean extends SimpleTrigger * @see SchedulerFactoryBean#setTriggerListeners * @see org.quartz.TriggerListener#getName */ - public void setTriggerListenerNames(String[] names) { - for (int i = 0; i < names.length; i++) { - addTriggerListener(names[i]); + public void setTriggerListenerNames(String... names) { + for (String name : names) { + addTriggerListener(name); } } @@ -153,6 +153,10 @@ public class SimpleTriggerBean extends SimpleTrigger } + /** + * Note that this method's declaration of a ParseException is deprecated + * and will be removed in the Spring 4.0 line. + */ public void afterPropertiesSet() throws ParseException { if (getName() == null) { setName(this.beanName); @@ -160,7 +164,7 @@ public class SimpleTriggerBean extends SimpleTrigger if (getGroup() == null) { setGroup(Scheduler.DEFAULT_GROUP); } - if (getStartTime() == null) { + if (this.startDelay > 0 || getStartTime() == null) { setStartTime(new Date(System.currentTimeMillis() + this.startDelay)); } if (this.jobDetail != null) { diff --git a/spring-context-support/src/main/java/org/springframework/scheduling/quartz/SimpleTriggerFactoryBean.java b/spring-context-support/src/main/java/org/springframework/scheduling/quartz/SimpleTriggerFactoryBean.java index ce4365eb52d..8a975a0ea6d 100644 --- a/spring-context-support/src/main/java/org/springframework/scheduling/quartz/SimpleTriggerFactoryBean.java +++ b/spring-context-support/src/main/java/org/springframework/scheduling/quartz/SimpleTriggerFactoryBean.java @@ -17,7 +17,6 @@ package org.springframework.scheduling.quartz; import java.lang.reflect.Method; -import java.text.ParseException; import java.util.Date; import java.util.Map; @@ -141,10 +140,20 @@ public class SimpleTriggerFactoryBean implements FactoryBean, Bea this.jobDataMap.putAll(jobDataAsMap); } + /** + * Set a specific start time for the trigger. + *

Note that a dynamically computed {@link #setStartDelay} specification + * overrides a static timestamp set here. + */ + public void setStartTime(Date startTime) { + this.startTime = startTime; + } + /** * Set the start delay in milliseconds. *

The start delay is added to the current system time (when the bean starts) * to control the start time of the trigger. + * @see #setStartTime */ public void setStartDelay(long startDelay) { Assert.isTrue(startDelay >= 0, "Start delay cannot be negative"); @@ -200,7 +209,7 @@ public class SimpleTriggerFactoryBean implements FactoryBean, Bea } - public void afterPropertiesSet() throws ParseException { + public void afterPropertiesSet() { if (this.name == null) { this.name = this.beanName; } @@ -210,12 +219,9 @@ public class SimpleTriggerFactoryBean implements FactoryBean, Bea if (this.jobDetail != null) { this.jobDataMap.put(JobDetailAwareTrigger.JOB_DETAIL_KEY, this.jobDetail); } - if (this.startDelay > 0) { + if (this.startDelay > 0 || this.startTime == null) { this.startTime = new Date(System.currentTimeMillis() + this.startDelay); } - else if (this.startTime == null) { - this.startTime = new Date(); - } /* SimpleTriggerImpl sti = new SimpleTriggerImpl(); @@ -231,7 +237,7 @@ public class SimpleTriggerFactoryBean implements FactoryBean, Bea this.simpleTrigger = sti; */ - Class simpleTriggerClass; + Class simpleTriggerClass; Method jobKeyMethod; try { simpleTriggerClass = getClass().getClassLoader().loadClass("org.quartz.impl.triggers.SimpleTriggerImpl"); @@ -277,4 +283,5 @@ public class SimpleTriggerFactoryBean implements FactoryBean, Bea public boolean isSingleton() { return true; } + } diff --git a/spring-context-support/src/main/java/org/springframework/scheduling/quartz/SpringBeanJobFactory.java b/spring-context-support/src/main/java/org/springframework/scheduling/quartz/SpringBeanJobFactory.java index 77965c965dc..ddbf7953db8 100644 --- a/spring-context-support/src/main/java/org/springframework/scheduling/quartz/SpringBeanJobFactory.java +++ b/spring-context-support/src/main/java/org/springframework/scheduling/quartz/SpringBeanJobFactory.java @@ -59,7 +59,7 @@ public class SpringBeanJobFactory extends AdaptableJobFactory implements Schedul * ignored if there is no corresponding property found on the particular * job class (all other unknown properties will still trigger an exception). */ - public void setIgnoredUnknownProperties(String[] ignoredUnknownProperties) { + public void setIgnoredUnknownProperties(String... ignoredUnknownProperties) { this.ignoredUnknownProperties = ignoredUnknownProperties; }