Skip to content

Commit c55200d

Browse files
eddumelendezwilkinsona
authored andcommitted
Ensure that Flyway/Liquibase run before jOOQ's DSLContext is used
See gh-25279
1 parent 08802d3 commit c55200d

File tree

5 files changed

+180
-7
lines changed

5 files changed

+180
-7
lines changed

spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/flyway/FlywayAutoConfiguration.java

Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2012-2020 the original author or authors.
2+
* Copyright 2012-2021 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -33,6 +33,7 @@
3333
import org.flywaydb.core.api.callback.Callback;
3434
import org.flywaydb.core.api.configuration.FluentConfiguration;
3535
import org.flywaydb.core.api.migration.JavaMigration;
36+
import org.jooq.DSLContext;
3637

3738
import org.springframework.beans.factory.ObjectProvider;
3839
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
@@ -44,6 +45,7 @@
4445
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
4546
import org.springframework.boot.autoconfigure.data.jpa.EntityManagerFactoryDependsOnPostProcessor;
4647
import org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration.FlywayDataSourceCondition;
48+
import org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration.FlywayDslContextDependsOnPostProcessor;
4749
import org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration.FlywayEntityManagerFactoryDependsOnPostProcessor;
4850
import org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration.FlywayJdbcOperationsDependsOnPostProcessor;
4951
import org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration.FlywayNamedParameterJdbcOperationsDependencyConfiguration;
@@ -52,6 +54,7 @@
5254
import org.springframework.boot.autoconfigure.jdbc.JdbcOperationsDependsOnPostProcessor;
5355
import org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration;
5456
import org.springframework.boot.autoconfigure.jdbc.NamedParameterJdbcOperationsDependsOnPostProcessor;
57+
import org.springframework.boot.autoconfigure.jooq.DslContextDependsOnPostProcessor;
5558
import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration;
5659
import org.springframework.boot.context.properties.ConfigurationPropertiesBinding;
5760
import org.springframework.boot.context.properties.EnableConfigurationProperties;
@@ -96,7 +99,7 @@
9699
@AutoConfigureAfter({ DataSourceAutoConfiguration.class, JdbcTemplateAutoConfiguration.class,
97100
HibernateJpaAutoConfiguration.class })
98101
@Import({ FlywayEntityManagerFactoryDependsOnPostProcessor.class, FlywayJdbcOperationsDependsOnPostProcessor.class,
99-
FlywayNamedParameterJdbcOperationsDependencyConfiguration.class })
102+
FlywayNamedParameterJdbcOperationsDependencyConfiguration.class, FlywayDslContextDependsOnPostProcessor.class })
100103
public class FlywayAutoConfiguration {
101104

102105
@Bean
@@ -115,7 +118,8 @@ public FlywaySchemaManagementProvider flywayDefaultDdlModeProvider(ObjectProvide
115118
@EnableConfigurationProperties({ DataSourceProperties.class, FlywayProperties.class })
116119
@Import({ FlywayMigrationInitializerEntityManagerFactoryDependsOnPostProcessor.class,
117120
FlywayMigrationInitializerJdbcOperationsDependsOnPostProcessor.class,
118-
FlywayMigrationInitializerNamedParameterJdbcOperationsDependsOnPostProcessor.class })
121+
FlywayMigrationInitializerNamedParameterJdbcOperationsDependsOnPostProcessor.class,
122+
FlywayMigrationInitializerDslContextDependsOnPostProcessor.class })
119123
public static class FlywayConfiguration {
120124

121125
@Bean
@@ -326,6 +330,20 @@ static class FlywayMigrationInitializerNamedParameterJdbcOperationsDependsOnPost
326330

327331
}
328332

