From 0bd69fded820ad5fa2a0c550a5369fc59fba3b5d Mon Sep 17 00:00:00 2001 From: Stephane Nicoll Date: Sun, 4 Nov 2018 09:58:41 +0100 Subject: [PATCH] Fix detection of ScheduledExecutorService `@EnableScheduling` detects primarily a suitable `TaskScheduler` in the context and fallbacks to the presence of a `ScheduledExecutorService` if that is not the case. This commit improves the auto-configuration to back off when such scheduled executor service is present, so that the framework initialization code can pick it up as usual. Closes gh-15032 --- .../task/TaskSchedulingAutoConfiguration.java | 5 +++- .../TaskSchedulingAutoConfigurationTests.java | 25 +++++++++++++++++++ .../main/asciidoc/spring-boot-features.adoc | 4 +-- 3 files changed, 31 insertions(+), 3 deletions(-) diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/task/TaskSchedulingAutoConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/task/TaskSchedulingAutoConfiguration.java index 6c02a63427..f87ace5d99 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/task/TaskSchedulingAutoConfiguration.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/task/TaskSchedulingAutoConfiguration.java @@ -16,6 +16,8 @@ package org.springframework.boot.autoconfigure.task; +import java.util.concurrent.ScheduledExecutorService; + import org.springframework.beans.factory.ObjectProvider; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; @@ -44,7 +46,8 @@ public class TaskSchedulingAutoConfiguration { @Bean @ConditionalOnBean(name = TaskManagementConfigUtils.SCHEDULED_ANNOTATION_PROCESSOR_BEAN_NAME) - @ConditionalOnMissingBean({ SchedulingConfigurer.class, TaskScheduler.class }) + @ConditionalOnMissingBean({ SchedulingConfigurer.class, TaskScheduler.class, + ScheduledExecutorService.class }) public ThreadPoolTaskScheduler taskScheduler(TaskSchedulerBuilder builder) { return builder.build(); } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/task/TaskSchedulingAutoConfigurationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/task/TaskSchedulingAutoConfigurationTests.java index afb863aa28..456ebb7d10 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/task/TaskSchedulingAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/task/TaskSchedulingAutoConfigurationTests.java @@ -18,6 +18,8 @@ package org.springframework.boot.autoconfigure.task; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; import org.junit.Test; @@ -96,6 +98,19 @@ public class TaskSchedulingAutoConfigurationTests { }); } + @Test + public void enableSchedulingWithExistingScheduledExecutorServiceBacksOff() { + this.contextRunner.withUserConfiguration(SchedulingConfiguration.class, + ScheduledExecutorServiceConfiguration.class).run((context) -> { + assertThat(context).doesNotHaveBean(TaskScheduler.class); + assertThat(context).hasSingleBean(ScheduledExecutorService.class); + TestBean bean = context.getBean(TestBean.class); + Thread.sleep(15); + assertThat(bean.threadNames) + .allMatch((name) -> name.contains("pool-")); + }); + } + @Test public void enableSchedulingWithConfigurerBacksOff() { this.contextRunner.withUserConfiguration(SchedulingConfiguration.class, @@ -123,6 +138,16 @@ public class TaskSchedulingAutoConfigurationTests { } + @Configuration + static class ScheduledExecutorServiceConfiguration { + + @Bean + public ScheduledExecutorService customScheduledExecutorService() { + return Executors.newScheduledThreadPool(2); + } + + } + @Configuration static class TaskSchedulerCustomizerConfiguration { diff --git a/spring-boot-project/spring-boot-docs/src/main/asciidoc/spring-boot-features.adoc b/spring-boot-project/spring-boot-docs/src/main/asciidoc/spring-boot-features.adoc index f663d8eaf8..67d8aae868 100644 --- a/spring-boot-project/spring-boot-docs/src/main/asciidoc/spring-boot-features.adoc +++ b/spring-boot-project/spring-boot-docs/src/main/asciidoc/spring-boot-features.adoc @@ -6382,8 +6382,8 @@ A `ThreadPoolTaskScheduler` can also be auto-configured if need to be associated scheduled task execution (`@EnableScheduling`). The thread pool uses one thread by default and those settings can be fine-tuned using the `spring.task.scheduling` namespace. -Both a `TaskExecutorBuilder` bean and a `TaskSchedulerBuilder` bean are made available in the -context if a custom executor or scheduler needs to be created. +Both a `TaskExecutorBuilder` bean and a `TaskSchedulerBuilder` bean are made available in +the context if a custom executor or scheduler needs to be created.