Merge pull request #16850 from Ilya Lukyanovich

* gh-16850:
  Polish "Auto-configure Flyway and Liquibase when there's a URL but no DataSource"
  Auto-configure Flyway and Liquibase when there's a URL but no DataSource

Closes gh-16850
pull/17002/head
Andy Wilkinson 6 years ago
commit 960c03dee5

@ -36,11 +36,13 @@ import org.flywaydb.core.api.configuration.FluentConfiguration;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.condition.AnyNestedCondition;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
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.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
import org.springframework.boot.autoconfigure.jdbc.JdbcOperationsDependsOnPostProcessor;
@ -52,6 +54,7 @@ import org.springframework.boot.context.properties.EnableConfigurationProperties
import org.springframework.boot.context.properties.PropertyMapper;
import org.springframework.boot.jdbc.DatabaseDriver;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.convert.TypeDescriptor;
import org.springframework.core.convert.converter.GenericConverter;
@ -82,7 +85,7 @@ import org.springframework.util.StringUtils;
@SuppressWarnings("deprecation")
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(Flyway.class)
@ConditionalOnBean(DataSource.class)
@Conditional(FlywayDataSourceCondition.class)
@ConditionalOnProperty(prefix = "spring.flyway", name = "enabled", matchIfMissing = true)
@AutoConfigureAfter({ DataSourceAutoConfiguration.class,
JdbcTemplateAutoConfiguration.class, HibernateJpaAutoConfiguration.class })
@ -462,4 +465,23 @@ public class FlywayAutoConfiguration {
}
static final class FlywayDataSourceCondition extends AnyNestedCondition {
FlywayDataSourceCondition() {
super(ConfigurationPhase.REGISTER_BEAN);
}
@ConditionalOnBean(DataSource.class)
private static final class DataSourceBeanCondition {
}
@ConditionalOnProperty(prefix = "spring.flyway", name = "url",
matchIfMissing = false)
private static final class FlywayUrlCondition {
}
}
}

@ -28,6 +28,7 @@ import liquibase.integration.spring.SpringLiquibase;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.condition.AnyNestedCondition;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
@ -37,10 +38,12 @@ import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
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.liquibase.LiquibaseAutoConfiguration.LiquibaseDataSourceCondition;
import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.core.io.Resource;
@ -65,9 +68,9 @@ import org.springframework.util.Assert;
*/
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass({ SpringLiquibase.class, DatabaseChange.class })
@ConditionalOnBean(DataSource.class)
@ConditionalOnProperty(prefix = "spring.liquibase", name = "enabled",
matchIfMissing = true)
@Conditional(LiquibaseDataSourceCondition.class)
@AutoConfigureAfter({ DataSourceAutoConfiguration.class,
HibernateJpaAutoConfiguration.class })
public class LiquibaseAutoConfiguration {
@ -225,4 +228,23 @@ public class LiquibaseAutoConfiguration {
}
static final class LiquibaseDataSourceCondition extends AnyNestedCondition {
LiquibaseDataSourceCondition() {
super(ConfigurationPhase.REGISTER_BEAN);
}
@ConditionalOnBean(DataSource.class)
private static final class DataSourceBeanCondition {
}
@ConditionalOnProperty(prefix = "spring.liquibase", name = "url",
matchIfMissing = false)
private static final class LiquibaseUrlCondition {
}
}
}

@ -79,11 +79,22 @@ public class FlywayAutoConfigurationTests {
.withPropertyValues("spring.datasource.generate-unique-name=true");
@Test
public void noDataSource() {
public void backsOffWithNoDataSourceBeanAndNoFlywayUrl() {
this.contextRunner
.run((context) -> assertThat(context).doesNotHaveBean(Flyway.class));
}
@Test
public void createsDataSourceWithNoDataSourceBeanAndFlywayUrl() {
this.contextRunner
.withPropertyValues(
"spring.flyway.url:jdbc:hsqldb:mem:" + UUID.randomUUID())
.run((context) -> {
assertThat(context).hasSingleBean(Flyway.class);
assertThat(context.getBean(Flyway.class).getDataSource()).isNotNull();
});
}
@Test
public void createDataSourceWithUrl() {
this.contextRunner.withUserConfiguration(EmbeddedDataSourceConfiguration.class)

@ -78,11 +78,23 @@ public class LiquibaseAutoConfigurationTests {
.withPropertyValues("spring.datasource.generate-unique-name=true");
@Test
public void noDataSource() {
public void backsOffWithNoDataSourceBeanAndNoLiquibaseUrl() {
this.contextRunner.run(
(context) -> assertThat(context).doesNotHaveBean(SpringLiquibase.class));
}
@Test
public void createsDataSourceWithNoDataSourceBeanAndLiquibaseUrl() {
this.contextRunner
.withPropertyValues("spring.liquibase.url:jdbc:hsqldb:mem:liquibase")
.run(assertLiquibase((liquibase) -> {
DataSource dataSource = liquibase.getDataSource();
assertThat(((HikariDataSource) dataSource).isClosed()).isTrue();
assertThat(((HikariDataSource) dataSource).getJdbcUrl())
.isEqualTo("jdbc:hsqldb:mem:liquibase");
}));
}
@Test
public void defaultSpringLiquibase() {
this.contextRunner.withUserConfiguration(EmbeddedDataSourceConfiguration.class)

Loading…
Cancel
Save