Skip to content

Commit 69c9abf

Browse files
committed
updated Quartz support package for full Quartz 2.0 support (SPR-8275)
1 parent cc7c64a commit 69c9abf

File tree

9 files changed

+222
-57
lines changed

9 files changed

+222
-57
lines changed

org.springframework.context.support/src/main/java/org/springframework/scheduling/quartz/AdaptableJobFactory.java

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,17 +16,21 @@
1616

1717
package org.springframework.scheduling.quartz;
1818

19+
import java.lang.reflect.Method;
20+
1921
import org.quartz.Job;
2022
import org.quartz.Scheduler;
2123
import org.quartz.SchedulerException;
2224
import org.quartz.spi.JobFactory;
2325
import org.quartz.spi.TriggerFiredBundle;
2426

27+
import org.springframework.util.ReflectionUtils;
28+
2529
/**
2630
* JobFactory implementation that supports {@link java.lang.Runnable}
2731
* objects as well as standard Quartz {@link org.quartz.Job} instances.
2832
*
29-
* <p>Compatible with Quartz 1.x as well as Quartz 2.0, as of Spring 3.1.
33+
* <p>Compatible with Quartz 1.5+ as well as Quartz 2.0, as of Spring 3.1.
3034
*
3135
* @author Juergen Hoeller
3236
* @since 2.0
@@ -65,7 +69,12 @@ public Job newJob(TriggerFiredBundle bundle) throws SchedulerException {
6569
* @throws Exception if job instantiation failed
6670
*/
6771
protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception {
68-
return bundle.getJobDetail().getJobClass().newInstance();
72+
// Reflectively adapting to differences between Quartz 1.x and Quartz 2.0...
73+
Method getJobDetail = bundle.getClass().getMethod("getJobDetail");
74+
Object jobDetail = ReflectionUtils.invokeMethod(getJobDetail, bundle);
75+
Method getJobClass = jobDetail.getClass().getMethod("getJobClass");
76+
Class jobClass = (Class) ReflectionUtils.invokeMethod(getJobClass, jobDetail);
77+
return jobClass.newInstance();
6978
}
7079