333+
/**
334+
* Post processor to ensure that {@link DSLContext} beans depend on any
335+
* {@link FlywayMigrationInitializer} beans.
336+
*/
337+
@ConditionalOnClass(DSLContext.class)
338+
@ConditionalOnBean(DSLContext.class)
339+
static class FlywayMigrationInitializerDslContextDependsOnPostProcessor extends DslContextDependsOnPostProcessor {
340+
341+
FlywayMigrationInitializerDslContextDependsOnPostProcessor() {
342+
super(FlywayMigrationInitializer.class);
343+
}
344+
345+
}
346+
329347
/**
330348
* Post processor to ensure that {@link EntityManagerFactory} beans depend on any
331349
* {@link Flyway} beans.
@@ -369,6 +387,20 @@ public FlywayNamedParameterJdbcOperationsDependencyConfiguration() {
369387

370388
}
371389

390+
/**
391+
* Post processor to ensure that {@link DSLContext} beans depend on any {@link Flyway}
392+
* beans.
393+
*/
394+
@ConditionalOnClass(DSLContext.class)
395+
@ConditionalOnBean(DSLContext.class)
396+
protected static class FlywayDslContextDependsOnPostProcessor extends DslContextDependsOnPostProcessor {
397+
398+
public FlywayDslContextDependsOnPostProcessor() {
399+
super(Flyway.class);
400+
}
401+
402+
}
403+
372404
private static class LocationResolver {
373405

374406
private static final String VENDOR_PLACEHOLDER = "{vendor}";
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
/*
2+
* Copyright 2012-2021 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.boot.autoconfigure.jooq;
18+
19+
import org.jooq.DSLContext;
20+
21+
import org.springframework.beans.factory.config.BeanDefinition;
22+
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
23+
import org.springframework.boot.autoconfigure.AbstractDependsOnBeanFactoryPostProcessor;
24+
25+
/**
26+
* {@link BeanFactoryPostProcessor} that can be used to dynamically declare that all
27+
* {@link DSLContext} beans should "depend on" one or more specific beans.
28+
*
29+
* @author Eddú Meléndez
30+
* @since 2.3.9
31+
* @see BeanDefinition#setDependsOn(String[])
32+
*/
33+
public class DslContextDependsOnPostProcessor extends AbstractDependsOnBeanFactoryPostProcessor {
34+
35+
/**
36+
* Creates a new {@code DslContextDependsOnPostProcessor} that will set up
37+
* dependencies upon beans with the given names.
38+
* @param dependsOn names of the beans to depend upon
39+
*/
40+
public DslContextDependsOnPostProcessor(String... dependsOn) {
41+
super(DSLContext.class, dependsOn);
42+
}
43+
44+
/**
45+
* Creates a new {@code DslContextDependsOnPostProcessor} that will set up
46+
* dependencies upon beans with the given types.
47+
* @param dependsOn types of the beans to depend upon
48+
*/
49+
public DslContextDependsOnPostProcessor(Class<?>... dependsOn) {
50+
super(DSLContext.class, dependsOn);
51+
}
52+
53+
}

spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/liquibase/LiquibaseAutoConfiguration.java

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2012-2020 the original author or authors.
2+
* Copyright 2012-2021 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -23,6 +23,7 @@
2323

2424
import liquibase.change.DatabaseChange;
2525
import liquibase.integration.spring.SpringLiquibase;
26+
import org.jooq.DSLContext;
2627

2728
import org.springframework.beans.factory.ObjectProvider;
2829
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
@@ -37,7 +38,9 @@
3738
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
3839
import org.springframework.boot.autoconfigure.jdbc.JdbcOperationsDependsOnPostProcessor;
3940
import org.springframework.boot.autoconfigure.jdbc.NamedParameterJdbcOperationsDependsOnPostProcessor;
41+
import org.springframework.boot.autoconfigure.jooq.DslContextDependsOnPostProcessor;
4042
import org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration.LiquibaseDataSourceCondition;
43+
import org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration.LiquibaseDslContextDependsOnPostProcessor;
4144
import org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration.LiquibaseEntityManagerFactoryDependsOnPostProcessor;
4245
import org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration.LiquibaseJdbcOperationsDependsOnPostProcessor;
4346
import org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration.LiquibaseNamedParameterJdbcOperationsDependsOnPostProcessor;
@@ -75,7 +78,8 @@
7578
@AutoConfigureAfter({ DataSourceAutoConfiguration.class, HibernateJpaAutoConfiguration.class })
7679
@Import({ LiquibaseEntityManagerFactoryDependsOnPostProcessor.class,
7780
LiquibaseJdbcOperationsDependsOnPostProcessor.class,
78-
LiquibaseNamedParameterJdbcOperationsDependsOnPostProcessor.class })
81+
LiquibaseNamedParameterJdbcOperationsDependsOnPostProcessor.class,
82+
LiquibaseDslContextDependsOnPostProcessor.class })
7983
public class LiquibaseAutoConfiguration {
8084

8185
@Bean
@@ -206,6 +210,20 @@ static class LiquibaseNamedParameterJdbcOperationsDependsOnPostProcessor
206210

207211
}
208212

213+
/**
214+
* Post processor to ensure that {@link DSLContext} beans depend on the liquibase
215+
* bean.
216+
*/
217+
@ConditionalOnClass(DSLContext.class)
218+
@ConditionalOnBean(DSLContext.class)
219+
static class LiquibaseDslContextDependsOnPostProcessor extends DslContextDependsOnPostProcessor {
220+
221+
LiquibaseDslContextDependsOnPostProcessor() {
222+
super(SpringLiquibase.class);
223+
}
224+
225+
}
226+
209227
static final class LiquibaseDataSourceCondition extends AnyNestedCondition {
210228

211229
LiquibaseDataSourceCondition() {

spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/flyway/FlywayAutoConfigurationTests.java

Lines changed: 60 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2012-2020 the original author or authors.
2+
* Copyright 2012-2021 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -32,11 +32,15 @@
3232
import org.flywaydb.core.api.migration.JavaMigration;
3333
import org.flywaydb.core.internal.license.FlywayProUpgradeRequiredException;
3434
import org.hibernate.engine.transaction.jta.platform.internal.NoJtaPlatform;
35+
import org.jooq.DSLContext;
36+
import org.jooq.SQLDialect;
37+
import org.jooq.impl.DefaultDSLContext;
3538
import org.junit.jupiter.api.Test;
3639
import org.junit.jupiter.api.extension.ExtendWith;
3740
import org.mockito.InOrder;
3841

3942
import org.springframework.beans.factory.BeanCreationException;
43+
import org.springframework.beans.factory.config.BeanDefinition;
4044
import org.springframework.boot.autoconfigure.AutoConfigurations;
4145
import org.springframework.boot.autoconfigure.jdbc.EmbeddedDataSourceConfiguration;
4246
import org.springframework.boot.jdbc.DataSourceBuilder;
@@ -520,6 +524,25 @@ void initSqlsWithFlywayUrl() {
520524
});
521525
}
522526

