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 f734a7f1379d..8a4b1dfc8117 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. @@ -34,6 +34,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; @@ -45,6 +46,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; @@ -53,6 +55,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; @@ -97,7 +100,7 @@ @AutoConfigureAfter({ DataSourceAutoConfiguration.class, JdbcTemplateAutoConfiguration.class, HibernateJpaAutoConfiguration.class }) @Import({ FlywayEntityManagerFactoryDependsOnPostProcessor.class, FlywayJdbcOperationsDependsOnPostProcessor.class, - FlywayNamedParameterJdbcOperationsDependencyConfiguration.class }) + FlywayNamedParameterJdbcOperationsDependencyConfiguration.class, FlywayDslContextDependsOnPostProcessor.class }) public class FlywayAutoConfiguration { @Bean @@ -116,7 +119,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 @@ -357,6 +361,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. @@ -400,6 +418,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 fe92c5db8a00..2a5a7b1c4448 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; @@ -78,7 +81,8 @@ @AutoConfigureAfter({ DataSourceAutoConfiguration.class, HibernateJpaAutoConfiguration.class }) @Import({ LiquibaseEntityManagerFactoryDependsOnPostProcessor.class, LiquibaseJdbcOperationsDependsOnPostProcessor.class, - LiquibaseNamedParameterJdbcOperationsDependsOnPostProcessor.class }) + LiquibaseNamedParameterJdbcOperationsDependsOnPostProcessor.class, + LiquibaseDslContextDependsOnPostProcessor.class }) public class LiquibaseAutoConfiguration { @Bean @@ -177,8 +181,8 @@ private String getProperty(Supplier property, Supplier defaultVa } /** - * Post processor to ensure that {@link EntityManagerFactory} beans depend on the - * liquibase bean. + * Post processor to ensure that {@link EntityManagerFactory} beans depend on any + * {@link SpringLiquibase} beans. */ @ConditionalOnClass(LocalContainerEntityManagerFactoryBean.class) @ConditionalOnBean(AbstractEntityManagerFactoryBean.class) @@ -192,8 +196,8 @@ static class LiquibaseEntityManagerFactoryDependsOnPostProcessor } /** - * Additional configuration to ensure that {@link JdbcOperations} beans depend on the - * liquibase bean. + * Additional configuration to ensure that {@link JdbcOperations} beans depend on any + * {@link SpringLiquibase} beans. */ @ConditionalOnClass(JdbcOperations.class) @ConditionalOnBean(JdbcOperations.class) @@ -207,7 +211,7 @@ static class LiquibaseJdbcOperationsDependsOnPostProcessor extends JdbcOperation /** * Post processor to ensure that {@link NamedParameterJdbcOperations} beans depend on - * the liquibase bean. + * any {@link SpringLiquibase} beans. */ @ConditionalOnClass(NamedParameterJdbcOperations.class) @ConditionalOnBean(NamedParameterJdbcOperations.class) @@ -220,6 +224,20 @@ static class LiquibaseNamedParameterJdbcOperationsDependsOnPostProcessor } + /** + * Post processor to ensure that {@link DSLContext} beans depend on any + * {@link SpringLiquibase} beans. + */ + @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 e9a58f933620..9e60ef80bf82 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.FlywayTeamsUpgradeRequiredException; 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; @@ -585,6 +589,33 @@ void skipExecutingMigrationsIsCorrectlyMapped() { }); } + @Test + void whenFlywayIsAutoConfiguredThenJooqDslContextDependsOnFlywayBeans() { + this.contextRunner.withUserConfiguration(EmbeddedDataSourceConfiguration.class, JooqConfiguration.class) + .run((context) -> { + BeanDefinition beanDefinition = context.getBeanFactory().getBeanDefinition("dslContext"); + assertThat(beanDefinition.getDependsOn()).containsExactly("flywayInitializer", "flyway"); + }); + } + + @Test + void whenCustomMigrationInitializerIsDefinedThenJooqDslContextDependsOnIt() { + this.contextRunner.withUserConfiguration(EmbeddedDataSourceConfiguration.class, JooqConfiguration.class, + CustomFlywayMigrationInitializer.class).run((context) -> { + BeanDefinition beanDefinition = context.getBeanFactory().getBeanDefinition("dslContext"); + assertThat(beanDefinition.getDependsOn()).containsExactly("flywayMigrationInitializer", "flyway"); + }); + } + + @Test + void whenCustomFlywayIsDefinedThenJooqDslContextDependsOnIt() { + this.contextRunner.withUserConfiguration(EmbeddedDataSourceConfiguration.class, JooqConfiguration.class, + CustomFlyway.class).run((context) -> { + BeanDefinition beanDefinition = context.getBeanFactory().getBeanDefinition("dslContext"); + assertThat(beanDefinition.getDependsOn()).containsExactly("customFlyway"); + }); + } + @Configuration(proxyBeanMethods = false) static class FlywayDataSourceConfiguration { @@ -661,6 +692,16 @@ FlywayMigrationInitializer flywayMigrationInitializer(Flyway flyway) { } + @Configuration(proxyBeanMethods = false) + static class CustomFlyway { + + @Bean + Flyway customFlyway() { + return Flyway.configure().load(); + } + + } + @Configuration(proxyBeanMethods = false) static class CustomFlywayMigrationInitializerWithJpaConfiguration { @@ -812,6 +853,16 @@ FlywayConfigurationCustomizer customizerTwo() { } + @Configuration(proxyBeanMethods = false) + static class JooqConfiguration { + + @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 586749c5cf6f..a21e055193de 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 @@ -42,6 +42,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; @@ -408,6 +409,25 @@ void overrideTag() { .run(assertLiquibase((liquibase) -> assertThat(liquibase.getTag()).isEqualTo("1.0.0"))); } + @Test + void whenLiquibaseIsAutoConfiguredThenJooqDslContextDependsOnSpringLiquibaseBeans() { + this.contextRunner.withConfiguration(AutoConfigurations.of(JooqAutoConfiguration.class)) + .withUserConfiguration(EmbeddedDataSourceConfiguration.class).run((context) -> { + BeanDefinition beanDefinition = context.getBeanFactory().getBeanDefinition("dslContext"); + assertThat(beanDefinition.getDependsOn()).containsExactly("liquibase"); + }); + } + + @Test + void whenCustomSpringLiquibaseIsDefinedThenJooqDslContextDependsOnSpringLiquibaseBeans() { + 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);