From c58853f5e5891147c43487fac3a249ba5c98de0c Mon Sep 17 00:00:00 2001 From: Daniil Pozdeev Date: Thu, 14 Oct 2021 17:20:41 +0300 Subject: [PATCH] Use LocalDataSourceJobStore only if one is not set via Quartz properties Prior to this commit, Spring's SchedulerFactoryBean always set the "org.quartz.jobStore.class" property to LocalDataSourceJobStore even if the user had already specified a custom JobStore implementation via the Quartz properties file or Properties object, thereby effectively ignoring the user configuration. This commit addresses this by configuring Quartz to use Spring's LocalDataSourceJobStore only if a JobStore has not already been specified via user configuration. Closes gh-27560 --- .../quartz/SchedulerFactoryBean.java | 2 +- .../scheduling/quartz/QuartzSupportTests.java | 27 +++++++++++++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/spring-context-support/src/main/java/org/springframework/scheduling/quartz/SchedulerFactoryBean.java b/spring-context-support/src/main/java/org/springframework/scheduling/quartz/SchedulerFactoryBean.java index 50ef456cfc..cb4c0d2a3a 100644 --- a/spring-context-support/src/main/java/org/springframework/scheduling/quartz/SchedulerFactoryBean.java +++ b/spring-context-support/src/main/java/org/springframework/scheduling/quartz/SchedulerFactoryBean.java @@ -570,7 +570,7 @@ public class SchedulerFactoryBean extends SchedulerAccessor implements FactoryBe CollectionUtils.mergePropertiesIntoMap(this.quartzProperties, mergedProps); if (this.dataSource != null) { - mergedProps.setProperty(StdSchedulerFactory.PROP_JOB_STORE_CLASS, LocalDataSourceJobStore.class.getName()); + mergedProps.putIfAbsent(StdSchedulerFactory.PROP_JOB_STORE_CLASS, LocalDataSourceJobStore.class.getName()); } // Determine scheduler name across local settings and Quartz properties... diff --git a/spring-context-support/src/test/java/org/springframework/scheduling/quartz/QuartzSupportTests.java b/spring-context-support/src/test/java/org/springframework/scheduling/quartz/QuartzSupportTests.java index 6c7d5b8691..a300ce010a 100644 --- a/spring-context-support/src/test/java/org/springframework/scheduling/quartz/QuartzSupportTests.java +++ b/spring-context-support/src/test/java/org/springframework/scheduling/quartz/QuartzSupportTests.java @@ -18,6 +18,7 @@ package org.springframework.scheduling.quartz; import java.util.HashMap; import java.util.Map; +import java.util.Properties; import javax.sql.DataSource; @@ -30,6 +31,7 @@ import org.quartz.SchedulerContext; import org.quartz.SchedulerFactory; import org.quartz.impl.JobDetailImpl; import org.quartz.impl.SchedulerRepository; +import org.quartz.impl.jdbcjobstore.JobStoreTX; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.support.BeanDefinitionBuilder; @@ -40,6 +42,8 @@ import org.springframework.context.support.StaticApplicationContext; import org.springframework.core.task.TaskExecutor; import org.springframework.core.testfixture.EnabledForTestGroups; import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.datasource.embedded.EmbeddedDatabase; +import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; @@ -396,6 +400,29 @@ public class QuartzSupportTests { } } + @Test + public void schedulerFactoryBeanWithCustomJobStore() throws Exception { + StaticApplicationContext context = new StaticApplicationContext(); + + final String dbName = "mydb"; + final EmbeddedDatabase database = new EmbeddedDatabaseBuilder().setName(dbName).build(); + + final Properties properties = new Properties(); + properties.setProperty("org.quartz.jobStore.class", JobStoreTX.class.getName()); + properties.setProperty("org.quartz.jobStore.dataSource", dbName); + + BeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition(SchedulerFactoryBean.class) + .addPropertyValue("autoStartup", false) + .addPropertyValue("dataSource", database) + .addPropertyValue("quartzProperties", properties) + .getBeanDefinition(); + context.registerBeanDefinition("scheduler", beanDefinition); + + Scheduler bean = context.getBean("scheduler", Scheduler.class); + + assertThat(bean.getMetaData().getJobStoreClass()).isEqualTo(JobStoreTX.class); + } + private ClassPathXmlApplicationContext context(String path) { return new ClassPathXmlApplicationContext(path, getClass()); }