527+
@Test
528+
void userConfigurationDslContextDependency() {
529+
this.contextRunner
530+
.withUserConfiguration(EmbeddedDataSourceConfiguration.class, CustomFlywayWithJooqConfiguration.class)
531+
.run((context) -> {
532+
BeanDefinition beanDefinition = context.getBeanFactory().getBeanDefinition("dslContext");
533+
assertThat(beanDefinition.getDependsOn()).containsExactly("flyway");
534+
});
535+
}
536+
537+
@Test
538+
void userConfigurationWithFlywayMigrationAndDslContextDependency() {
539+
this.contextRunner.withUserConfiguration(EmbeddedDataSourceConfiguration.class,
540+
CustomFlywayMigrationInitializerWithJooqConfiguration.class).run((context) -> {
541+
BeanDefinition beanDefinition = context.getBeanFactory().getBeanDefinition("dslContext");
542+
assertThat(beanDefinition.getDependsOn()).containsExactly("flywayMigrationInitializer", "flyway");
543+
});
544+
}
545+
523546
@Configuration(proxyBeanMethods = false)
524547
static class FlywayDataSourceConfiguration {
525548

@@ -748,6 +771,42 @@ FlywayConfigurationCustomizer customizerTwo() {
748771

749772
}
750773

774+
@Configuration
775+
static class CustomFlywayWithJooqConfiguration {
776+
777+
@Bean
778+
Flyway flyway(DataSource dataSource) {
779+
return Flyway.configure().dataSource(dataSource).load();
780+
}
781+
782+
@Bean
783+
DSLContext dslContext() {
784+
return new DefaultDSLContext(SQLDialect.H2);
785+
}
786+
787+
}
788+
789+
@Configuration
790+
protected static class CustomFlywayMigrationInitializerWithJooqConfiguration {
791+
792+
private final DataSource dataSource;
793+
794+
protected CustomFlywayMigrationInitializerWithJooqConfiguration(DataSource dataSource) {
795+
this.dataSource = dataSource;
796+
}
797+
798+
@Bean
799+
public FlywayMigrationInitializer flywayMigrationInitializer(Flyway flyway) {
800+
return new FlywayMigrationInitializer(flyway);
801+
}
802+
803+
@Bean
804+
DSLContext dslContext() {
805+
return new DefaultDSLContext(SQLDialect.H2);
806+
}
807+
808+
}
809+
751810
static final class CustomClassLoader extends ClassLoader {
752811

753812
private CustomClassLoader(ClassLoader parent) {

spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/liquibase/LiquibaseAutoConfigurationTests.java

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2012-2020 the original author or authors.
2+
* Copyright 2012-2021 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -41,6 +41,7 @@
4141
import org.springframework.boot.autoconfigure.AutoConfigurations;
4242
import org.springframework.boot.autoconfigure.jdbc.EmbeddedDataSourceConfiguration;
4343
import org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration;
44+
import org.springframework.boot.autoconfigure.jooq.JooqAutoConfiguration;
4445
import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration;
4546
import org.springframework.boot.context.event.ApplicationStartingEvent;
4647
import org.springframework.boot.jdbc.DataSourceBuilder;
@@ -374,6 +375,16 @@ void overrideTag() {
374375
.run(assertLiquibase((liquibase) -> assertThat(liquibase.getTag()).isEqualTo("1.0.0")));
375376
}
376377

378+
@Test
379+
void userConfigurationDslContextDependency() {
380+
this.contextRunner.withConfiguration(AutoConfigurations.of(JooqAutoConfiguration.class))
381+
.withUserConfiguration(LiquibaseUserConfiguration.class, EmbeddedDataSourceConfiguration.class)
382+
.run((context) -> {
383+
BeanDefinition beanDefinition = context.getBeanFactory().getBeanDefinition("dslContext");
384+
assertThat(beanDefinition.getDependsOn()).containsExactly("springLiquibase");
385+
});
386+
}
387+
377388
private ContextConsumer<AssertableApplicationContext> assertLiquibase(Consumer<SpringLiquibase> consumer) {
378389
return (context) -> {
379390
assertThat(context).hasSingleBean(SpringLiquibase.class);

0 commit comments

Comments
 (0)