Stop JPA and a custom Flyway bean from causing a startup failure

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
pull/4095/head
Andy Wilkinson 9 years ago
parent 81f6a77d15
commit fd53cbf2f3

@ -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");
}
}

@ -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 {

Loading…
Cancel
Save