Stop associating an Executor bean to Quartz
This commits make sure that the Quartz auto-configuration no longer associates an `Executor` bean if present in the context as Quartz offers properties to tune it, which would mutate and lead to unexpected results. Closes gh-12823
This commit is contained in:
parent
e4e56bbcc3
commit
38bd4bd58c
|
@ -19,7 +19,6 @@ package org.springframework.boot.autoconfigure.quartz;
|
|||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
|
@ -64,8 +63,6 @@ public class QuartzAutoConfiguration {
|
|||
|
||||
private final List<SchedulerFactoryBeanCustomizer> customizers;
|
||||
|
||||
private final Executor taskExecutor;
|
||||
|
||||
private final JobDetail[] jobDetails;
|
||||
|
||||
private final Map<String, Calendar> calendars;
|
||||
|
@ -76,12 +73,11 @@ public class QuartzAutoConfiguration {
|
|||
|
||||
public QuartzAutoConfiguration(QuartzProperties properties,
|
||||
ObjectProvider<List<SchedulerFactoryBeanCustomizer>> customizers,
|
||||
ObjectProvider<Executor> taskExecutor, ObjectProvider<JobDetail[]> jobDetails,
|
||||
ObjectProvider<JobDetail[]> jobDetails,
|
||||
ObjectProvider<Map<String, Calendar>> calendars,
|
||||
ObjectProvider<Trigger[]> triggers, ApplicationContext applicationContext) {
|
||||
this.properties = properties;
|
||||
this.customizers = customizers.getIfAvailable();
|
||||
this.taskExecutor = taskExecutor.getIfUnique();
|
||||
this.jobDetails = jobDetails.getIfAvailable();
|
||||
this.calendars = calendars.getIfAvailable();
|
||||
this.triggers = triggers.getIfAvailable();
|
||||
|
@ -98,9 +94,6 @@ public class QuartzAutoConfiguration {
|
|||
schedulerFactoryBean
|
||||
.setQuartzProperties(asProperties(this.properties.getProperties()));
|
||||
}
|
||||
if (this.taskExecutor != null) {
|
||||
schedulerFactoryBean.setTaskExecutor(this.taskExecutor);
|
||||
}
|
||||
if (this.jobDetails != null && this.jobDetails.length > 0) {
|
||||
schedulerFactoryBean.setJobDetails(this.jobDetails);
|
||||
}
|
||||
|
|
|
@ -17,7 +17,6 @@
|
|||
package org.springframework.boot.autoconfigure.quartz;
|
||||
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
|
@ -36,7 +35,6 @@ 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.AutoConfigurations;
|
||||
|
@ -54,12 +52,13 @@ import org.springframework.context.annotation.Primary;
|
|||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
import org.springframework.scheduling.quartz.LocalDataSourceJobStore;
|
||||
import org.springframework.scheduling.quartz.LocalTaskExecutorThreadPool;
|
||||
import org.springframework.scheduling.quartz.QuartzJobBean;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.hamcrest.CoreMatchers.containsString;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verifyZeroInteractions;
|
||||
|
||||
/**
|
||||
* Tests for {@link QuartzAutoConfiguration}.
|
||||
|
@ -144,53 +143,15 @@ public class QuartzAutoConfigurationTests {
|
|||
|
||||
@Test
|
||||
public void withTaskExecutor() {
|
||||
this.contextRunner.withUserConfiguration(QuartzExecutorConfiguration.class)
|
||||
this.contextRunner.withUserConfiguration(MockExecutorConfiguration.class)
|
||||
.withPropertyValues(
|
||||
"spring.quartz.properties.org.quartz.threadPool.threadCount=50")
|
||||
.run((context) -> {
|
||||
assertThat(context).hasSingleBean(Scheduler.class);
|
||||
Scheduler scheduler = context.getBean(Scheduler.class);
|
||||
assertThat(scheduler.getMetaData().getThreadPoolClass())
|
||||
.isEqualTo(LocalTaskExecutorThreadPool.class);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void withMultipleTaskExecutors() {
|
||||
this.contextRunner
|
||||
.withUserConfiguration(QuartzMultipleExecutorsConfiguration.class)
|
||||
.run((context) -> {
|
||||
assertThat(context.getBeansOfType(Executor.class)).hasSize(2);
|
||||
assertThat(context).hasSingleBean(Scheduler.class);
|
||||
Scheduler scheduler = context.getBean(Scheduler.class);
|
||||
assertThat(scheduler.getMetaData().getThreadPoolClass())
|
||||
.isEqualTo(SimpleThreadPool.class);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void withMultipleTaskExecutorsWithPrimary() {
|
||||
this.contextRunner
|
||||
.withUserConfiguration(
|
||||
QuartzMultipleExecutorsWithPrimaryConfiguration.class)
|
||||
.run((context) -> {
|
||||
assertThat(context.getBeansOfType(Executor.class)).hasSize(2);
|
||||
assertThat(context).hasSingleBean(Scheduler.class);
|
||||
Scheduler scheduler = context.getBean(Scheduler.class);
|
||||
assertThat(scheduler.getMetaData().getThreadPoolClass())
|
||||
.isEqualTo(LocalTaskExecutorThreadPool.class);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void withMultipleTaskExecutorsWithCustomizer() {
|
||||
this.contextRunner
|
||||
.withUserConfiguration(
|
||||
QuartzMultipleExecutorsWithCustomizerConfiguration.class)
|
||||
.run((context) -> {
|
||||
assertThat(context.getBeansOfType(Executor.class)).hasSize(3);
|
||||
assertThat(context).hasSingleBean(Scheduler.class);
|
||||
Scheduler scheduler = context.getBean(Scheduler.class);
|
||||
assertThat(scheduler.getMetaData().getThreadPoolClass())
|
||||
.isEqualTo(LocalTaskExecutorThreadPool.class);
|
||||
assertThat(scheduler.getMetaData().getThreadPoolSize()).isEqualTo(50);
|
||||
Executor executor = context.getBean(Executor.class);
|
||||
verifyZeroInteractions(executor);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -304,51 +265,11 @@ public class QuartzAutoConfigurationTests {
|
|||
}
|
||||
|
||||
@Configuration
|
||||
protected static class QuartzExecutorConfiguration extends BaseQuartzConfiguration {
|
||||
protected static class MockExecutorConfiguration extends BaseQuartzConfiguration {
|
||||
|
||||
@Bean
|
||||
public Executor executor() {
|
||||
return Executors.newSingleThreadExecutor();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@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());
|
||||
return mock(Executor.class);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -5876,6 +5876,10 @@ Quartz Scheduler configuration can be customized by using Quartz configuration p
|
|||
()`spring.quartz.properties.*`) and `SchedulerFactoryBeanCustomizer` beans, which allow
|
||||
programmatic `SchedulerFactoryBean` customization.
|
||||
|
||||
NOTE: In particular, an `Executor` bean is not associated with the scheduler as Quartz
|
||||
offers a way to configure the scheduler via `spring.quartz.properties`. If you need
|
||||
to customize the task executor, consider implementing `SchedulerFactoryBeanCustomizer`.
|
||||
|
||||
Jobs can define setters to inject data map properties. Regular beans can also be injected
|
||||
in a similar manner, as shown in the following example:
|
||||
|
||||
|
|
Loading…
Reference in New Issue