From fd53cbf2f3cb2b8314982dc6c089a8edee662a2e Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Mon, 5 Oct 2015 13:36:20 +0100 Subject: [PATCH] Stop JPA and a custom Flyway bean from causing a startup failure MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Previously, if an application used JPA and declared its own Flyway bean, startup would fail. The custom Flyway bean would switch off auto-configuration of the FlywayMigrationInitializer bean but the context’s entity manager factory beans would still be configured to depend on the migration initialiser. This commit splits the post-processor that configures the dependencies into two. One that configures the dependency on the Flyway bean and one that configures the dependency on the FlywayMigrationInitializer bean. When to auto-configuration of the FlywayMigrationInitializer is switched off, the auto-configuration of the latter dependency is also switched off. Closes gh-4079 --- .../flyway/FlywayAutoConfiguration.java | 21 ++++++++++--- .../flyway/FlywayAutoConfigurationTests.java | 31 +++++++++++++++++++ 2 files changed, 48 insertions(+), 4 deletions(-) diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/flyway/FlywayAutoConfiguration.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/flyway/FlywayAutoConfiguration.java index 2d58251b65..e1b63d4869 100644 --- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/flyway/FlywayAutoConfiguration.java +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/flyway/FlywayAutoConfiguration.java @@ -35,7 +35,6 @@ import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.Import; import org.springframework.core.io.DefaultResourceLoader; import org.springframework.core.io.ResourceLoader; import org.springframework.orm.jpa.AbstractEntityManagerFactoryBean; @@ -60,7 +59,6 @@ public class FlywayAutoConfiguration { @Configuration @ConditionalOnMissingBean(Flyway.class) @EnableConfigurationProperties(FlywayProperties.class) - @Import(FlywayJpaDependencyConfiguration.class) public static class FlywayConfiguration { @Autowired @@ -122,6 +120,21 @@ public class FlywayAutoConfiguration { @ConditionalOnMissingBean public FlywayMigrationInitializer flywayInitializer(Flyway flyway) { return new FlywayMigrationInitializer(flyway, this.migrationStrategy); + } + + /** + * Additional configuration to ensure that {@link EntityManagerFactory} beans + * depend-on the {@code flywayInitializer} bean. + */ + @Configuration + @ConditionalOnClass(LocalContainerEntityManagerFactoryBean.class) + @ConditionalOnBean(AbstractEntityManagerFactoryBean.class) + protected class FlywayInitializerJpaDependencyConfiguration extends + EntityManagerFactoryDependsOnPostProcessor { + + public FlywayInitializerJpaDependencyConfiguration() { + super("flywayInitializer"); + } } @@ -129,7 +142,7 @@ public class FlywayAutoConfiguration { /** * Additional configuration to ensure that {@link EntityManagerFactory} beans - * depend-on the flyway bean. + * depend-on the {@code flyway} bean. */ @Configuration @ConditionalOnClass(LocalContainerEntityManagerFactoryBean.class) @@ -138,7 +151,7 @@ public class FlywayAutoConfiguration { EntityManagerFactoryDependsOnPostProcessor { public FlywayJpaDependencyConfiguration() { - super("flywayInitializer", "flyway"); + super("flyway"); } } diff --git a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/flyway/FlywayAutoConfigurationTests.java b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/flyway/FlywayAutoConfigurationTests.java index 3ea4511261..b1ea0f1f1c 100644 --- a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/flyway/FlywayAutoConfigurationTests.java +++ b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/flyway/FlywayAutoConfigurationTests.java @@ -17,6 +17,7 @@ package org.springframework.boot.autoconfigure.flyway; import java.util.Arrays; +import java.util.Collections; import javax.sql.DataSource; @@ -27,14 +28,18 @@ import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; import org.springframework.beans.factory.BeanCreationException; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.PropertyPlaceholderAutoConfiguration; import org.springframework.boot.autoconfigure.jdbc.DataSourceBuilder; import org.springframework.boot.autoconfigure.jdbc.EmbeddedDataSourceConfiguration; +import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder; import org.springframework.boot.test.EnvironmentTestUtils; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.Ordered; +import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; +import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter; import org.springframework.stereotype.Component; import static org.hamcrest.Matchers.equalTo; @@ -47,6 +52,7 @@ import static org.junit.Assert.assertThat; * * @author Dave Syer * @author Phillip Webb + * @author Andy Wilkinson */ public class FlywayAutoConfigurationTests { @@ -171,7 +177,13 @@ public class FlywayAutoConfigurationTests { FlywayMigrationInitializer initializer = this.context .getBean(FlywayMigrationInitializer.class); assertThat(initializer.getOrder(), equalTo(Ordered.HIGHEST_PRECEDENCE)); + } + @Test + public void customFlywayWithJpa() throws Exception { + registerAndRefresh(CustomFlywayWithJpaConfiguration.class, + EmbeddedDataSourceConfiguration.class, FlywayAutoConfiguration.class, + PropertyPlaceholderAutoConfiguration.class); } private void registerAndRefresh(Class... annotatedClasses) { @@ -204,6 +216,25 @@ public class FlywayAutoConfigurationTests { } } + @Configuration + protected static class CustomFlywayWithJpaConfiguration { + + @Autowired + private DataSource dataSource; + + @Bean + public Flyway flyway() { + return new Flyway(); + } + + @Bean + public LocalContainerEntityManagerFactoryBean entityManagerFactoryBean() { + return new EntityManagerFactoryBuilder(new HibernateJpaVendorAdapter(), + Collections.emptyMap(), null).dataSource(this.dataSource).build(); + } + + } + @Component protected static class MockFlywayMigrationStrategy implements FlywayMigrationStrategy {