From a80348753df58dc0c5aadd0364183ab5e60da7c9 Mon Sep 17 00:00:00 2001 From: Vedran Pavic Date: Thu, 8 Jun 2017 09:48:30 +0200 Subject: [PATCH] Fix `QuartzAutoConfigurtion` failure with multiple `Executor` beans `QuartzAutoConfigurtion` currently blows up if there are multiple `Executor` beans in the context. This commit changes the configuration to retrieve `Executor` bean using `ObjectProvider#getIfUnique` which won't fail in scenarios where there are multiple `Executor` beans with none marked as `@Primary`. Closes gh-9434 --- .../quartz/QuartzAutoConfiguration.java | 2 +- .../quartz/QuartzAutoConfigurationTests.java | 72 +++++++++++++++++++ 2 files changed, 73 insertions(+), 1 deletion(-) diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/quartz/QuartzAutoConfiguration.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/quartz/QuartzAutoConfiguration.java index 38307f3a5a..ce49baf2ee 100644 --- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/quartz/QuartzAutoConfiguration.java +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/quartz/QuartzAutoConfiguration.java @@ -81,7 +81,7 @@ public class QuartzAutoConfiguration { ObjectProvider triggers, ApplicationContext applicationContext) { this.properties = properties; this.customizers = customizers.getIfAvailable(); - this.taskExecutor = taskExecutor.getIfAvailable(); + this.taskExecutor = taskExecutor.getIfUnique(); this.jobDetails = jobDetails.getIfAvailable(); this.calendars = calendars.getIfAvailable(); this.triggers = triggers.getIfAvailable(); diff --git a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/quartz/QuartzAutoConfigurationTests.java b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/quartz/QuartzAutoConfigurationTests.java index 4ff0d41b43..a4b8811e73 100644 --- a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/quartz/QuartzAutoConfigurationTests.java +++ b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/quartz/QuartzAutoConfigurationTests.java @@ -40,6 +40,7 @@ import org.quartz.TriggerKey; import org.quartz.impl.calendar.MonthlyCalendar; import org.quartz.impl.calendar.WeeklyCalendar; import org.quartz.simpl.RAMJobStore; +import org.quartz.simpl.SimpleThreadPool; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration; @@ -51,6 +52,7 @@ import org.springframework.context.annotation.AnnotationConfigApplicationContext import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; +import org.springframework.context.annotation.Primary; import org.springframework.core.env.Environment; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.scheduling.quartz.LocalDataSourceJobStore; @@ -145,6 +147,36 @@ public class QuartzAutoConfigurationTests { .isEqualTo(LocalTaskExecutorThreadPool.class); } + @Test + public void withMultipleTaskExecutors() throws Exception { + load(QuartzMultipleExecutorsConfiguration.class); + assertThat(this.context.getBeansOfType(Executor.class)).hasSize(2); + assertThat(this.context.getBeansOfType(Scheduler.class)).hasSize(1); + Scheduler scheduler = this.context.getBean(Scheduler.class); + assertThat(scheduler.getMetaData().getThreadPoolClass()) + .isEqualTo(SimpleThreadPool.class); + } + + @Test + public void withMultipleTaskExecutorsWithPrimary() throws Exception { + load(QuartzMultipleExecutorsWithPrimaryConfiguration.class); + assertThat(this.context.getBeansOfType(Executor.class)).hasSize(2); + assertThat(this.context.getBeansOfType(Scheduler.class)).hasSize(1); + Scheduler scheduler = this.context.getBean(Scheduler.class); + assertThat(scheduler.getMetaData().getThreadPoolClass()) + .isEqualTo(LocalTaskExecutorThreadPool.class); + } + + @Test + public void withMultipleTaskExecutorsWithCustomizer() throws Exception { + load(QuartzMultipleExecutorsWithCustomizerConfiguration.class); + assertThat(this.context.getBeansOfType(Executor.class)).hasSize(3); + assertThat(this.context.getBeansOfType(Scheduler.class)).hasSize(1); + Scheduler scheduler = this.context.getBean(Scheduler.class); + assertThat(scheduler.getMetaData().getThreadPoolClass()) + .isEqualTo(LocalTaskExecutorThreadPool.class); + } + @Test public void withConfiguredJobAndTrigger() throws Exception { load(QuartzFullConfiguration.class, "test-name=withConfiguredJobAndTrigger"); @@ -269,6 +301,46 @@ public class QuartzAutoConfigurationTests { } + @Configuration + protected static class QuartzMultipleExecutorsConfiguration + extends QuartzExecutorConfiguration { + + @Bean + public Executor anotherExecutor() { + return Executors.newSingleThreadExecutor(); + } + + } + + @Configuration + protected static class QuartzMultipleExecutorsWithPrimaryConfiguration + extends QuartzExecutorConfiguration { + + @Bean + @Primary + public Executor primaryExecutor() { + return Executors.newSingleThreadExecutor(); + } + + } + + @Configuration + protected static class QuartzMultipleExecutorsWithCustomizerConfiguration + extends QuartzMultipleExecutorsConfiguration { + + @Bean + public Executor yetAnotherExecutor() { + return Executors.newSingleThreadExecutor(); + } + + @Bean + public SchedulerFactoryBeanCustomizer customizer() { + return schedulerFactoryBean -> schedulerFactoryBean + .setTaskExecutor(yetAnotherExecutor()); + } + + } + @Configuration protected static class QuartzCustomConfiguration extends BaseQuartzConfiguration {