7180
/**

org.springframework.context.support/src/main/java/org/springframework/scheduling/quartz/CronTriggerBean.java

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2009 the original author or authors.
2+
* Copyright 2002-2011 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -43,10 +43,9 @@
4343
* to automatically register a trigger for the corresponding JobDetail,
4444
* instead of registering the JobDetail separately.
4545
*
46-
* <p><b>NOTE:</b> This convenience subclass does not work with trigger
47-
* persistence in Quartz 1.6, due to a change in Quartz's trigger handling.
48-
* Use Quartz 1.5 if you rely on trigger persistence based on this class,
49-
* or the standard Quartz {@link org.quartz.CronTrigger} class instead.
46+
* <p><b>NOTE: This convenience subclass does not work against Quartz 2.0.</b>
47+
* Use Quartz 2.0's native <code>CronTriggerImpl</code> class or the new
48+
* Quartz 2.0 builder API instead.
5049
*
5150
* @author Juergen Hoeller
5251
* @since 18.02.2004

org.springframework.context.support/src/main/java/org/springframework/scheduling/quartz/JobDetailBean.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2009 the original author or authors.
2+
* Copyright 2002-2011 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -35,6 +35,10 @@
3535
* sensible defaults. This class uses the Spring bean name as job name,
3636
* and the Quartz default group ("DEFAULT") as job group if not specified.
3737
*
38+
* <p><b>NOTE: This convenience subclass does not work against Quartz 2.0.</b>
39+
* Use Quartz 2.0's native <code>JobDetailImpl</code> class or the new
40+
* Quartz 2.0 builder API instead.
41+
*
3842
* @author Juergen Hoeller
3943
* @since 18.02.2004
4044
* @see #setName

org.springframework.context.support/src/main/java/org/springframework/scheduling/quartz/MethodInvokingJobDetailFactoryBean.java

Lines changed: 44 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2009 the original author or authors.
2+
* Copyright 2002-2011 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -20,12 +20,16 @@
2020

2121
import org.apache.commons.logging.Log;
2222
import org.apache.commons.logging.LogFactory;
23+
import org.quartz.JobDataMap;
2324
import org.quartz.JobDetail;
2425
import org.quartz.JobExecutionContext;
2526
import org.quartz.JobExecutionException;
2627
import org.quartz.Scheduler;
2728
import org.quartz.StatefulJob;
2829

30+
import org.springframework.beans.BeanUtils;
31+
import org.springframework.beans.BeanWrapper;
32+
import org.springframework.beans.PropertyAccessorFactory;
2933
import org.springframework.beans.factory.BeanClassLoaderAware;
3034
import org.springframework.beans.factory.BeanFactory;
3135
import org.springframework.beans.factory.BeanFactoryAware;
@@ -61,6 +65,8 @@
6165
* You need to implement your own Quartz Job as a thin wrapper for each case
6266
* where you want a persistent job to delegate to a specific service method.
6367
*
68+
* <p>Compatible with Quartz 1.5+ as well as Quartz 2.0, as of Spring 3.1.
69+
*
6470
* @author Juergen Hoeller
6571
* @author Alef Arendsen
6672
* @since 18.02.2004
@@ -70,7 +76,19 @@
7076
* @see #setConcurrent
7177
*/
7278
public class MethodInvokingJobDetailFactoryBean extends ArgumentConvertingMethodInvoker
73-
implements FactoryBean<Object>, BeanNameAware, BeanClassLoaderAware, BeanFactoryAware, InitializingBean {
79+
implements FactoryBean<JobDetail>, BeanNameAware, BeanClassLoaderAware, BeanFactoryAware, InitializingBean {
80+
81+
private static Class<?> jobDetailImplClass;
82+
83+
static {
84+
try {
85+
jobDetailImplClass = Class.forName("org.quartz.impl.JobDetailImpl");
86+
}
87+
catch (ClassNotFoundException ex) {
88+
jobDetailImplClass = null;
89+
}
90+
}
91+
7492

7593
private String name;
7694

@@ -174,14 +192,31 @@ public void afterPropertiesSet() throws ClassNotFoundException, NoSuchMethodExce
174192
Class jobClass = (this.concurrent ? MethodInvokingJob.class : StatefulMethodInvokingJob.class);
175193

176194
// Build JobDetail instance.
177-
this.jobDetail = new JobDetail(name, this.group, jobClass);
178-
this.jobDetail.getJobDataMap().put("methodInvoker", this);
179-
this.jobDetail.setVolatility(true);
180-
this.jobDetail.setDurability(true);
195+
if (jobDetailImplClass != null) {
196+
// Using Quartz 2.0 JobDetailImpl class...
197+
Object jobDetail = BeanUtils.instantiate(jobDetailImplClass);
198+
BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(jobDetail);
199+
bw.setPropertyValue("name", name);
200+
bw.setPropertyValue("group", this.group);
201+
bw.setPropertyValue("jobClass", jobClass);
202+
bw.setPropertyValue("durability", true);
203+
((JobDataMap) bw.getPropertyValue("jobDataMap")).put("methodInvoker", this);
204+
}
205+
else {
206+
// Using Quartz 1.x JobDetail class...
207+
this.jobDetail = new JobDetail(name, this.group, jobClass);
208+
this.jobDetail.setVolatility(true);
209+
this.jobDetail.setDurability(true);
210+
this.jobDetail.getJobDataMap().put("methodInvoker", this);
211+
}
181212

182213
// Register job listener names.
183214
if (this.jobListenerNames != null) {
184215
for (String jobListenerName : this.jobListenerNames) {
216+
if (jobDetailImplClass != null) {
217+
throw new IllegalStateException("Non-global JobListeners not supported on Quartz 2 - " +
218+
"manually register a Matcher against the Quartz ListenerManager instead");
219+
}
185220
this.jobDetail.addJobListener(jobListenerName);
186221
}
187222
}
@@ -225,12 +260,12 @@ public Object getTargetObject() {
225260
}
226261

227262

228-
public Object getObject() {
263+
public JobDetail getObject() {
229264
return this.jobDetail;
230265
}
231266

232-
public Class<?> getObjectType() {
233-
return JobDetail.class;
267+
public Class<? extends JobDetail> getObjectType() {
268+
return (this.jobDetail != null ? this.jobDetail.getClass() : JobDetail.class);
234269
}
235270

236271
public boolean isSingleton() {

0 commit comments

Comments
 (0)