diff --git a/spring-context/src/main/java/org/springframework/scheduling/concurrent/ScheduledExecutorFactoryBean.java b/spring-context/src/main/java/org/springframework/scheduling/concurrent/ScheduledExecutorFactoryBean.java index 2705bcefdd6..e514b9cb986 100644 --- a/spring-context/src/main/java/org/springframework/scheduling/concurrent/ScheduledExecutorFactoryBean.java +++ b/spring-context/src/main/java/org/springframework/scheduling/concurrent/ScheduledExecutorFactoryBean.java @@ -28,6 +28,7 @@ import org.springframework.lang.UsesJava7; import org.springframework.scheduling.support.DelegatingErrorHandlingRunnable; import org.springframework.scheduling.support.TaskUtils; import org.springframework.util.Assert; +import org.springframework.util.ClassUtils; import org.springframework.util.ObjectUtils; /** @@ -67,9 +68,14 @@ import org.springframework.util.ObjectUtils; public class ScheduledExecutorFactoryBean extends ExecutorConfigurationSupport implements FactoryBean { + // ScheduledThreadPoolExecutor.setRemoveOnCancelPolicy(boolean) only available on JDK 1.7+ + private static final boolean setRemoveOnCancelPolicyAvailable = + ClassUtils.hasMethod(ScheduledThreadPoolExecutor.class, "setRemoveOnCancelPolicy", boolean.class); + + private int poolSize = 1; - private Boolean removeOnCancelPolicy; + private boolean removeOnCancelPolicy; private ScheduledExecutorTask[] scheduledExecutorTasks; @@ -143,8 +149,13 @@ public class ScheduledExecutorFactoryBean extends ExecutorConfigurationSupport ScheduledExecutorService executor = createExecutor(this.poolSize, threadFactory, rejectedExecutionHandler); - if (executor instanceof ScheduledThreadPoolExecutor && this.removeOnCancelPolicy != null) { - ((ScheduledThreadPoolExecutor) executor).setRemoveOnCancelPolicy(this.removeOnCancelPolicy); + if (this.removeOnCancelPolicy) { + if (setRemoveOnCancelPolicyAvailable && executor instanceof ScheduledThreadPoolExecutor) { + ((ScheduledThreadPoolExecutor) executor).setRemoveOnCancelPolicy(true); + } + else { + logger.info("Could not apply remove-on-cancel policy - not a Java 7+ ScheduledThreadPoolExecutor"); + } } // Register specified ScheduledExecutorTasks, if necessary. @@ -216,6 +227,7 @@ public class ScheduledExecutorFactoryBean extends ExecutorConfigurationSupport new DelegatingErrorHandlingRunnable(task.getRunnable(), TaskUtils.LOG_AND_PROPAGATE_ERROR_HANDLER)); } + @Override public ScheduledExecutorService getObject() { return this.exposedExecutor; diff --git a/spring-context/src/main/java/org/springframework/scheduling/concurrent/ThreadPoolTaskScheduler.java b/spring-context/src/main/java/org/springframework/scheduling/concurrent/ThreadPoolTaskScheduler.java index 3bc8dbb8879..ab8caab3578 100644 --- a/spring-context/src/main/java/org/springframework/scheduling/concurrent/ThreadPoolTaskScheduler.java +++ b/spring-context/src/main/java/org/springframework/scheduling/concurrent/ThreadPoolTaskScheduler.java @@ -37,6 +37,7 @@ import org.springframework.scheduling.TaskScheduler; import org.springframework.scheduling.Trigger; import org.springframework.scheduling.support.TaskUtils; import org.springframework.util.Assert; +import org.springframework.util.ClassUtils; import org.springframework.util.ErrorHandler; import org.springframework.util.concurrent.ListenableFuture; import org.springframework.util.concurrent.ListenableFutureTask; @@ -57,9 +58,14 @@ import org.springframework.util.concurrent.ListenableFutureTask; public class ThreadPoolTaskScheduler extends ExecutorConfigurationSupport implements AsyncListenableTaskExecutor, SchedulingTaskExecutor, TaskScheduler { + // ScheduledThreadPoolExecutor.setRemoveOnCancelPolicy(boolean) only available on JDK 1.7+ + private static final boolean setRemoveOnCancelPolicyAvailable = + ClassUtils.hasMethod(ScheduledThreadPoolExecutor.class, "setRemoveOnCancelPolicy", boolean.class); + + private volatile int poolSize = 1; - private volatile Boolean removeOnCancelPolicy; + private volatile boolean removeOnCancelPolicy; private volatile ScheduledExecutorService scheduledExecutor; @@ -87,19 +93,22 @@ public class ThreadPoolTaskScheduler extends ExecutorConfigurationSupport @UsesJava7 public void setRemoveOnCancelPolicy(boolean removeOnCancelPolicy) { this.removeOnCancelPolicy = removeOnCancelPolicy; - if (this.scheduledExecutor instanceof ScheduledThreadPoolExecutor) { + if (setRemoveOnCancelPolicyAvailable && this.scheduledExecutor instanceof ScheduledThreadPoolExecutor) { ((ScheduledThreadPoolExecutor) this.scheduledExecutor).setRemoveOnCancelPolicy(removeOnCancelPolicy); } + else if (removeOnCancelPolicy && this.scheduledExecutor != null) { + logger.info("Could not apply remove-on-cancel policy - not a Java 7+ ScheduledThreadPoolExecutor"); + } } /** * Set a custom {@link ErrorHandler} strategy. */ public void setErrorHandler(ErrorHandler errorHandler) { - Assert.notNull(errorHandler, "'errorHandler' must not be null"); this.errorHandler = errorHandler; } + @UsesJava7 @Override protected ExecutorService initializeExecutor( @@ -107,8 +116,13 @@ public class ThreadPoolTaskScheduler extends ExecutorConfigurationSupport this.scheduledExecutor = createExecutor(this.poolSize, threadFactory, rejectedExecutionHandler); - if (this.scheduledExecutor instanceof ScheduledThreadPoolExecutor && this.removeOnCancelPolicy != null) { - ((ScheduledThreadPoolExecutor) this.scheduledExecutor).setRemoveOnCancelPolicy(this.removeOnCancelPolicy); + if (this.removeOnCancelPolicy) { + if (setRemoveOnCancelPolicyAvailable && this.scheduledExecutor instanceof ScheduledThreadPoolExecutor) { + ((ScheduledThreadPoolExecutor) this.scheduledExecutor).setRemoveOnCancelPolicy(true); + } + else { + logger.info("Could not apply remove-on-cancel policy - not a Java 7+ ScheduledThreadPoolExecutor"); + } } return this.scheduledExecutor; @@ -175,8 +189,8 @@ public class ThreadPoolTaskScheduler extends ExecutorConfigurationSupport @UsesJava7 public boolean isRemoveOnCancelPolicy() { if (this.scheduledExecutor == null) { - // Not initialized yet: return false (the default of the executor) - return false; + // Not initialized yet: return our setting for the time being. + return (setRemoveOnCancelPolicyAvailable && this.removeOnCancelPolicy); } return getScheduledThreadPoolExecutor().getRemoveOnCancelPolicy(); }