Skip to content

Commit 0c680d6

Browse files
committed
Defensively use setRemoveOnCancelPolicy for JDK 6 compatibility
Issue: SPR-12238 (cherry picked from commit e003d21)
1 parent b87329c commit 0c680d6

File tree

2 files changed

+53
-23
lines changed

2 files changed

+53
-23
lines changed

spring-context/src/main/java/org/springframework/scheduling/concurrent/ScheduledExecutorFactoryBean.java

+24-12
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
import org.springframework.scheduling.support.DelegatingErrorHandlingRunnable;
2828
import org.springframework.scheduling.support.TaskUtils;
2929
import org.springframework.util.Assert;
30+
import org.springframework.util.ClassUtils;
3031
import org.springframework.util.ObjectUtils;
3132

3233
/**
@@ -66,12 +67,17 @@
6667
public class ScheduledExecutorFactoryBean extends ExecutorConfigurationSupport
6768
implements FactoryBean<ScheduledExecutorService> {
6869

69-
private int poolSize = 1;
70+
// ScheduledThreadPoolExecutor.setRemoveOnCancelPolicy(boolean) only available on JDK 7+
71+
private static final boolean setRemoveOnCancelPolicyAvailable =
72+
ClassUtils.hasMethod(ScheduledThreadPoolExecutor.class, "setRemoveOnCancelPolicy", boolean.class);
73+
7074

71-
private Boolean removeOnCancelPolicy;
75+
private int poolSize = 1;
7276

7377
private ScheduledExecutorTask[] scheduledExecutorTasks;
7478

79+
private boolean removeOnCancelPolicy = false;
80+
7581
private boolean continueScheduledExecutionAfterException = false;
7682

7783
private boolean exposeUnconfigurableExecutor = false;
@@ -88,14 +94,6 @@ public void setPoolSize(int poolSize) {
8894
this.poolSize = poolSize;
8995
}
9096

91-
/**
92-
* Set the same property on ScheduledExecutorService (JDK 1.7+).
93-
* There is no default. If not set, the executor property is not set.
94-
*/
95-
public void setRemoveOnCancelPolicy(boolean removeOnCancelPolicy) {
96-
this.removeOnCancelPolicy = removeOnCancelPolicy;
97-
}
98-
9997
/**
10098
* Register a list of ScheduledExecutorTask objects with the ScheduledExecutorService
10199
* that this FactoryBean creates. Depending on each ScheduledExecutorTask's settings,
@@ -108,6 +106,15 @@ public void setScheduledExecutorTasks(ScheduledExecutorTask... scheduledExecutor
108106
this.scheduledExecutorTasks = scheduledExecutorTasks;
109107
}
110108

109+
/**
110+
* Set the remove-on-cancel mode on {@link ScheduledThreadPoolExecutor} (JDK 7+).
111+
* <p>Default is {@code false}. If set to {@code true}, the target executor will be
112+
* switched into remove-on-cancel mode (if possible, with a soft fallback otherwise).
113+
*/
114+
public void setRemoveOnCancelPolicy(boolean removeOnCancelPolicy) {
115+
this.removeOnCancelPolicy = removeOnCancelPolicy;
116+
}
117+
111118
/**
112119
* Specify whether to continue the execution of a scheduled task
113120
* after it threw an exception.
@@ -141,8 +148,13 @@ protected ExecutorService initializeExecutor(
141148
ScheduledExecutorService executor =
142149
createExecutor(this.poolSize, threadFactory, rejectedExecutionHandler);
143150

144-
if (executor instanceof ScheduledThreadPoolExecutor && this.removeOnCancelPolicy != null) {
145-
((ScheduledThreadPoolExecutor) executor).setRemoveOnCancelPolicy(this.removeOnCancelPolicy);
151+
if (this.removeOnCancelPolicy) {
152+
if (setRemoveOnCancelPolicyAvailable && executor instanceof ScheduledThreadPoolExecutor) {
153+
((ScheduledThreadPoolExecutor) executor).setRemoveOnCancelPolicy(true);
154+
}
155+
else {
156+
logger.info("Could not apply remove-on-cancel policy - not a Java 7+ ScheduledThreadPoolExecutor");
157+
}
146158
}
147159

148160
// Register specified ScheduledExecutorTasks, if necessary.

spring-context/src/main/java/org/springframework/scheduling/concurrent/ThreadPoolTaskScheduler.java

+29-11
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
import org.springframework.scheduling.Trigger;
3737
import org.springframework.scheduling.support.TaskUtils;
3838
import org.springframework.util.Assert;
39+
import org.springframework.util.ClassUtils;
3940
import org.springframework.util.ErrorHandler;
4041
import org.springframework.util.concurrent.ListenableFuture;
4142
import org.springframework.util.concurrent.ListenableFutureTask;
@@ -56,9 +57,14 @@
5657
public class ThreadPoolTaskScheduler extends ExecutorConfigurationSupport
5758
implements AsyncListenableTaskExecutor, SchedulingTaskExecutor, TaskScheduler {
5859

60+
// ScheduledThreadPoolExecutor.setRemoveOnCancelPolicy(boolean) only available on JDK 7+
61+
private static final boolean setRemoveOnCancelPolicyAvailable =
62+
ClassUtils.hasMethod(ScheduledThreadPoolExecutor.class, "setRemoveOnCancelPolicy", boolean.class);
63+
64+
5965
private volatile int poolSize = 1;
6066

61-
private volatile Boolean removeOnCancelPolicy;
67+
private volatile boolean removeOnCancelPolicy = false;
6268

6369
private volatile ScheduledExecutorService scheduledExecutor;
6470

@@ -79,33 +85,42 @@ public void setPoolSize(int poolSize) {
7985
}
8086

8187
/**
82-
* Set the same property on ScheduledExecutorService (JDK 1.7+).
83-
* There is no default. If not set, the executor property is not set.
88+
* Set the remove-on-cancel mode on {@link ScheduledThreadPoolExecutor} (JDK 7+).
89+
* <p>Default is {@code false}. If set to {@code true}, the target executor will be
90+
* switched into remove-on-cancel mode (if possible, with a soft fallback otherwise).
8491
* <p><b>This setting can be modified at runtime, for example through JMX.</b>
8592
*/
8693
public void setRemoveOnCancelPolicy(boolean removeOnCancelPolicy) {
8794
this.removeOnCancelPolicy = removeOnCancelPolicy;
88-
if (this.scheduledExecutor instanceof ScheduledThreadPoolExecutor) {
95+
if (setRemoveOnCancelPolicyAvailable && this.scheduledExecutor instanceof ScheduledThreadPoolExecutor) {
8996
((ScheduledThreadPoolExecutor) this.scheduledExecutor).setRemoveOnCancelPolicy(removeOnCancelPolicy);
9097
}
98+
else if (removeOnCancelPolicy && this.scheduledExecutor != null) {
99+
logger.info("Could not apply remove-on-cancel policy - not a Java 7+ ScheduledThreadPoolExecutor");
100+
}
91101
}
92102

93103
/**
94104
* Set a custom {@link ErrorHandler} strategy.
95105
*/
96106
public void setErrorHandler(ErrorHandler errorHandler) {
97-
Assert.notNull(errorHandler, "'errorHandler' must not be null");
98107
this.errorHandler = errorHandler;
99108
}
100109

110+
101111
@Override
102112
protected ExecutorService initializeExecutor(
103113
ThreadFactory threadFactory, RejectedExecutionHandler rejectedExecutionHandler) {
104114

105115
this.scheduledExecutor = createExecutor(this.poolSize, threadFactory, rejectedExecutionHandler);
106116

107-
if (this.scheduledExecutor instanceof ScheduledThreadPoolExecutor && this.removeOnCancelPolicy != null) {
108-
((ScheduledThreadPoolExecutor) this.scheduledExecutor).setRemoveOnCancelPolicy(this.removeOnCancelPolicy);
117+
if (this.removeOnCancelPolicy) {
118+
if (setRemoveOnCancelPolicyAvailable && this.scheduledExecutor instanceof ScheduledThreadPoolExecutor) {
119+
((ScheduledThreadPoolExecutor) this.scheduledExecutor).setRemoveOnCancelPolicy(true);
120+
}
121+
else {
122+
logger.info("Could not apply remove-on-cancel policy - not a Java 7+ ScheduledThreadPoolExecutor");
123+
}
109124
}
110125

111126
return this.scheduledExecutor;
@@ -166,14 +181,17 @@ public int getPoolSize() {
166181
}
167182

168183
/**
169-
* Return the current setting of removeOnCancelPolicy.
170-
* <p>Requires an underlying {@link ScheduledThreadPoolExecutor} and JDK 1.7+.
184+
* Return the current setting for the remove-on-cancel mode.
185+
* <p>Requires an underlying {@link ScheduledThreadPoolExecutor}.
171186
*/
172187
public boolean isRemoveOnCancelPolicy() {
173-
if (this.scheduledExecutor == null) {
174-
// Not initialized yet: return false (the default of the executor)
188+
if (!setRemoveOnCancelPolicyAvailable) {
175189
return false;
176190
}
191+
if (this.scheduledExecutor == null) {
192+
// Not initialized yet: return our setting for the time being.
193+
return this.removeOnCancelPolicy;
194+
}
177195
return getScheduledThreadPoolExecutor().getRemoveOnCancelPolicy();
178196
}
179197

0 commit comments

Comments
 (0)