Skip to content

Commit

Permalink
Ensure that Flyway/Liquibase run before jOOQ's DSLContext is used
Browse files Browse the repository at this point in the history
  • Loading branch information
eddumelendez authored and wilkinsona committed Feb 16, 2021
1 parent 08802d3 commit c55200d
Show file tree
Hide file tree
Showing 5 changed files with 180 additions and 7 deletions.
@@ -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.
Expand Down Expand Up @@ -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;
Expand All @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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}";
Expand Down
@@ -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);
}

}
@@ -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.
Expand All @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -75,7 +78,8 @@
@AutoConfigureAfter({ DataSourceAutoConfiguration.class, HibernateJpaAutoConfiguration.class })
@Import({ LiquibaseEntityManagerFactoryDependsOnPostProcessor.class,
LiquibaseJdbcOperationsDependsOnPostProcessor.class,
LiquibaseNamedParameterJdbcOperationsDependsOnPostProcessor.class })
LiquibaseNamedParameterJdbcOperationsDependsOnPostProcessor.class,
LiquibaseDslContextDependsOnPostProcessor.class })
public class LiquibaseAutoConfiguration {

@Bean
Expand Down Expand Up @@ -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() {
Expand Down
@@ -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.
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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 {

Expand Down Expand Up @@ -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) {
Expand Down
@@ -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.
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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<AssertableApplicationContext> assertLiquibase(Consumer<SpringLiquibase> consumer) {
return (context) -> {
assertThat(context).hasSingleBean(SpringLiquibase.class);
Expand Down

0 comments on commit c55200d

Please sign in to comment.