diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/flyway/FlywayAutoConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/flyway/FlywayAutoConfiguration.java index 1ca4fd424d5b..4ede9f50a3ad 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/flyway/FlywayAutoConfiguration.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/flyway/FlywayAutoConfiguration.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2020 the original author or authors. + * Copyright 2012-2021 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -33,6 +33,7 @@ import org.flywaydb.core.api.callback.Callback; import org.flywaydb.core.api.configuration.FluentConfiguration; import org.flywaydb.core.api.migration.JavaMigration; +import org.jooq.DSLContext; import org.springframework.beans.factory.ObjectProvider; import org.springframework.boot.autoconfigure.AutoConfigureAfter; @@ -44,6 +45,7 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.autoconfigure.data.jpa.EntityManagerFactoryDependsOnPostProcessor; import org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration.FlywayDataSourceCondition; +import org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration.FlywayDslContextDependsOnPostProcessor; import org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration.FlywayEntityManagerFactoryDependsOnPostProcessor; import org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration.FlywayJdbcOperationsDependsOnPostProcessor; import org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration.FlywayNamedParameterJdbcOperationsDependencyConfiguration; @@ -52,6 +54,7 @@ import org.springframework.boot.autoconfigure.jdbc.JdbcOperationsDependsOnPostProcessor; import org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration; import org.springframework.boot.autoconfigure.jdbc.NamedParameterJdbcOperationsDependsOnPostProcessor; +import org.springframework.boot.autoconfigure.jooq.DslContextDependsOnPostProcessor; import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration; import org.springframework.boot.context.properties.ConfigurationPropertiesBinding; import org.springframework.boot.context.properties.EnableConfigurationProperties; @@ -96,7 +99,7 @@ @AutoConfigureAfter({ DataSourceAutoConfiguration.class, JdbcTemplateAutoConfiguration.class, HibernateJpaAutoConfiguration.class }) @Import({ FlywayEntityManagerFactoryDependsOnPostProcessor.class, FlywayJdbcOperationsDependsOnPostProcessor.class, - FlywayNamedParameterJdbcOperationsDependencyConfiguration.class }) + FlywayNamedParameterJdbcOperationsDependencyConfiguration.class, FlywayDslContextDependsOnPostProcessor.class }) public class FlywayAutoConfiguration { @Bean @@ -115,7 +118,8 @@ public FlywaySchemaManagementProvider flywayDefaultDdlModeProvider(ObjectProvide @EnableConfigurationProperties({ DataSourceProperties.class, FlywayProperties.class }) @Import({ FlywayMigrationInitializerEntityManagerFactoryDependsOnPostProcessor.class, FlywayMigrationInitializerJdbcOperationsDependsOnPostProcessor.class, - FlywayMigrationInitializerNamedParameterJdbcOperationsDependsOnPostProcessor.class }) + FlywayMigrationInitializerNamedParameterJdbcOperationsDependsOnPostProcessor.class, + FlywayMigrationInitializerDslContextDependsOnPostProcessor.class }) public static class FlywayConfiguration { @Bean @@ -326,6 +330,20 @@ static class FlywayMigrationInitializerNamedParameterJdbcOperationsDependsOnPost } + /** + * Post processor to ensure that {@link DSLContext} beans depend on any + * {@link FlywayMigrationInitializer} beans. + */ + @ConditionalOnClass(DSLContext.class) + @ConditionalOnBean(DSLContext.class) + static class FlywayMigrationInitializerDslContextDependsOnPostProcessor extends DslContextDependsOnPostProcessor { + + FlywayMigrationInitializerDslContextDependsOnPostProcessor() { + super(FlywayMigrationInitializer.class); + } + + } + /** * Post processor to ensure that {@link EntityManagerFactory} beans depend on any * {@link Flyway} beans. @@ -369,6 +387,20 @@ public FlywayNamedParameterJdbcOperationsDependencyConfiguration() { } + /** + * Post processor to ensure that {@link DSLContext} beans depend on any {@link Flyway} + * beans. + */ + @ConditionalOnClass(DSLContext.class) + @ConditionalOnBean(DSLContext.class) + protected static class FlywayDslContextDependsOnPostProcessor extends DslContextDependsOnPostProcessor { + + public FlywayDslContextDependsOnPostProcessor() { + super(Flyway.class); + } + + } + private static class LocationResolver { private static final String VENDOR_PLACEHOLDER = "{vendor}"; diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jooq/DslContextDependsOnPostProcessor.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jooq/DslContextDependsOnPostProcessor.java new file mode 100644 index 000000000000..d951fba6105a --- /dev/null +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jooq/DslContextDependsOnPostProcessor.java @@ -0,0 +1,53 @@ +/* + * Copyright 2012-2021 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.autoconfigure.jooq; + +import org.jooq.DSLContext; + +import org.springframework.beans.factory.config.BeanDefinition; +import org.springframework.beans.factory.config.BeanFactoryPostProcessor; +import org.springframework.boot.autoconfigure.AbstractDependsOnBeanFactoryPostProcessor; + +/** + * {@link BeanFactoryPostProcessor} that can be used to dynamically declare that all + * {@link DSLContext} beans should "depend on" one or more specific beans. + * + * @author EddĂș MelĂ©ndez + * @since 2.3.9 + * @see BeanDefinition#setDependsOn(String[]) + */ +public class DslContextDependsOnPostProcessor extends AbstractDependsOnBeanFactoryPostProcessor { + + /** + * Creates a new {@code DslContextDependsOnPostProcessor} that will set up + * dependencies upon beans with the given names. + * @param dependsOn names of the beans to depend upon + */ + public DslContextDependsOnPostProcessor(String... dependsOn) { + super(DSLContext.class, dependsOn); + } + + /** + * Creates a new {@code DslContextDependsOnPostProcessor} that will set up + * dependencies upon beans with the given types. + * @param dependsOn types of the beans to depend upon + */ + public DslContextDependsOnPostProcessor(Class... dependsOn) { + super(DSLContext.class, dependsOn); + } + +} diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/liquibase/LiquibaseAutoConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/liquibase/LiquibaseAutoConfiguration.java index 604421565382..9c70170b735b 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/liquibase/LiquibaseAutoConfiguration.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/liquibase/LiquibaseAutoConfiguration.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2020 the original author or authors. + * Copyright 2012-2021 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -23,6 +23,7 @@ import liquibase.change.DatabaseChange; import liquibase.integration.spring.SpringLiquibase; +import org.jooq.DSLContext; import org.springframework.beans.factory.ObjectProvider; import org.springframework.boot.autoconfigure.AutoConfigureAfter; @@ -37,7 +38,9 @@ import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties; import org.springframework.boot.autoconfigure.jdbc.JdbcOperationsDependsOnPostProcessor; import org.springframework.boot.autoconfigure.jdbc.NamedParameterJdbcOperationsDependsOnPostProcessor; +import org.springframework.boot.autoconfigure.jooq.DslContextDependsOnPostProcessor; import org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration.LiquibaseDataSourceCondition; +import org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration.LiquibaseDslContextDependsOnPostProcessor; import org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration.LiquibaseEntityManagerFactoryDependsOnPostProcessor; import org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration.LiquibaseJdbcOperationsDependsOnPostProcessor; import org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration.LiquibaseNamedParameterJdbcOperationsDependsOnPostProcessor; @@ -75,7 +78,8 @@ @AutoConfigureAfter({ DataSourceAutoConfiguration.class, HibernateJpaAutoConfiguration.class }) @Import({ LiquibaseEntityManagerFactoryDependsOnPostProcessor.class, LiquibaseJdbcOperationsDependsOnPostProcessor.class, - LiquibaseNamedParameterJdbcOperationsDependsOnPostProcessor.class }) + LiquibaseNamedParameterJdbcOperationsDependsOnPostProcessor.class, + LiquibaseDslContextDependsOnPostProcessor.class }) public class LiquibaseAutoConfiguration { @Bean @@ -206,6 +210,20 @@ static class LiquibaseNamedParameterJdbcOperationsDependsOnPostProcessor } + /** + * Post processor to ensure that {@link DSLContext} beans depend on the liquibase + * bean. + */ + @ConditionalOnClass(DSLContext.class) + @ConditionalOnBean(DSLContext.class) + static class LiquibaseDslContextDependsOnPostProcessor extends DslContextDependsOnPostProcessor { + + LiquibaseDslContextDependsOnPostProcessor() { + super(SpringLiquibase.class); + } + + } + static final class LiquibaseDataSourceCondition extends AnyNestedCondition { LiquibaseDataSourceCondition() { diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/flyway/FlywayAutoConfigurationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/flyway/FlywayAutoConfigurationTests.java index f978ed9b0e45..ebe496c6ab14 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/flyway/FlywayAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/flyway/FlywayAutoConfigurationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2020 the original author or authors. + * Copyright 2012-2021 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -32,11 +32,15 @@ import org.flywaydb.core.api.migration.JavaMigration; import org.flywaydb.core.internal.license.FlywayProUpgradeRequiredException; import org.hibernate.engine.transaction.jta.platform.internal.NoJtaPlatform; +import org.jooq.DSLContext; +import org.jooq.SQLDialect; +import org.jooq.impl.DefaultDSLContext; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.InOrder; import org.springframework.beans.factory.BeanCreationException; +import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.boot.autoconfigure.AutoConfigurations; import org.springframework.boot.autoconfigure.jdbc.EmbeddedDataSourceConfiguration; import org.springframework.boot.jdbc.DataSourceBuilder; @@ -520,6 +524,25 @@ void initSqlsWithFlywayUrl() { }); } + @Test + void userConfigurationDslContextDependency() { + this.contextRunner + .withUserConfiguration(EmbeddedDataSourceConfiguration.class, CustomFlywayWithJooqConfiguration.class) + .run((context) -> { + BeanDefinition beanDefinition = context.getBeanFactory().getBeanDefinition("dslContext"); + assertThat(beanDefinition.getDependsOn()).containsExactly("flyway"); + }); + } + + @Test + void userConfigurationWithFlywayMigrationAndDslContextDependency() { + this.contextRunner.withUserConfiguration(EmbeddedDataSourceConfiguration.class, + CustomFlywayMigrationInitializerWithJooqConfiguration.class).run((context) -> { + BeanDefinition beanDefinition = context.getBeanFactory().getBeanDefinition("dslContext"); + assertThat(beanDefinition.getDependsOn()).containsExactly("flywayMigrationInitializer", "flyway"); + }); + } + @Configuration(proxyBeanMethods = false) static class FlywayDataSourceConfiguration { @@ -748,6 +771,42 @@ FlywayConfigurationCustomizer customizerTwo() { } + @Configuration + static class CustomFlywayWithJooqConfiguration { + + @Bean + Flyway flyway(DataSource dataSource) { + return Flyway.configure().dataSource(dataSource).load(); + } + + @Bean + DSLContext dslContext() { + return new DefaultDSLContext(SQLDialect.H2); + } + + } + + @Configuration + protected static class CustomFlywayMigrationInitializerWithJooqConfiguration { + + private final DataSource dataSource; + + protected CustomFlywayMigrationInitializerWithJooqConfiguration(DataSource dataSource) { + this.dataSource = dataSource; + } + + @Bean + public FlywayMigrationInitializer flywayMigrationInitializer(Flyway flyway) { + return new FlywayMigrationInitializer(flyway); + } + + @Bean + DSLContext dslContext() { + return new DefaultDSLContext(SQLDialect.H2); + } + + } + static final class CustomClassLoader extends ClassLoader { private CustomClassLoader(ClassLoader parent) { diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/liquibase/LiquibaseAutoConfigurationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/liquibase/LiquibaseAutoConfigurationTests.java index 7f854d2c529d..6ea18343e73e 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/liquibase/LiquibaseAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/liquibase/LiquibaseAutoConfigurationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2020 the original author or authors. + * Copyright 2012-2021 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -41,6 +41,7 @@ import org.springframework.boot.autoconfigure.AutoConfigurations; import org.springframework.boot.autoconfigure.jdbc.EmbeddedDataSourceConfiguration; import org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration; +import org.springframework.boot.autoconfigure.jooq.JooqAutoConfiguration; import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration; import org.springframework.boot.context.event.ApplicationStartingEvent; import org.springframework.boot.jdbc.DataSourceBuilder; @@ -374,6 +375,16 @@ void overrideTag() { .run(assertLiquibase((liquibase) -> assertThat(liquibase.getTag()).isEqualTo("1.0.0"))); } + @Test + void userConfigurationDslContextDependency() { + this.contextRunner.withConfiguration(AutoConfigurations.of(JooqAutoConfiguration.class)) + .withUserConfiguration(LiquibaseUserConfiguration.class, EmbeddedDataSourceConfiguration.class) + .run((context) -> { + BeanDefinition beanDefinition = context.getBeanFactory().getBeanDefinition("dslContext"); + assertThat(beanDefinition.getDependsOn()).containsExactly("springLiquibase"); + }); + } + private ContextConsumer assertLiquibase(Consumer consumer) { return (context) -> { assertThat(context).hasSingleBean(SpringLiquibase.class);