From 050460f635bbb3ed9fd091ce399971ffb69271ff Mon Sep 17 00:00:00 2001 From: Phillip Webb Date: Thu, 26 Sep 2019 12:06:51 -0700 Subject: [PATCH] Check factory bean for EntityManager datasource Update `DataSourceInitializedPublisher` to fallback to the `LocalContainerEntityManagerFactoryBean` if the `javax.persistence.nonJtaDataSource` property is not defined. As of Hibernate 4.3 the property is no longer set if the `EntityManager` is created from a `PersistenceUnitInfo` instance rather than actual properties. Although this is being addressed in Hibernate issue HHH-13432, it's not strictly a requirement of the JPA spec that the property is set. Fixes gh-17061 --- .../jpa/DataSourceInitializedPublisher.java | 38 +++++++++++-------- 1 file changed, 22 insertions(+), 16 deletions(-) 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 8d9e2f7358..58702c6c8b 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 @@ -65,8 +65,7 @@ class DataSourceInitializedPublisher implements BeanPostProcessor { if (bean instanceof LocalContainerEntityManagerFactoryBean) { LocalContainerEntityManagerFactoryBean factory = (LocalContainerEntityManagerFactoryBean) bean; if (factory.getBootstrapExecutor() != null && factory.getJpaVendorAdapter() != null) { - this.schemaCreatedPublisher = new DataSourceSchemaCreatedPublisher(factory.getBootstrapExecutor(), - factory.getJpaVendorAdapter()); + this.schemaCreatedPublisher = new DataSourceSchemaCreatedPublisher(factory); factory.setJpaVendorAdapter(this.schemaCreatedPublisher); } } @@ -86,21 +85,27 @@ class DataSourceInitializedPublisher implements BeanPostProcessor { this.hibernateProperties = (HibernateProperties) bean; } if (bean instanceof LocalContainerEntityManagerFactoryBean && this.schemaCreatedPublisher == null) { - LocalContainerEntityManagerFactoryBean factory = (LocalContainerEntityManagerFactoryBean) bean; - publishEventIfRequired(factory.getNativeEntityManagerFactory()); + LocalContainerEntityManagerFactoryBean factoryBean = (LocalContainerEntityManagerFactoryBean) bean; + EntityManagerFactory entityManagerFactory = factoryBean.getNativeEntityManagerFactory(); + publishEventIfRequired(factoryBean, entityManagerFactory); } return bean; } - private void publishEventIfRequired(EntityManagerFactory entityManagerFactory) { - DataSource dataSource = findDataSource(entityManagerFactory); + private void publishEventIfRequired(LocalContainerEntityManagerFactoryBean factoryBean, + EntityManagerFactory entityManagerFactory) { + DataSource dataSource = findDataSource(factoryBean, entityManagerFactory); if (dataSource != null && isInitializingDatabase(dataSource)) { this.applicationContext.publishEvent(new DataSourceSchemaCreatedEvent(dataSource)); } } - private DataSource findDataSource(EntityManagerFactory entityManagerFactory) { + private DataSource findDataSource(LocalContainerEntityManagerFactoryBean factoryBean, + EntityManagerFactory entityManagerFactory) { Object dataSource = entityManagerFactory.getProperties().get("javax.persistence.nonJtaDataSource"); + if (dataSource == null) { + dataSource = factoryBean.getPersistenceUnitInfo().getNonJtaDataSource(); + } return (dataSource instanceof DataSource) ? (DataSource) dataSource : this.dataSource; } @@ -145,14 +150,13 @@ class DataSourceInitializedPublisher implements BeanPostProcessor { final class DataSourceSchemaCreatedPublisher implements JpaVendorAdapter { - private final AsyncTaskExecutor bootstrapExecutor; + private final LocalContainerEntityManagerFactoryBean factoryBean; private final JpaVendorAdapter delegate; - private DataSourceSchemaCreatedPublisher(AsyncTaskExecutor bootstrapExecutor, - JpaVendorAdapter jpaVendorAdapter) { - this.bootstrapExecutor = bootstrapExecutor; - this.delegate = jpaVendorAdapter; + private DataSourceSchemaCreatedPublisher(LocalContainerEntityManagerFactoryBean factoryBean) { + this.factoryBean = factoryBean; + this.delegate = factoryBean.getJpaVendorAdapter(); } @Override @@ -191,10 +195,12 @@ class DataSourceInitializedPublisher implements BeanPostProcessor { } @Override - public void postProcessEntityManagerFactory(EntityManagerFactory emf) { - this.delegate.postProcessEntityManagerFactory(emf); - if (this.bootstrapExecutor != null) { - this.bootstrapExecutor.execute(() -> DataSourceInitializedPublisher.this.publishEventIfRequired(emf)); + public void postProcessEntityManagerFactory(EntityManagerFactory entityManagerFactory) { + this.delegate.postProcessEntityManagerFactory(entityManagerFactory); + AsyncTaskExecutor bootstrapExecutor = this.factoryBean.getBootstrapExecutor(); + if (bootstrapExecutor != null) { + bootstrapExecutor.execute(() -> DataSourceInitializedPublisher.this + .publishEventIfRequired(this.factoryBean, entityManagerFactory)); } }