diff --git a/build.gradle b/build.gradle
index 703d8cbf34e..d63395d49da 100644
--- a/build.gradle
+++ b/build.gradle
@@ -19,7 +19,6 @@ configure(allprojects) { project ->
ext.hibernate4Version = "4.2.11.Final"
ext.hibValVersion = "4.3.1.Final"
ext.hsqldbVersion = "2.3.2"
- ext.jackson1Version = "1.9.13"
ext.jackson2Version = "2.3.1"
ext.jasperReportsVersion = "5.5.1"
ext.jettyVersion = "9.1.3.v20140225"
@@ -495,7 +494,6 @@ project("spring-jms") {
optional("aopalliance:aopalliance:1.0")
optional("javax.transaction:javax.transaction-api:1.2")
optional("javax.resource:connector-api:1.5")
- optional("org.codehaus.jackson:jackson-mapper-asl:${jackson1Version}")
optional("com.fasterxml.jackson.core:jackson-databind:${jackson2Version}")
}
}
@@ -530,9 +528,7 @@ project("spring-context-support") {
optional("javax.cache:cache-api:1.0.0-RC1")
optional("com.google.guava:guava:16.0.1")
optional("net.sf.ehcache:ehcache-core:2.6.5")
- optional("org.quartz-scheduler:quartz:1.8.6") {
- exclude group: "org.slf4j", module: "slf4j-log4j12"
- }
+ optional("org.quartz-scheduler:quartz:2.1.7")
optional("org.codehaus.fabric3.api:commonj:1.1.0")
optional("org.apache.velocity:velocity:1.7")
optional("org.freemarker:freemarker:2.3.20")
@@ -568,7 +564,6 @@ project("spring-web") {
optional("commons-fileupload:commons-fileupload:1.3.1")
optional("org.apache.httpcomponents:httpclient:4.3.3")
optional("org.apache.httpcomponents:httpasyncclient:4.0.1")
- optional("org.codehaus.jackson:jackson-mapper-asl:${jackson1Version}")
optional("com.fasterxml.jackson.core:jackson-databind:${jackson2Version}")
optional("rome:rome:1.0")
optional("taglibs:standard:1.1.2")
@@ -709,7 +704,6 @@ project("spring-webmvc") {
optional("net.sf.jasperreports:jasperreports:$jasperReportsVersion") {
exclude group: "xml-apis", module: "xml-apis"
}
- optional("org.codehaus.jackson:jackson-mapper-asl:${jackson1Version}")
optional("com.fasterxml.jackson.core:jackson-databind:${jackson2Version}")
optional("rome:rome:1.0")
optional("org.apache.tiles:tiles-api:${tiles2Version}")
@@ -847,7 +841,6 @@ project("spring-test") {
testCompile("org.hibernate:hibernate-entitymanager:${hibernate3Version}")
testCompile("org.hibernate:hibernate-validator:${hibValVersion}")
testCompile("com.thoughtworks.xstream:xstream:${xstreamVersion}")
- testCompile("org.codehaus.jackson:jackson-mapper-asl:${jackson1Version}")
testCompile("com.fasterxml.jackson.core:jackson-databind:${jackson2Version}")
testCompile("rome:rome:1.0")
testCompile("org.apache.tiles:tiles-api:${tiles3Version}")
diff --git a/spring-context-support/src/main/java/org/springframework/cache/ehcache/EhCacheFactoryBean.java b/spring-context-support/src/main/java/org/springframework/cache/ehcache/EhCacheFactoryBean.java
index 1aed482cfbf..0a48df385d8 100644
--- a/spring-context-support/src/main/java/org/springframework/cache/ehcache/EhCacheFactoryBean.java
+++ b/spring-context-support/src/main/java/org/springframework/cache/ehcache/EhCacheFactoryBean.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2013 the original author or authors.
+ * Copyright 2002-2014 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.
@@ -52,9 +52,8 @@ import org.springframework.util.ClassUtils;
*
Note: If the named Cache instance is found, the properties will be ignored and the
* Cache instance will be retrieved from the CacheManager.
*
- *
Note: As of Spring 4.0, Spring's EhCache support requires EhCache 2.1 or higher.
- * We recommend the use of EhCache 2.5 or higher.
-
+ *
Note: As of Spring 4.1, Spring's EhCache support requires EhCache 2.5 or higher.
+ *
* @author Juergen Hoeller
* @author Dmitriy Kopylenko
* @since 1.1.1
@@ -92,10 +91,8 @@ public class EhCacheFactoryBean extends CacheConfiguration implements FactoryBea
private Ehcache cache;
- @SuppressWarnings("deprecation")
public EhCacheFactoryBean() {
- // Using deprecated setMaxElementsInMemory method for EhCache 2.1-2.4 compatibility
- setMaxElementsInMemory(10000);
+ setMaxEntriesLocalHeap(10000);
setMaxElementsOnDisk(10000000);
setTimeToLiveSeconds(120);
setTimeToIdleSeconds(120);
diff --git a/spring-context-support/src/main/java/org/springframework/cache/ehcache/EhCacheManagerFactoryBean.java b/spring-context-support/src/main/java/org/springframework/cache/ehcache/EhCacheManagerFactoryBean.java
index a17adb14263..dcc038d6cb4 100644
--- a/spring-context-support/src/main/java/org/springframework/cache/ehcache/EhCacheManagerFactoryBean.java
+++ b/spring-context-support/src/main/java/org/springframework/cache/ehcache/EhCacheManagerFactoryBean.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2013 the original author or authors.
+ * Copyright 2002-2014 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.
@@ -44,8 +44,7 @@ import org.springframework.core.io.Resource;
* and cares for proper shutdown of the CacheManager. EhCacheManagerFactoryBean is
* also necessary for loading EhCache configuration from a non-default config location.
*
- *
Note: As of Spring 4.0, Spring's EhCache support requires EhCache 2.1 or higher.
- * We recommend the use of EhCache 2.5 or higher.
+ *
Note: As of Spring 4.1, Spring's EhCache support requires EhCache 2.5 or higher.
*
* @author Juergen Hoeller
* @author Dmitriy Kopylenko
diff --git a/spring-context-support/src/main/java/org/springframework/scheduling/quartz/AdaptableJobFactory.java b/spring-context-support/src/main/java/org/springframework/scheduling/quartz/AdaptableJobFactory.java
index 91dae748775..7aeb07d70ad 100644
--- a/spring-context-support/src/main/java/org/springframework/scheduling/quartz/AdaptableJobFactory.java
+++ b/spring-context-support/src/main/java/org/springframework/scheduling/quartz/AdaptableJobFactory.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2013 the original author or authors.
+ * Copyright 2002-2014 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.
@@ -16,22 +16,17 @@
package org.springframework.scheduling.quartz;
-import java.lang.reflect.Method;
-
import org.quartz.Job;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.spi.JobFactory;
import org.quartz.spi.TriggerFiredBundle;
-import org.springframework.util.ReflectionUtils;
-
/**
* JobFactory implementation that supports {@link java.lang.Runnable}
* objects as well as standard Quartz {@link org.quartz.Job} instances.
*
- *
Compatible with Quartz 1.8 as well as Quartz 2.0-2.2, as of Spring 4.0.
- * Note: Quartz 1.x support is deprecated - please upgrade to Quartz 2.0+.
+ *
Compatible with Quartz 2.1.4 and higher, as of Spring 4.1.
*
* @author Juergen Hoeller
* @since 2.0
@@ -40,19 +35,8 @@ import org.springframework.util.ReflectionUtils;
*/
public class AdaptableJobFactory implements JobFactory {
- /**
- * Quartz 2.0 version of newJob: simply delegates to old newJob variant.
- * @see #newJob(org.quartz.spi.TriggerFiredBundle)
- */
- public Job newJob(TriggerFiredBundle bundle, Scheduler scheduler) throws SchedulerException {
- return newJob(bundle);
- }
-
- /**
- * Quartz 1.x version of newJob: contains actual implementation code.
- */
@Override
- public Job newJob(TriggerFiredBundle bundle) throws SchedulerException {
+ public Job newJob(TriggerFiredBundle bundle, Scheduler scheduler) throws SchedulerException {
try {
Object jobObject = createJobInstance(bundle);
return adaptJob(jobObject);
@@ -71,12 +55,7 @@ public class AdaptableJobFactory implements JobFactory {
* @throws Exception if job instantiation failed
*/
protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception {
- // Reflectively adapting to differences between Quartz 1.x and Quartz 2.0...
- Method getJobDetail = bundle.getClass().getMethod("getJobDetail");
- Object jobDetail = ReflectionUtils.invokeMethod(getJobDetail, bundle);
- Method getJobClass = jobDetail.getClass().getMethod("getJobClass");
- Class> jobClass = (Class>) ReflectionUtils.invokeMethod(getJobClass, jobDetail);
- return jobClass.newInstance();
+ return bundle.getJobDetail().getJobClass().newInstance();
}
/**
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
deleted file mode 100644
index 5a29248d56e..00000000000
--- a/spring-context-support/src/main/java/org/springframework/scheduling/quartz/CronTriggerBean.java
+++ /dev/null
@@ -1,175 +0,0 @@
-/*
- * Copyright 2002-2013 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.Date;
-import java.util.Map;
-import java.util.TimeZone;
-
-import org.quartz.CronTrigger;
-import org.quartz.JobDetail;
-import org.quartz.Scheduler;
-
-import org.springframework.beans.factory.BeanNameAware;
-import org.springframework.beans.factory.InitializingBean;
-import org.springframework.core.Constants;
-import org.springframework.util.Assert;
-
-/**
- * Convenience subclass of Quartz's {@link org.quartz.CronTrigger} class,
- * making bean-style usage easier.
- *
- *
{@code CronTrigger} itself is already a JavaBean but lacks sensible defaults.
- * This class uses the Spring bean name as job name, the Quartz default group
- * ("DEFAULT") as job group, the current time as start time, and indefinite
- * repetition, if not specified.
- *
- *
This class will also register the trigger with the job name and group of
- * a given {@link org.quartz.JobDetail}. This allows {@link SchedulerFactoryBean}
- * to automatically register a trigger for the corresponding JobDetail,
- * instead of registering the JobDetail separately.
- *
- *
NOTE: This convenience subclass does not work against Quartz 2.0.
- * Use Quartz 2.0's native {@code JobDetailImpl} class or the new Quartz 2.0
- * builder API instead. Alternatively, switch to Spring's {@link CronTriggerFactoryBean}
- * which largely is a drop-in replacement for this class and its properties and
- * consistently works against Quartz 1.x as well as Quartz 2.x.
- *
- * @author Juergen Hoeller
- * @since 18.02.2004
- * @see #setName
- * @see #setGroup
- * @see #setStartTime
- * @see #setJobName
- * @see #setJobGroup
- * @see #setJobDetail
- * @see SchedulerFactoryBean#setTriggers
- * @see SchedulerFactoryBean#setJobDetails
- * @see SimpleTriggerBean
- */
-@SuppressWarnings("serial")
-public class CronTriggerBean extends CronTrigger
- implements JobDetailAwareTrigger, BeanNameAware, InitializingBean {
-
- /** Constants for the CronTrigger class */
- private static final Constants constants = new Constants(CronTrigger.class);
-
-
- private JobDetail jobDetail;
-
- private String beanName;
-
- private long startDelay = 0;
-
-
- /**
- * Register objects in the JobDataMap via a given Map.
- *
These objects will be available to this Trigger only,
- * in contrast to objects in the JobDetail's data map.
- * @param jobDataAsMap Map with String keys and any objects as values
- * (for example Spring-managed beans)
- * @see JobDetailBean#setJobDataAsMap
- */
- public void setJobDataAsMap(Map jobDataAsMap) {
- getJobDataMap().putAll(jobDataAsMap);
- }
-
- /**
- * Set the misfire instruction via the name of the corresponding
- * constant in the {@link org.quartz.CronTrigger} class.
- * Default is {@code MISFIRE_INSTRUCTION_SMART_POLICY}.
- * @see org.quartz.CronTrigger#MISFIRE_INSTRUCTION_FIRE_ONCE_NOW
- * @see org.quartz.CronTrigger#MISFIRE_INSTRUCTION_DO_NOTHING
- * @see org.quartz.Trigger#MISFIRE_INSTRUCTION_SMART_POLICY
- */
- public void setMisfireInstructionName(String constantName) {
- setMisfireInstruction(constants.asNumber(constantName).intValue());
- }
-
- /**
- * Set a list of TriggerListener names for this job, referring to
- * non-global TriggerListeners registered with the Scheduler.
- *
A TriggerListener name always refers to the name returned
- * by the TriggerListener implementation.
- * @see SchedulerFactoryBean#setTriggerListeners
- * @see org.quartz.TriggerListener#getName
- * @deprecated as of Spring 4.0, since it only works on Quartz 1.x
- */
- @Deprecated
- public void setTriggerListenerNames(String... names) {
- for (String name : names) {
- addTriggerListener(name);
- }
- }
-
- /**
- * Set the start delay in milliseconds.
- *
The start delay is added to the current system time (when the bean starts)
- * to control the {@link #setStartTime start time} of the trigger.
- *
If the start delay is non-zero, it will always
- * take precedence over start time.
- * @param startDelay the start delay, in milliseconds
- */
- public void setStartDelay(long startDelay) {
- Assert.state(startDelay >= 0, "Start delay cannot be negative.");
- this.startDelay = startDelay;
- }
-
- /**
- * Set the JobDetail that this trigger should be associated with.
- *
This is typically used with a bean reference if the JobDetail
- * is a Spring-managed bean. Alternatively, the trigger can also
- * be associated with a job by name and group.
- * @see #setJobName
- * @see #setJobGroup
- */
- public void setJobDetail(JobDetail jobDetail) {
- this.jobDetail = jobDetail;
- }
-
- @Override
- public JobDetail getJobDetail() {
- return this.jobDetail;
- }
-
- @Override
- public void setBeanName(String beanName) {
- this.beanName = beanName;
- }
-
-
- @Override
- public void afterPropertiesSet() {
- if (getName() == null) {
- setName(this.beanName);
- }
- if (getGroup() == null) {
- setGroup(Scheduler.DEFAULT_GROUP);
- }
- if (this.startDelay > 0 || getStartTime() == null) {
- setStartTime(new Date(System.currentTimeMillis() + this.startDelay));
- }
- if (getTimeZone() == null) {
- setTimeZone(TimeZone.getDefault());
- }
- if (this.jobDetail != null) {
- setJobName(this.jobDetail.getName());
- setJobGroup(this.jobDetail.getGroup());
- }
- }
-
-}
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 d5ffbcc94b6..666f591e008 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
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2013 the original author or authors.
+ * Copyright 2002-2014 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.
@@ -16,7 +16,7 @@
package org.springframework.scheduling.quartz;
-import java.lang.reflect.Method;
+import java.text.ParseException;
import java.util.Date;
import java.util.Map;
import java.util.TimeZone;
@@ -25,16 +25,13 @@ import org.quartz.CronTrigger;
import org.quartz.JobDataMap;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
+import org.quartz.impl.triggers.CronTriggerImpl;
-import org.springframework.beans.BeanWrapper;
-import org.springframework.beans.BeanWrapperImpl;
-import org.springframework.beans.MutablePropertyValues;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.core.Constants;
import org.springframework.util.Assert;
-import org.springframework.util.ReflectionUtils;
/**
* A Spring {@link FactoryBean} for creating a Quartz {@link org.quartz.CronTrigger}
@@ -49,9 +46,6 @@ import org.springframework.util.ReflectionUtils;
* to automatically register a trigger for the corresponding JobDetail,
* instead of registering the JobDetail separately.
*
- *
NOTE: This FactoryBean works against both Quartz 1.x and Quartz 2.x,
- * in contrast to the older {@link CronTriggerBean} class.
- *
* @author Juergen Hoeller
* @since 3.1
* @see #setName
@@ -60,7 +54,6 @@ import org.springframework.util.ReflectionUtils;
* @see #setJobDetail
* @see SchedulerFactoryBean#setTriggers
* @see SchedulerFactoryBean#setJobDetails
- * @see SimpleTriggerBean
*/
public class CronTriggerFactoryBean implements FactoryBean, BeanNameAware, InitializingBean {
@@ -139,7 +132,6 @@ public class CronTriggerFactoryBean implements FactoryBean, BeanNam
* in contrast to objects in the JobDetail's data map.
* @param jobDataAsMap Map with String keys and any objects as values
* (for example Spring-managed beans)
- * @see org.springframework.scheduling.quartz.JobDetailBean#setJobDataAsMap
*/
public void setJobDataAsMap(Map jobDataAsMap) {
this.jobDataMap.putAll(jobDataAsMap);
@@ -225,7 +217,7 @@ public class CronTriggerFactoryBean implements FactoryBean, BeanNam
@Override
- public void afterPropertiesSet() {
+ public void afterPropertiesSet() throws ParseException {
if (this.name == null) {
this.name = this.beanName;
}
@@ -233,7 +225,7 @@ public class CronTriggerFactoryBean implements FactoryBean, BeanNam
this.group = Scheduler.DEFAULT_GROUP;
}
if (this.jobDetail != null) {
- this.jobDataMap.put(JobDetailAwareTrigger.JOB_DETAIL_KEY, this.jobDetail);
+ this.jobDataMap.put("jobDetail", this.jobDetail);
}
if (this.startDelay > 0 || this.startTime == null) {
this.startTime = new Date(System.currentTimeMillis() + this.startDelay);
@@ -242,7 +234,6 @@ public class CronTriggerFactoryBean implements FactoryBean, BeanNam
this.timeZone = TimeZone.getDefault();
}
- /*
CronTriggerImpl cti = new CronTriggerImpl();
cti.setName(this.name);
cti.setGroup(this.group);
@@ -256,42 +247,6 @@ public class CronTriggerFactoryBean implements FactoryBean, BeanNam
cti.setMisfireInstruction(this.misfireInstruction);
cti.setDescription(this.description);
this.cronTrigger = cti;
- */
-
- Class> cronTriggerClass;
- Method jobKeyMethod;
- try {
- cronTriggerClass = getClass().getClassLoader().loadClass("org.quartz.impl.triggers.CronTriggerImpl");
- jobKeyMethod = JobDetail.class.getMethod("getKey");
- }
- catch (ClassNotFoundException ex) {
- cronTriggerClass = CronTrigger.class;
- jobKeyMethod = null;
- }
- catch (NoSuchMethodException ex) {
- throw new IllegalStateException("Incompatible Quartz version");
- }
- BeanWrapper bw = new BeanWrapperImpl(cronTriggerClass);
- MutablePropertyValues pvs = new MutablePropertyValues();
- pvs.add("name", this.name);
- pvs.add("group", this.group);
- if (jobKeyMethod != null) {
- pvs.add("jobKey", ReflectionUtils.invokeMethod(jobKeyMethod, this.jobDetail));
- }
- else {
- pvs.add("jobName", this.jobDetail.getName());
- pvs.add("jobGroup", this.jobDetail.getGroup());
- }
- pvs.add("jobDataMap", this.jobDataMap);
- pvs.add("startTime", this.startTime);
- pvs.add("cronExpression", this.cronExpression);
- pvs.add("timeZone", this.timeZone);
- pvs.add("calendarName", this.calendarName);
- pvs.add("priority", this.priority);
- pvs.add("misfireInstruction", this.misfireInstruction);
- pvs.add("description", this.description);
- bw.setPropertyValues(pvs);
- this.cronTrigger = (CronTrigger) bw.getWrappedInstance();
}
diff --git a/spring-context-support/src/main/java/org/springframework/scheduling/quartz/JobDetailAwareTrigger.java b/spring-context-support/src/main/java/org/springframework/scheduling/quartz/JobDetailAwareTrigger.java
deleted file mode 100644
index 3edec2aacba..00000000000
--- a/spring-context-support/src/main/java/org/springframework/scheduling/quartz/JobDetailAwareTrigger.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright 2002-2012 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 org.quartz.JobDetail;
-
-/**
- * Interface to be implemented by Quartz Triggers that are aware
- * of the JobDetail object that they are associated with.
- *
- *
SchedulerFactoryBean will auto-detect Triggers that implement this
- * interface and register them for the respective JobDetail accordingly.
- *
- *
The alternative is to configure a Trigger for a Job name and group:
- * This involves the need to register the JobDetail object separately
- * with SchedulerFactoryBean.
- *
- *
NOTE: As of Quartz 2.0, the recommended strategy is to define an
- * entry of name "jobDetail" and type JobDetail in the trigger's JobDataMap.
- *
- * @author Juergen Hoeller
- * @since 18.02.2004
- * @see SchedulerFactoryBean#setTriggers
- * @see SchedulerFactoryBean#setJobDetails
- * @see org.quartz.Trigger#setJobName
- * @see org.quartz.Trigger#setJobGroup
- */
-public interface JobDetailAwareTrigger {
-
- /**
- * Name of the key for the JobDetail value in the trigger's JobDataMap.
- * This is an alternative to implementing the JobDetailAwareTrigger interface.
- */
- String JOB_DETAIL_KEY = "jobDetail";
-
- /**
- * Return the JobDetail that this Trigger is associated with.
- * @return the associated JobDetail, or {@code null} if none
- */
- JobDetail getJobDetail();
-
-}
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
deleted file mode 100644
index f0d7762225c..00000000000
--- a/spring-context-support/src/main/java/org/springframework/scheduling/quartz/JobDetailBean.java
+++ /dev/null
@@ -1,169 +0,0 @@
-/*
- * Copyright 2002-2013 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.Map;
-
-import org.quartz.Job;
-import org.quartz.JobDetail;
-import org.quartz.Scheduler;
-
-import org.springframework.beans.factory.BeanNameAware;
-import org.springframework.beans.factory.InitializingBean;
-import org.springframework.context.ApplicationContext;
-import org.springframework.context.ApplicationContextAware;
-
-/**
- * Convenience subclass of Quartz's {@link org.quartz.JobDetail} class,
- * making bean-style usage easier.
- *
- *
{@code JobDetail} itself is already a JavaBean but lacks
- * sensible defaults. This class uses the Spring bean name as job name,
- * and the Quartz default group ("DEFAULT") as job group if not specified.
- *
- *
NOTE: This convenience subclass does not work against Quartz 2.0.
- * Use Quartz 2.0's native {@code JobDetailImpl} class or the new Quartz 2.0
- * builder API instead. Alternatively, switch to Spring's {@link JobDetailFactoryBean}
- * which largely is a drop-in replacement for this class and its properties and
- * consistently works against Quartz 1.x as well as Quartz 2.x.
- *
- * @author Juergen Hoeller
- * @since 18.02.2004
- * @see #setName
- * @see #setGroup
- * @see org.springframework.beans.factory.BeanNameAware
- * @see org.quartz.Scheduler#DEFAULT_GROUP
- */
-@SuppressWarnings({"serial", "rawtypes"})
-public class JobDetailBean extends JobDetail
- implements BeanNameAware, ApplicationContextAware, InitializingBean {
-
- private Class> actualJobClass;
-
- private String beanName;
-
- private ApplicationContext applicationContext;
-
- private String applicationContextJobDataKey;
-
-
- /**
- * Overridden to support any job class, to allow a custom JobFactory
- * to adapt the given job class to the Quartz Job interface.
- * @see SchedulerFactoryBean#setJobFactory
- */
- @Override
- public void setJobClass(Class jobClass) {
- if (jobClass != null && !Job.class.isAssignableFrom(jobClass)) {
- super.setJobClass(DelegatingJob.class);
- this.actualJobClass = jobClass;
- }
- else {
- super.setJobClass(jobClass);
- }
- }
-
- /**
- * Overridden to support any job class, to allow a custom JobFactory
- * to adapt the given job class to the Quartz Job interface.
- */
- @Override
- public Class getJobClass() {
- return (this.actualJobClass != null ? this.actualJobClass : super.getJobClass());
- }
-
- /**
- * Register objects in the JobDataMap via a given Map.
- *
These objects will be available to this Job only,
- * in contrast to objects in the SchedulerContext.
- *
Note: When using persistent Jobs whose JobDetail will be kept in the
- * database, do not put Spring-managed beans or an ApplicationContext
- * reference into the JobDataMap but rather into the SchedulerContext.
- * @param jobDataAsMap Map with String keys and any objects as values
- * (for example Spring-managed beans)
- * @see SchedulerFactoryBean#setSchedulerContextAsMap
- */
- public void setJobDataAsMap(Map jobDataAsMap) {
- getJobDataMap().putAll(jobDataAsMap);
- }
-
- /**
- * Set a list of JobListener names for this job, referring to
- * non-global JobListeners registered with the Scheduler.
- *
A JobListener name always refers to the name returned
- * by the JobListener implementation.
- * @see SchedulerFactoryBean#setJobListeners
- * @see org.quartz.JobListener#getName
- * @deprecated as of Spring 4.0, since it only works on Quartz 1.x
- */
- @Deprecated
- public void setJobListenerNames(String... names) {
- for (String name : names) {
- addJobListener(name);
- }
- }
-
- @Override
- public void setBeanName(String beanName) {
- this.beanName = beanName;
- }
-
- @Override
- public void setApplicationContext(ApplicationContext applicationContext) {
- this.applicationContext = applicationContext;
- }
-
- /**
- * Set the key of an ApplicationContext reference to expose in the JobDataMap,
- * for example "applicationContext". Default is none.
- * Only applicable when running in a Spring ApplicationContext.
- *
In case of a QuartzJobBean, the reference will be applied to the Job
- * instance as bean property. An "applicationContext" attribute will correspond
- * to a "setApplicationContext" method in that scenario.
- *
Note that BeanFactory callback interfaces like ApplicationContextAware
- * are not automatically applied to Quartz Job instances, because Quartz
- * itself is responsible for the lifecycle of its Jobs.
- *
Note: When using persistent job stores where JobDetail contents will
- * be kept in the database, do not put an ApplicationContext reference into
- * the JobDataMap but rather into the SchedulerContext.
- * @see SchedulerFactoryBean#setApplicationContextSchedulerContextKey
- * @see org.springframework.context.ApplicationContext
- */
- public void setApplicationContextJobDataKey(String applicationContextJobDataKey) {
- this.applicationContextJobDataKey = applicationContextJobDataKey;
- }
-
-
- @Override
- public void afterPropertiesSet() {
- if (getName() == null) {
- setName(this.beanName);
- }
- if (getGroup() == null) {
- setGroup(Scheduler.DEFAULT_GROUP);
- }
- if (this.applicationContextJobDataKey != null) {
- if (this.applicationContext == null) {
- throw new IllegalStateException(
- "JobDetailBean needs to be set up in an ApplicationContext " +
- "to be able to handle an 'applicationContextJobDataKey'");
- }
- getJobDataMap().put(this.applicationContextJobDataKey, this.applicationContext);
- }
- }
-
-}
diff --git a/spring-context-support/src/main/java/org/springframework/scheduling/quartz/JobDetailFactoryBean.java b/spring-context-support/src/main/java/org/springframework/scheduling/quartz/JobDetailFactoryBean.java
index 38d64537a25..50167a90127 100644
--- a/spring-context-support/src/main/java/org/springframework/scheduling/quartz/JobDetailFactoryBean.java
+++ b/spring-context-support/src/main/java/org/springframework/scheduling/quartz/JobDetailFactoryBean.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2013 the original author or authors.
+ * Copyright 2002-2014 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.
@@ -21,10 +21,8 @@ import java.util.Map;
import org.quartz.JobDataMap;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
+import org.quartz.impl.JobDetailImpl;
-import org.springframework.beans.BeanWrapper;
-import org.springframework.beans.BeanWrapperImpl;
-import org.springframework.beans.MutablePropertyValues;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InitializingBean;
@@ -39,9 +37,6 @@ import org.springframework.context.ApplicationContextAware;
* sensible defaults. This class uses the Spring bean name as job name,
* and the Quartz default group ("DEFAULT") as job group if not specified.
*
- *
NOTE: This FactoryBean works against both Quartz 1.x and Quartz 2.x,
- * in contrast to the older {@link JobDetailBean} class.
- *
* @author Juergen Hoeller
* @since 3.1
* @see #setName
@@ -181,6 +176,7 @@ public class JobDetailFactoryBean
@Override
+ @SuppressWarnings("unchecked")
public void afterPropertiesSet() {
if (this.name == null) {
this.name = this.beanName;
@@ -197,35 +193,15 @@ public class JobDetailFactoryBean
getJobDataMap().put(this.applicationContextJobDataKey, this.applicationContext);
}
- /*
JobDetailImpl jdi = new JobDetailImpl();
jdi.setName(this.name);
jdi.setGroup(this.group);
- jdi.setJobClass(this.jobClass);
+ jdi.setJobClass((Class) this.jobClass);
jdi.setJobDataMap(this.jobDataMap);
jdi.setDurability(this.durability);
+ jdi.setRequestsRecovery(this.requestsRecovery);
jdi.setDescription(this.description);
this.jobDetail = jdi;
- */
-
- Class> jobDetailClass;
- try {
- jobDetailClass = getClass().getClassLoader().loadClass("org.quartz.impl.JobDetailImpl");
- }
- catch (ClassNotFoundException ex) {
- jobDetailClass = JobDetail.class;
- }
- BeanWrapper bw = new BeanWrapperImpl(jobDetailClass);
- MutablePropertyValues pvs = new MutablePropertyValues();
- pvs.add("name", this.name);
- pvs.add("group", this.group);
- pvs.add("jobClass", this.jobClass);
- pvs.add("jobDataMap", this.jobDataMap);
- pvs.add("durability", this.durability);
- pvs.add("requestsRecovery", this.requestsRecovery);
- pvs.add("description", this.description);
- bw.setPropertyValues(pvs);
- this.jobDetail = (JobDetail) bw.getWrappedInstance();
}
diff --git a/spring-context-support/src/main/java/org/springframework/scheduling/quartz/LocalTaskExecutorThreadPool.java b/spring-context-support/src/main/java/org/springframework/scheduling/quartz/LocalTaskExecutorThreadPool.java
index ec3ccac53fd..03117880b40 100644
--- a/spring-context-support/src/main/java/org/springframework/scheduling/quartz/LocalTaskExecutorThreadPool.java
+++ b/spring-context-support/src/main/java/org/springframework/scheduling/quartz/LocalTaskExecutorThreadPool.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2012 the original author or authors.
+ * Copyright 2002-2014 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.
@@ -87,7 +87,7 @@ public class LocalTaskExecutorThreadPool implements ThreadPool {
@Override
public int blockForAvailableThreads() {
- // The present implementation always returns 1, making Quartz (1.6)
+ // The present implementation always returns 1, making Quartz
// always schedule any tasks that it feels like scheduling.
// This could be made smarter for specific TaskExecutors,
// for example calling {@code getMaximumPoolSize() - getActiveCount()}
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 2bf9d504dc4..f2381411a30 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
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2013 the original author or authors.
+ * Copyright 2002-2014 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.
@@ -17,20 +17,17 @@
package org.springframework.scheduling.quartz;
import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
-import org.quartz.JobDataMap;
+import org.quartz.DisallowConcurrentExecution;
import org.quartz.JobDetail;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
+import org.quartz.PersistJobDataAfterExecution;
import org.quartz.Scheduler;
-import org.quartz.StatefulJob;
+import org.quartz.impl.JobDetailImpl;
-import org.springframework.beans.BeanUtils;
-import org.springframework.beans.BeanWrapper;
-import org.springframework.beans.PropertyAccessorFactory;
import org.springframework.beans.factory.BeanClassLoaderAware;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
@@ -41,7 +38,6 @@ import org.springframework.beans.support.ArgumentConvertingMethodInvoker;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.MethodInvoker;
-import org.springframework.util.ReflectionUtils;
/**
* {@link org.springframework.beans.factory.FactoryBean} that exposes a
@@ -67,8 +63,7 @@ import org.springframework.util.ReflectionUtils;
* You need to implement your own Quartz Job as a thin wrapper for each case
* where you want a persistent job to delegate to a specific service method.
*
- *
Compatible with Quartz 1.8 as well as Quartz 2.0-2.2, as of Spring 4.0.
- * Note: Quartz 1.x support is deprecated - please upgrade to Quartz 2.0+.
+ *
Compatible with Quartz 2.1.4 and higher, as of Spring 4.1.
*
* @author Juergen Hoeller
* @author Alef Arendsen
@@ -81,28 +76,6 @@ import org.springframework.util.ReflectionUtils;
public class MethodInvokingJobDetailFactoryBean extends ArgumentConvertingMethodInvoker
implements FactoryBean, BeanNameAware, BeanClassLoaderAware, BeanFactoryAware, InitializingBean {
- private static Class> jobDetailImplClass;
-
- private static Method setResultMethod;
-
- static {
- try {
- jobDetailImplClass = Class.forName("org.quartz.impl.JobDetailImpl");
- }
- catch (ClassNotFoundException ex) {
- jobDetailImplClass = null;
- }
- try {
- Class> jobExecutionContextClass =
- QuartzJobBean.class.getClassLoader().loadClass("org.quartz.JobExecutionContext");
- setResultMethod = jobExecutionContextClass.getMethod("setResult", Object.class);
- }
- catch (Exception ex) {
- throw new IllegalStateException("Incompatible Quartz API: " + ex);
- }
- }
-
-
private String name;
private String group = Scheduler.DEFAULT_GROUP;
@@ -111,8 +84,6 @@ public class MethodInvokingJobDetailFactoryBean extends ArgumentConvertingMethod
private String targetBeanName;
- private String[] jobListenerNames;
-
private String beanName;
private ClassLoader beanClassLoader = ClassUtils.getDefaultClassLoader();
@@ -125,7 +96,6 @@ public class MethodInvokingJobDetailFactoryBean extends ArgumentConvertingMethod
/**
* Set the name of the job.
*
Default is the bean name of this FactoryBean.
- * @see org.quartz.JobDetail#setName
*/
public void setName(String name) {
this.name = name;
@@ -134,7 +104,6 @@ public class MethodInvokingJobDetailFactoryBean extends ArgumentConvertingMethod
/**
* Set the group of the job.
*
Default is the default group of the Scheduler.
- * @see org.quartz.JobDetail#setGroup
* @see org.quartz.Scheduler#DEFAULT_GROUP
*/
public void setGroup(String group) {
@@ -142,9 +111,10 @@ public class MethodInvokingJobDetailFactoryBean extends ArgumentConvertingMethod
}
/**
- * Specify whether or not multiple jobs should be run in a concurrent
- * fashion. The behavior when one does not want concurrent jobs to be
- * executed is realized through adding the {@link StatefulJob} interface.
+ * Specify whether or not multiple jobs should be run in a concurrent fashion.
+ * The behavior when one does not want concurrent jobs to be executed is
+ * realized through adding the {@code @PersistJobDataAfterExecution} and
+ * {@code @DisallowConcurrentExecution} markers.
* More information on stateful versus stateless jobs can be found
* here.
*
The default setting is to run jobs concurrently.
@@ -165,20 +135,6 @@ public class MethodInvokingJobDetailFactoryBean extends ArgumentConvertingMethod
this.targetBeanName = targetBeanName;
}
- /**
- * Set a list of JobListener names for this job, referring to
- * non-global JobListeners registered with the Scheduler.
- *
A JobListener name always refers to the name returned
- * by the JobListener implementation.
- * @see SchedulerFactoryBean#setJobListeners
- * @see org.quartz.JobListener#getName
- * @deprecated as of Spring 4.0, since it only works on Quartz 1.x
- */
- @Deprecated
- public void setJobListenerNames(String... names) {
- this.jobListenerNames = names;
- }
-
@Override
public void setBeanName(String beanName) {
this.beanName = beanName;
@@ -201,6 +157,7 @@ public class MethodInvokingJobDetailFactoryBean extends ArgumentConvertingMethod
@Override
+ @SuppressWarnings("unchecked")
public void afterPropertiesSet() throws ClassNotFoundException, NoSuchMethodException {
prepare();
@@ -211,34 +168,13 @@ public class MethodInvokingJobDetailFactoryBean extends ArgumentConvertingMethod
Class> jobClass = (this.concurrent ? MethodInvokingJob.class : StatefulMethodInvokingJob.class);
// Build JobDetail instance.
- if (jobDetailImplClass != null) {
- // Using Quartz 2.0 JobDetailImpl class...
- this.jobDetail = (JobDetail) BeanUtils.instantiate(jobDetailImplClass);
- BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(this.jobDetail);
- bw.setPropertyValue("name", name);
- bw.setPropertyValue("group", this.group);
- bw.setPropertyValue("jobClass", jobClass);
- bw.setPropertyValue("durability", true);
- ((JobDataMap) bw.getPropertyValue("jobDataMap")).put("methodInvoker", this);
- }
- else {
- // Using Quartz 1.x JobDetail class...
- this.jobDetail = new JobDetail(name, this.group, jobClass);
- this.jobDetail.setVolatility(true);
- this.jobDetail.setDurability(true);
- this.jobDetail.getJobDataMap().put("methodInvoker", this);
- }
-
- // Register job listener names.
- if (this.jobListenerNames != null) {
- for (String jobListenerName : this.jobListenerNames) {
- if (jobDetailImplClass != null) {
- throw new IllegalStateException("Non-global JobListeners not supported on Quartz 2 - " +
- "manually register a Matcher against the Quartz ListenerManager instead");
- }
- this.jobDetail.addJobListener(jobListenerName);
- }
- }
+ JobDetailImpl jdi = new JobDetailImpl();
+ jdi.setName(name);
+ jdi.setGroup(group);
+ jdi.setJobClass((Class) jobClass);
+ jdi.setDurability(true);
+ jdi.getJobDataMap().put("methodInvoker", this);
+ this.jobDetail = jdi;
postProcessJobDetail(this.jobDetail);
}
@@ -318,7 +254,7 @@ public class MethodInvokingJobDetailFactoryBean extends ArgumentConvertingMethod
@Override
protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
try {
- ReflectionUtils.invokeMethod(setResultMethod, context, this.methodInvoker.invoke());
+ context.setResult(this.methodInvoker.invoke());
}
catch (InvocationTargetException ex) {
if (ex.getTargetException() instanceof JobExecutionException) {
@@ -343,7 +279,9 @@ public class MethodInvokingJobDetailFactoryBean extends ArgumentConvertingMethod
* Quartz checks whether or not jobs are stateful and if so,
* won't let jobs interfere with each other.
*/
- public static class StatefulMethodInvokingJob extends MethodInvokingJob implements StatefulJob {
+ @PersistJobDataAfterExecution
+ @DisallowConcurrentExecution
+ public static class StatefulMethodInvokingJob extends MethodInvokingJob {
// No implementation, just an addition of the tag interface StatefulJob
// in order to allow stateful method invoking jobs.
diff --git a/spring-context-support/src/main/java/org/springframework/scheduling/quartz/QuartzJobBean.java b/spring-context-support/src/main/java/org/springframework/scheduling/quartz/QuartzJobBean.java
index c78498f5d00..8f823d24928 100644
--- a/spring-context-support/src/main/java/org/springframework/scheduling/quartz/QuartzJobBean.java
+++ b/spring-context-support/src/main/java/org/springframework/scheduling/quartz/QuartzJobBean.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2013 the original author or authors.
+ * Copyright 2002-2014 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.
@@ -16,19 +16,14 @@
package org.springframework.scheduling.quartz;
-import java.lang.reflect.Method;
-import java.util.Map;
-
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
-import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.springframework.beans.BeanWrapper;
import org.springframework.beans.MutablePropertyValues;
import org.springframework.beans.PropertyAccessorFactory;
-import org.springframework.util.ReflectionUtils;
/**
* Simple implementation of the Quartz Job interface, applying the
@@ -43,15 +38,9 @@ import org.springframework.util.ReflectionUtils;
* i.e. a method "setMyParam(int)". This will also work for complex
* types like business objects etc.
*
- *
Note: The QuartzJobBean class itself only implements the standard
- * Quartz {@link org.quartz.Job} interface. Let your subclass explicitly
- * implement the Quartz {@link org.quartz.StatefulJob} interface to
- * mark your concrete job bean as stateful.
- *
- *
Note that as of Spring 2.0 and Quartz 1.5, the preferred way
- * to apply dependency injection to Job instances is via a JobFactory:
- * that is, to specify {@link SpringBeanJobFactory} as Quartz JobFactory
- * (typically via
+ *
Note that the preferred way to apply dependency injection
+ * to Job instances is via a JobFactory: that is, to specify
+ * {@link SpringBeanJobFactory} as Quartz JobFactory (typically via
* {@link SchedulerFactoryBean#setJobFactory} SchedulerFactoryBean's "jobFactory" property}).
* This allows to implement dependency-injected Quartz Jobs without
* a dependency on Spring base classes.
@@ -60,33 +49,12 @@ import org.springframework.util.ReflectionUtils;
* @since 18.02.2004
* @see org.quartz.JobExecutionContext#getMergedJobDataMap()
* @see org.quartz.Scheduler#getContext()
- * @see JobDetailBean#setJobDataAsMap
- * @see SimpleTriggerBean#setJobDataAsMap
- * @see CronTriggerBean#setJobDataAsMap
* @see SchedulerFactoryBean#setSchedulerContextAsMap
* @see SpringBeanJobFactory
* @see SchedulerFactoryBean#setJobFactory
*/
public abstract class QuartzJobBean implements Job {
- private static final Method getSchedulerMethod;
-
- private static final Method getMergedJobDataMapMethod;
-
-
- static {
- try {
- Class> jobExecutionContextClass =
- QuartzJobBean.class.getClassLoader().loadClass("org.quartz.JobExecutionContext");
- getSchedulerMethod = jobExecutionContextClass.getMethod("getScheduler");
- getMergedJobDataMapMethod = jobExecutionContextClass.getMethod("getMergedJobDataMap");
- }
- catch (Exception ex) {
- throw new IllegalStateException("Incompatible Quartz API: " + ex);
- }
- }
-
-
/**
* This implementation applies the passed-in job data map as bean property
* values, and delegates to {@code executeInternal} afterwards.
@@ -95,14 +63,10 @@ public abstract class QuartzJobBean implements Job {
@Override
public final void execute(JobExecutionContext context) throws JobExecutionException {
try {
- // Reflectively adapting to differences between Quartz 1.x and Quartz 2.0...
- Scheduler scheduler = (Scheduler) ReflectionUtils.invokeMethod(getSchedulerMethod, context);
- Map, ?> mergedJobDataMap = (Map, ?>) ReflectionUtils.invokeMethod(getMergedJobDataMapMethod, context);
-
BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(this);
MutablePropertyValues pvs = new MutablePropertyValues();
- pvs.addPropertyValues(scheduler.getContext());
- pvs.addPropertyValues(mergedJobDataMap);
+ pvs.addPropertyValues(context.getScheduler().getContext());
+ pvs.addPropertyValues(context.getMergedJobDataMap());
bw.setPropertyValues(pvs, true);
}
catch (SchedulerException ex) {
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 a86a4b054a7..d93aa31f5f1 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
@@ -16,7 +16,6 @@
package org.springframework.scheduling.quartz;
-import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
@@ -28,6 +27,7 @@ import org.apache.commons.logging.LogFactory;
import org.quartz.Calendar;
import org.quartz.JobDetail;
import org.quartz.JobListener;
+import org.quartz.ListenerManager;
import org.quartz.ObjectAlreadyExistsException;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
@@ -43,7 +43,6 @@ import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionException;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;
-import org.springframework.util.ReflectionUtils;
/**
* Common base class for accessing a Quartz Scheduler, i.e. for registering jobs,
@@ -52,8 +51,7 @@ import org.springframework.util.ReflectionUtils;
*
For concrete usage, check out the {@link SchedulerFactoryBean} and
* {@link SchedulerAccessorBean} classes.
*
- *
Compatible with Quartz 1.8 as well as Quartz 2.0-2.2, as of Spring 4.0.
- * Note: Quartz 1.x support is deprecated - please upgrade to Quartz 2.0+.
+ *
Compatible with Quartz 2.1.4 and higher, as of Spring 4.1.
*
* @author Juergen Hoeller
* @author Stephane Nicoll
@@ -61,23 +59,6 @@ import org.springframework.util.ReflectionUtils;
*/
public abstract class SchedulerAccessor implements ResourceLoaderAware {
- private static Class> jobKeyClass;
-
- private static Class> triggerKeyClass;
-
- static {
- // Quartz 2.0 job/trigger key available?
- try {
- jobKeyClass = Class.forName("org.quartz.JobKey");
- triggerKeyClass = Class.forName("org.quartz.TriggerKey");
- }
- catch (ClassNotFoundException ex) {
- jobKeyClass = null;
- triggerKeyClass = null;
- }
- }
-
-
protected final Log logger = LogFactory.getLog(getClass());
private boolean overwriteExistingJobs = false;
@@ -94,24 +75,13 @@ public abstract class SchedulerAccessor implements ResourceLoaderAware {
private JobListener[] globalJobListeners;
- private JobListener[] jobListeners;
-
private TriggerListener[] globalTriggerListeners;
- private TriggerListener[] triggerListeners;
-
private PlatformTransactionManager transactionManager;
protected ResourceLoader resourceLoader;
- public SchedulerAccessor() {
- if (jobKeyClass == null && logger.isInfoEnabled()) {
- logger.info("Spring's Quartz 1.x support is deprecated - please upgrade to Quartz 2.0+");
- }
- }
-
-
/**
* Set whether any jobs defined on this SchedulerFactoryBean should overwrite
* existing job definitions. Default is "false", to not overwrite already
@@ -151,8 +121,6 @@ public abstract class SchedulerAccessor implements ResourceLoaderAware {
* in combination with the Trigger.
* @see #setTriggers
* @see org.quartz.JobDetail
- * @see JobDetailBean
- * @see JobDetailAwareTrigger
*/
public void setJobDetails(JobDetail... jobDetails) {
// Use modifiable ArrayList here, to allow for further adding of
@@ -180,15 +148,11 @@ public abstract class SchedulerAccessor implements ResourceLoaderAware {
* "jobDetails" property of this FactoryBean.
* @see #setJobDetails
* @see org.quartz.JobDetail
- * @see JobDetailAwareTrigger
- * @see CronTriggerBean
- * @see SimpleTriggerBean
*/
public void setTriggers(Trigger... triggers) {
this.triggers = Arrays.asList(triggers);
}
-
/**
* Specify Quartz SchedulerListeners to be registered with the Scheduler.
*/
@@ -204,21 +168,6 @@ public abstract class SchedulerAccessor implements ResourceLoaderAware {
this.globalJobListeners = globalJobListeners;
}
- /**
- * 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 JobDetailBean#setJobListenerNames
- * @deprecated as of Spring 4.0, since it only works on Quartz 1.x
- */
- @Deprecated
- public void setJobListeners(JobListener... jobListeners) {
- this.jobListeners = jobListeners;
- }
-
/**
* Specify global Quartz TriggerListeners to be registered with the Scheduler.
* Such TriggerListeners will apply to all Triggers in the Scheduler.
@@ -227,23 +176,6 @@ public abstract class SchedulerAccessor implements ResourceLoaderAware {
this.globalTriggerListeners = globalTriggerListeners;
}
- /**
- * 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 CronTriggerBean#setTriggerListenerNames
- * @see SimpleTriggerBean#setTriggerListenerNames
- * @deprecated as of Spring 4.0, since it only works on Quartz 1.x
- */
- @Deprecated
- public void setTriggerListeners(TriggerListener... triggerListeners) {
- this.triggerListeners = triggerListeners;
- }
-
-
/**
* Set the transaction manager to be used for registering jobs and triggers
* that are defined by this SchedulerFactoryBean. Default is none; setting
@@ -338,7 +270,7 @@ public abstract class SchedulerAccessor implements ResourceLoaderAware {
* @see #setOverwriteExistingJobs
*/
private boolean addJobToScheduler(JobDetail jobDetail) throws SchedulerException {
- if (this.overwriteExistingJobs || !jobDetailExists(jobDetail)) {
+ if (this.overwriteExistingJobs || getScheduler().getJobDetail(jobDetail.getKey()) == null) {
getScheduler().addJob(jobDetail, true);
return true;
}
@@ -356,10 +288,10 @@ public abstract class SchedulerAccessor implements ResourceLoaderAware {
* @see #setOverwriteExistingJobs
*/
private boolean addTriggerToScheduler(Trigger trigger) throws SchedulerException {
- boolean triggerExists = triggerExists(trigger);
+ boolean triggerExists = (getScheduler().getTrigger(trigger.getKey()) != null);
if (!triggerExists || this.overwriteExistingJobs) {
// Check if the Trigger is aware of an associated JobDetail.
- JobDetail jobDetail = findJobDetail(trigger);
+ JobDetail jobDetail = (JobDetail) trigger.getJobDataMap().remove("jobDetail");
if (jobDetail != null) {
// Automatically register the JobDetail too.
if (!this.jobDetails.contains(jobDetail) && addJobToScheduler(jobDetail)) {
@@ -376,12 +308,12 @@ public abstract class SchedulerAccessor implements ResourceLoaderAware {
ex.getMessage() + " - can safely be ignored");
}
if (this.overwriteExistingJobs) {
- rescheduleJob(trigger);
+ getScheduler().rescheduleJob(trigger.getKey(), trigger);
}
}
}
else {
- rescheduleJob(trigger);
+ getScheduler().rescheduleJob(trigger.getKey(), trigger);
}
return true;
}
@@ -390,160 +322,25 @@ public abstract class SchedulerAccessor implements ResourceLoaderAware {
}
}
- private JobDetail findJobDetail(Trigger trigger) {
- if (trigger instanceof JobDetailAwareTrigger) {
- return ((JobDetailAwareTrigger) trigger).getJobDetail();
- }
- else {
- try {
- Map, ?> jobDataMap =
- (Map, ?>) ReflectionUtils.invokeMethod(Trigger.class.getMethod("getJobDataMap"), trigger);
- return (JobDetail) jobDataMap.remove(JobDetailAwareTrigger.JOB_DETAIL_KEY);
- }
- catch (NoSuchMethodException ex) {
- throw new IllegalStateException("Inconsistent Quartz API: " + ex);
- }
- }
- }
-
-
- // Reflectively adapting to differences between Quartz 1.x and Quartz 2.0...
- private boolean jobDetailExists(JobDetail jobDetail) throws SchedulerException {
- if (jobKeyClass != null) {
- try {
- Method getJobDetail = Scheduler.class.getMethod("getJobDetail", jobKeyClass);
- Object key = ReflectionUtils.invokeMethod(JobDetail.class.getMethod("getKey"), jobDetail);
- return (ReflectionUtils.invokeMethod(getJobDetail, getScheduler(), key) != null);
- }
- catch (NoSuchMethodException ex) {
- throw new IllegalStateException("Inconsistent Quartz 2.0 API: " + ex);
- }
- }
- else {
- return (getScheduler().getJobDetail(jobDetail.getName(), jobDetail.getGroup()) != null);
- }
- }
-
- // Reflectively adapting to differences between Quartz 1.x and Quartz 2.0...
- private boolean triggerExists(Trigger trigger) throws SchedulerException {
- if (triggerKeyClass != null) {
- try {
- Method getTrigger = Scheduler.class.getMethod("getTrigger", triggerKeyClass);
- Object key = ReflectionUtils.invokeMethod(Trigger.class.getMethod("getKey"), trigger);
- return (ReflectionUtils.invokeMethod(getTrigger, getScheduler(), key) != null);
- }
- catch (NoSuchMethodException ex) {
- throw new IllegalStateException("Inconsistent Quartz 2.0 API: " + ex);
- }
- }
- else {
- return (getScheduler().getTrigger(trigger.getName(), trigger.getGroup()) != null);
- }
- }
-
- // Reflectively adapting to differences between Quartz 1.x and Quartz 2.0...
- private void rescheduleJob(Trigger trigger) throws SchedulerException {
- if (triggerKeyClass != null) {
- try {
- Method rescheduleJob = Scheduler.class.getMethod("rescheduleJob", triggerKeyClass, Trigger.class);
- Object key = ReflectionUtils.invokeMethod(Trigger.class.getMethod("getKey"), trigger);
- ReflectionUtils.invokeMethod(rescheduleJob, getScheduler(), key, trigger);
- }
- catch (NoSuchMethodException ex) {
- throw new IllegalStateException("Inconsistent Quartz 2.0 API: " + ex);
- }
- }
- else {
- getScheduler().rescheduleJob(trigger.getName(), trigger.getGroup(), trigger);
- }
- }
-
-
/**
* Register all specified listeners with the Scheduler.
*/
protected void registerListeners() throws SchedulerException {
- Object target;
- boolean quartz2;
- try {
- Method getListenerManager = Scheduler.class.getMethod("getListenerManager");
- target = ReflectionUtils.invokeMethod(getListenerManager, getScheduler());
- quartz2 = true;
- }
- catch (NoSuchMethodException ex) {
- target = getScheduler();
- quartz2 = false;
- }
- Class> targetClass = target.getClass();
-
- try {
- if (this.schedulerListeners != null) {
- Method addSchedulerListener = targetClass.getMethod("addSchedulerListener", SchedulerListener.class);
- for (SchedulerListener listener : this.schedulerListeners) {
- ReflectionUtils.invokeMethod(addSchedulerListener, target, listener);
- }
+ ListenerManager listenerManager = getScheduler().getListenerManager();
+ if (this.schedulerListeners != null) {
+ for (SchedulerListener listener : this.schedulerListeners) {
+ listenerManager.addSchedulerListener(listener);
}
- if (this.globalJobListeners != null) {
- Method addJobListener;
- if (quartz2) {
- // addJobListener(JobListener) only introduced as late as Quartz 2.2, so we need
- // to fall back to the Quartz 2.0/2.1 compatible variant with an empty matchers List
- addJobListener = targetClass.getMethod("addJobListener", JobListener.class, List.class);
- }
- else {
- addJobListener = targetClass.getMethod("addGlobalJobListener", JobListener.class);
- }
- for (JobListener listener : this.globalJobListeners) {
- if (quartz2) {
- List> emptyMatchers = new LinkedList