Skip to content

Commit ac0a22d

Browse files
committed
Tolerate LCEMFB with null JpaVendorAdapter in JPA auto-config
Closes gh-17935
1 parent abe3d38 commit ac0a22d

File tree

2 files changed

+51
-13
lines changed

2 files changed

+51
-13
lines changed

spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/orm/jpa/DataSourceInitializedPublisher.java

+17-13
Original file line numberDiff line numberDiff line change
@@ -58,11 +58,17 @@ class DataSourceInitializedPublisher implements BeanPostProcessor {
5858

5959
private HibernateProperties hibernateProperties;
6060

61+
private DataSourceSchemaCreatedPublisher schemaCreatedPublisher;
62+
6163
@Override
6264
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
6365
if (bean instanceof LocalContainerEntityManagerFactoryBean) {
6466
LocalContainerEntityManagerFactoryBean factory = (LocalContainerEntityManagerFactoryBean) bean;
65-
factory.setJpaVendorAdapter(new DataSourceSchemaCreatedPublisher(factory));
67+
if (factory.getBootstrapExecutor() != null && factory.getJpaVendorAdapter() != null) {
68+
this.schemaCreatedPublisher = new DataSourceSchemaCreatedPublisher(factory.getBootstrapExecutor(),
69+
factory.getJpaVendorAdapter());
70+
factory.setJpaVendorAdapter(this.schemaCreatedPublisher);
71+
}
6672
}
6773
return bean;
6874
}
@@ -79,11 +85,9 @@ public Object postProcessAfterInitialization(Object bean, String beanName) throw
7985
if (bean instanceof HibernateProperties) {
8086
this.hibernateProperties = (HibernateProperties) bean;
8187
}
82-
if (bean instanceof LocalContainerEntityManagerFactoryBean) {
88+
if (bean instanceof LocalContainerEntityManagerFactoryBean && this.schemaCreatedPublisher == null) {
8389
LocalContainerEntityManagerFactoryBean factory = (LocalContainerEntityManagerFactoryBean) bean;
84-
if (factory.getBootstrapExecutor() == null) {
85-
publishEventIfRequired(factory.getNativeEntityManagerFactory());
86-
}
90+
publishEventIfRequired(factory.getNativeEntityManagerFactory());
8791
}
8892
return bean;
8993
}
@@ -141,13 +145,14 @@ public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata,
141145

142146
final class DataSourceSchemaCreatedPublisher implements JpaVendorAdapter {
143147

144-
private final JpaVendorAdapter delegate;
148+
private final AsyncTaskExecutor bootstrapExecutor;
145149

146-
private final LocalContainerEntityManagerFactoryBean factory;
150+
private final JpaVendorAdapter delegate;
147151

148-
private DataSourceSchemaCreatedPublisher(LocalContainerEntityManagerFactoryBean factory) {
149-
this.delegate = factory.getJpaVendorAdapter();
150-
this.factory = factory;
152+
private DataSourceSchemaCreatedPublisher(AsyncTaskExecutor bootstrapExecutor,
153+
JpaVendorAdapter jpaVendorAdapter) {
154+
this.bootstrapExecutor = bootstrapExecutor;
155+
this.delegate = jpaVendorAdapter;
151156
}
152157

153158
@Override
@@ -188,9 +193,8 @@ public Class<? extends EntityManager> getEntityManagerInterface() {
188193
@Override
189194
public void postProcessEntityManagerFactory(EntityManagerFactory emf) {
190195
this.delegate.postProcessEntityManagerFactory(emf);
191-
AsyncTaskExecutor bootstrapExecutor = this.factory.getBootstrapExecutor();
192-
if (bootstrapExecutor != null) {
193-
bootstrapExecutor.execute(() -> DataSourceInitializedPublisher.this.publishEventIfRequired(emf));
196+
if (this.bootstrapExecutor != null) {
197+
this.bootstrapExecutor.execute(() -> DataSourceInitializedPublisher.this.publishEventIfRequired(emf));
194198
}
195199
}
196200

spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaAutoConfigurationTests.java

+34
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,13 @@
2323
import java.util.Arrays;
2424
import java.util.Collections;
2525
import java.util.Enumeration;
26+
import java.util.HashMap;
2627
import java.util.List;
2728
import java.util.Map;
2829

2930
import javax.persistence.EntityManager;
3031
import javax.persistence.EntityManagerFactory;
32+
import javax.sql.DataSource;
3133
import javax.transaction.Synchronization;
3234
import javax.transaction.Transaction;
3335
import javax.transaction.TransactionManager;
@@ -40,6 +42,7 @@
4042
import org.hibernate.engine.transaction.jta.platform.internal.NoJtaPlatform;
4143
import org.hibernate.engine.transaction.jta.platform.spi.JtaPlatform;
4244
import org.hibernate.internal.SessionFactoryImpl;
45+
import org.hibernate.jpa.HibernatePersistenceProvider;
4346
import org.junit.Test;
4447

4548
import org.springframework.beans.factory.BeanCreationException;
@@ -359,6 +362,18 @@ public void withAsyncBootstrappingAnApplicationListenerThatUsesJpaDoesNotTrigger
359362
});
360363
}
361364

365+
@Test
366+
public void whenLocalContanerEntityManagerFactoryBeanHasNoJpaVendorAdapterAutoConfigurationSucceeds() {
367+
contextRunner()
368+
.withUserConfiguration(
369+
TestConfigurationWithLocalContainerEntityManagerFactoryBeanWithNoJpaVendorAdapter.class)
370+
.run((context) -> {
371+
EntityManagerFactory factoryBean = context.getBean(EntityManagerFactory.class);
372+
Map<String, Object> map = factoryBean.getProperties();
373+
assertThat(map.get("configured")).isEqualTo("manually");
374+
});
375+
}
376+
362377
private boolean dataSourceSchemaCreatedEventReceived(EventCapturingApplicationListener listener) {
363378
for (ApplicationEvent event : listener.events) {
364379
if (event instanceof DataSourceSchemaCreatedEvent) {
@@ -522,4 +537,23 @@ public EntityManagerFactoryBuilderCustomizer asyncBootstrappingCustomizer(Thread
522537

523538
}
524539

540+
@Configuration
541+
protected static class TestConfigurationWithLocalContainerEntityManagerFactoryBeanWithNoJpaVendorAdapter
542+
extends TestConfiguration {
543+
544+
@Bean
545+
public LocalContainerEntityManagerFactoryBean entityManagerFactory(DataSource dataSource) {
546+
LocalContainerEntityManagerFactoryBean factoryBean = new LocalContainerEntityManagerFactoryBean();
547+
factoryBean.setDataSource(dataSource);
548+
factoryBean.setPersistenceUnitName("manually-configured");
549+
factoryBean.setPersistenceProviderClass(HibernatePersistenceProvider.class);
550+
Map<String, Object> properties = new HashMap<>();
551+
properties.put("configured", "manually");
552+
properties.put("hibernate.transaction.jta.platform", NoJtaPlatform.INSTANCE);
553+
factoryBean.setJpaPropertyMap(properties);
554+
return factoryBean;
555+
}
556+
557+
}
558+
525559
}

0 commit comments

Comments
 (0)