diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/orm/jpa/DataSourceInitializedPublisher.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/orm/jpa/DataSourceInitializedPublisher.java index 84d1f0c023..8d9e2f7358 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/orm/jpa/DataSourceInitializedPublisher.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/orm/jpa/DataSourceInitializedPublisher.java @@ -58,11 +58,17 @@ class DataSourceInitializedPublisher implements BeanPostProcessor { private HibernateProperties hibernateProperties; + private DataSourceSchemaCreatedPublisher schemaCreatedPublisher; + @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { if (bean instanceof LocalContainerEntityManagerFactoryBean) { LocalContainerEntityManagerFactoryBean factory = (LocalContainerEntityManagerFactoryBean) bean; - factory.setJpaVendorAdapter(new DataSourceSchemaCreatedPublisher(factory)); + if (factory.getBootstrapExecutor() != null && factory.getJpaVendorAdapter() != null) { + this.schemaCreatedPublisher = new DataSourceSchemaCreatedPublisher(factory.getBootstrapExecutor(), + factory.getJpaVendorAdapter()); + factory.setJpaVendorAdapter(this.schemaCreatedPublisher); + } } return bean; } @@ -79,11 +85,9 @@ class DataSourceInitializedPublisher implements BeanPostProcessor { if (bean instanceof HibernateProperties) { this.hibernateProperties = (HibernateProperties) bean; } - if (bean instanceof LocalContainerEntityManagerFactoryBean) { + if (bean instanceof LocalContainerEntityManagerFactoryBean && this.schemaCreatedPublisher == null) { LocalContainerEntityManagerFactoryBean factory = (LocalContainerEntityManagerFactoryBean) bean; - if (factory.getBootstrapExecutor() == null) { - publishEventIfRequired(factory.getNativeEntityManagerFactory()); - } + publishEventIfRequired(factory.getNativeEntityManagerFactory()); } return bean; } @@ -141,13 +145,14 @@ class DataSourceInitializedPublisher implements BeanPostProcessor { final class DataSourceSchemaCreatedPublisher implements JpaVendorAdapter { - private final JpaVendorAdapter delegate; + private final AsyncTaskExecutor bootstrapExecutor; - private final LocalContainerEntityManagerFactoryBean factory; + private final JpaVendorAdapter delegate; - private DataSourceSchemaCreatedPublisher(LocalContainerEntityManagerFactoryBean factory) { - this.delegate = factory.getJpaVendorAdapter(); - this.factory = factory; + private DataSourceSchemaCreatedPublisher(AsyncTaskExecutor bootstrapExecutor, + JpaVendorAdapter jpaVendorAdapter) { + this.bootstrapExecutor = bootstrapExecutor; + this.delegate = jpaVendorAdapter; } @Override @@ -188,9 +193,8 @@ class DataSourceInitializedPublisher implements BeanPostProcessor { @Override public void postProcessEntityManagerFactory(EntityManagerFactory emf) { this.delegate.postProcessEntityManagerFactory(emf); - AsyncTaskExecutor bootstrapExecutor = this.factory.getBootstrapExecutor(); - if (bootstrapExecutor != null) { - bootstrapExecutor.execute(() -> DataSourceInitializedPublisher.this.publishEventIfRequired(emf)); + if (this.bootstrapExecutor != null) { + this.bootstrapExecutor.execute(() -> DataSourceInitializedPublisher.this.publishEventIfRequired(emf)); } } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaAutoConfigurationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaAutoConfigurationTests.java index ff62b09b27..4e0b4f7d00 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaAutoConfigurationTests.java @@ -23,12 +23,14 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Enumeration; +import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.function.Consumer; import javax.persistence.EntityManager; import javax.persistence.EntityManagerFactory; +import javax.sql.DataSource; import javax.transaction.Synchronization; import javax.transaction.Transaction; import javax.transaction.TransactionManager; @@ -42,6 +44,7 @@ import org.hibernate.dialect.H2Dialect; import org.hibernate.engine.transaction.jta.platform.internal.NoJtaPlatform; import org.hibernate.engine.transaction.jta.platform.spi.JtaPlatform; import org.hibernate.internal.SessionFactoryImpl; +import org.hibernate.jpa.HibernatePersistenceProvider; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.BeanCreationException; @@ -393,6 +396,18 @@ class HibernateJpaAutoConfigurationTests extends AbstractJpaAutoConfigurationTes }); } + @Test + void whenLocalContanerEntityManagerFactoryBeanHasNoJpaVendorAdapterAutoConfigurationSucceeds() { + contextRunner() + .withUserConfiguration( + TestConfigurationWithLocalContainerEntityManagerFactoryBeanWithNoJpaVendorAdapter.class) + .run((context) -> { + EntityManagerFactory factoryBean = context.getBean(EntityManagerFactory.class); + Map map = factoryBean.getProperties(); + assertThat(map.get("configured")).isEqualTo("manually"); + }); + } + private boolean dataSourceSchemaCreatedEventReceived(EventCapturingApplicationListener listener) { for (ApplicationEvent event : listener.events) { if (event instanceof DataSourceSchemaCreatedEvent) { @@ -556,6 +571,25 @@ class HibernateJpaAutoConfigurationTests extends AbstractJpaAutoConfigurationTes } + @Configuration(proxyBeanMethods = false) + static class TestConfigurationWithLocalContainerEntityManagerFactoryBeanWithNoJpaVendorAdapter + extends TestConfiguration { + + @Bean + LocalContainerEntityManagerFactoryBean entityManagerFactory(DataSource dataSource) { + LocalContainerEntityManagerFactoryBean factoryBean = new LocalContainerEntityManagerFactoryBean(); + factoryBean.setDataSource(dataSource); + factoryBean.setPersistenceUnitName("manually-configured"); + factoryBean.setPersistenceProviderClass(HibernatePersistenceProvider.class); + Map properties = new HashMap<>(); + properties.put("configured", "manually"); + properties.put("hibernate.transaction.jta.platform", NoJtaPlatform.INSTANCE); + factoryBean.setJpaPropertyMap(properties); + return factoryBean; + } + + } + public static class TestH2Dialect extends H2Dialect { }