Skip to content

Commit 1dcbbff

Browse files
committed
Ensure that SchedulerFactoryBean and Scheduler beans depend on the
Flyway and Liquibase. see gh-17528
1 parent 74d0035 commit 1dcbbff

File tree

2 files changed

+96
-7
lines changed

2 files changed

+96
-7
lines changed

spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/quartz/QuartzAutoConfiguration.java

Lines changed: 64 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,19 +21,25 @@
2121

2222
import javax.sql.DataSource;
2323

24+
import liquibase.integration.spring.SpringLiquibase;
25+
import org.flywaydb.core.Flyway;
2426
import org.quartz.Calendar;
2527
import org.quartz.JobDetail;
2628
import org.quartz.Scheduler;
2729
import org.quartz.Trigger;
2830

2931
import org.springframework.beans.factory.ObjectProvider;
32+
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
3033
import org.springframework.boot.autoconfigure.AbstractDependsOnBeanFactoryPostProcessor;
3134
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
3235
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
3336
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
3437
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
3538
import org.springframework.boot.autoconfigure.condition.ConditionalOnSingleCandidate;
39+
import org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration;
40+
import org.springframework.boot.autoconfigure.flyway.FlywayMigrationInitializer;
3641
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
42+
import org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration;
3743
import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration;
3844
import org.springframework.boot.context.properties.EnableConfigurationProperties;
3945
import org.springframework.context.ApplicationContext;
@@ -55,7 +61,8 @@
5561
@Configuration(proxyBeanMethods = false)
5662
@ConditionalOnClass({ Scheduler.class, SchedulerFactoryBean.class, PlatformTransactionManager.class })
5763
@EnableConfigurationProperties(QuartzProperties.class)
58-
@AutoConfigureAfter({ DataSourceAutoConfiguration.class, HibernateJpaAutoConfiguration.class })
64+
@AutoConfigureAfter({ DataSourceAutoConfiguration.class, HibernateJpaAutoConfiguration.class,
65+
LiquibaseAutoConfiguration.class, FlywayAutoConfiguration.class })
5966
public class QuartzAutoConfiguration {
6067

6168
@Bean
@@ -125,16 +132,66 @@ public QuartzDataSourceInitializer quartzDataSourceInitializer(DataSource dataSo
125132
return new QuartzDataSourceInitializer(dataSourceToUse, resourceLoader, properties);
126133
}
127134

128-
@Bean
129-
public static DataSourceInitializerSchedulerDependencyPostProcessor dataSourceInitializerSchedulerDependencyPostProcessor() {
130-
return new DataSourceInitializerSchedulerDependencyPostProcessor();
135+
/**
136+
* Additional configuration to ensure that {@link SchedulerFactoryBean} and
137+
* {@link Scheduler} beans depend on the {@link QuartzDataSourceInitializer}
138+
* bean(s).
139+
*/
140+
@Configuration(proxyBeanMethods = false)
141+
protected static class SchedulerQuartzDataSourceInitializerDependencyConfiguration
142+
extends AbstractSchedulerDependsOnBeanFactoryPostProcessor {
143+
144+
SchedulerQuartzDataSourceInitializerDependencyConfiguration() {
145+
super(QuartzDataSourceInitializer.class);
146+
}
147+
148+
}
149+
150+
/**
151+
* Additional configuration to ensure that {@link SchedulerFactoryBean} and
152+
* {@link Scheduler} beans depend on the {@link SpringLiquibase} bean(s).
153+
*/
154+
@Configuration(proxyBeanMethods = false)
155+
@ConditionalOnClass(SpringLiquibase.class)
156+
protected static class SchedulerSpringLiquibaseDependencyConfiguration
157+
extends AbstractSchedulerDependsOnBeanFactoryPostProcessor {
158+
159+
SchedulerSpringLiquibaseDependencyConfiguration() {
160+
super(SpringLiquibase.class);
161+
}
162+
163+
}
164+
165+
/**
166+
* Additional configuration to ensure that {@link SchedulerFactoryBean} and
167+
* {@link Scheduler} beans depend on the {@link FlywayMigrationInitializer}
168+
* bean(s).
169+
*/
170+
@Configuration(proxyBeanMethods = false)
171+
@ConditionalOnClass(Flyway.class)
172+
protected static class SchedulerFlywayMigrationInitializerDependencyConfiguration
173+
extends AbstractSchedulerDependsOnBeanFactoryPostProcessor {
174+
175+
SchedulerFlywayMigrationInitializerDependencyConfiguration() {
176+
super(FlywayMigrationInitializer.class);
177+
}
178+
131179
}
132180

133-
private static class DataSourceInitializerSchedulerDependencyPostProcessor
181+
/**
182+
* {@link BeanFactoryPostProcessor} that can be used to declare that all
183+
* {@link Scheduler} and {@link SchedulerFactoryBean} beans should "depend on" one
184+
* or more specific beans.
185+
*/
186+
protected abstract static class AbstractSchedulerDependsOnBeanFactoryPostProcessor
134187
extends AbstractDependsOnBeanFactoryPostProcessor {
135188

136-
DataSourceInitializerSchedulerDependencyPostProcessor() {
137-
super(Scheduler.class, SchedulerFactoryBean.class, "quartzDataSourceInitializer");
189+
/**
190+
* Create an instance with dependency types.
191+
* @param dependencyTypes dependency types
192+
*/
193+
protected AbstractSchedulerDependsOnBeanFactoryPostProcessor(Class<?>... dependencyTypes) {
194+
super(Scheduler.class, SchedulerFactoryBean.class, dependencyTypes);
138195
}
139196

140197
}

spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/quartz/QuartzAutoConfigurationTests.java

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,16 @@
1616

1717
package org.springframework.boot.autoconfigure.quartz;
1818

19+
import java.io.InputStream;
20+
import java.nio.file.Files;
21+
import java.nio.file.Path;
1922
import java.util.concurrent.Executor;
2023

2124
import javax.sql.DataSource;
2225

2326
import org.junit.jupiter.api.Test;
2427
import org.junit.jupiter.api.extension.ExtendWith;
28+
import org.junit.jupiter.api.io.TempDir;
2529
import org.quartz.Calendar;
2630
import org.quartz.JobBuilder;
2731
import org.quartz.JobDetail;
@@ -39,9 +43,11 @@
3943

4044
import org.springframework.beans.factory.annotation.Autowired;
4145
import org.springframework.boot.autoconfigure.AutoConfigurations;
46+
import org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration;
4247
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
4348
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
4449
import org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration;
50+
import org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration;
4551
import org.springframework.boot.test.context.assertj.AssertableApplicationContext;
4652
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
4753
import org.springframework.boot.test.context.runner.ContextConsumer;
@@ -52,6 +58,7 @@
5258
import org.springframework.context.annotation.Import;
5359
import org.springframework.context.annotation.Primary;
5460
import org.springframework.core.env.Environment;
61+
import org.springframework.core.io.ClassPathResource;
5562
import org.springframework.jdbc.core.JdbcTemplate;
5663
import org.springframework.scheduling.quartz.LocalDataSourceJobStore;
5764
import org.springframework.scheduling.quartz.QuartzJobBean;
@@ -102,6 +109,31 @@ void withDataSource() {
102109
.withPropertyValues("spring.quartz.job-store-type=jdbc").run(assertDataSourceJobStore("dataSource"));
103110
}
104111

112+
@Test
113+
void withLiquibase() {
114+
this.contextRunner.withUserConfiguration(QuartzJobsConfiguration.class)
115+
.withConfiguration(AutoConfigurations.of(DataSourceAutoConfiguration.class,
116+
DataSourceTransactionManagerAutoConfiguration.class, LiquibaseAutoConfiguration.class))
117+
.withPropertyValues("spring.quartz.job-store-type=jdbc", "spring.quartz.jdbc.initialize-schema=never",
118+
"spring.liquibase.change-log=classpath:org/quartz/impl/jdbcjobstore/liquibase.quartz.init.xml"
119+
120+
).run(assertDataSourceJobStore("dataSource"));
121+
}
122+
123+
@Test
124+
void withFlyway(@TempDir Path flywayDir) throws Exception {
125+
try (InputStream stream = new ClassPathResource("org/quartz/impl/jdbcjobstore/tables_h2.sql")
126+
.getInputStream()) {
127+
Files.copy(stream, flywayDir.resolve("V2__quartz.sql"));
128+
}
129+
this.contextRunner.withUserConfiguration(QuartzJobsConfiguration.class)
130+
.withConfiguration(AutoConfigurations.of(DataSourceAutoConfiguration.class,
131+
DataSourceTransactionManagerAutoConfiguration.class, FlywayAutoConfiguration.class))
132+
.withPropertyValues("spring.quartz.job-store-type=jdbc", "spring.quartz.jdbc.initialize-schema=never",
133+
"spring.flyway.locations=filesystem:" + flywayDir, "spring.flyway.baseline-on-migrate=true")
134+
.run(assertDataSourceJobStore("dataSource"));
135+
}
136+
105137
@Test
106138
void withDataSourceNoTransactionManager() {
107139
this.contextRunner.withUserConfiguration(QuartzJobsConfiguration.class)

0 commit comments

Comments
 (0)