Let Hibernate configure the transaction manager on WebSphere

Closes gh-8926
pull/14184/merge
Stephane Nicoll 6 years ago
parent fc4340c5d4
commit 833e39eeb6

@ -16,6 +16,7 @@
package org.springframework.boot.autoconfigure.orm.jpa;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedHashMap;
@ -75,14 +76,6 @@ class HibernateJpaConfiguration extends JpaBaseConfiguration {
"org.hibernate.engine.transaction.jta.platform.internal.NoJtaPlatform",
"org.hibernate.service.jta.platform.internal.NoJtaPlatform" };
/**
* {@code WebSphereExtendedJtaPlatform} implementations for various Hibernate
* versions.
*/
private static final String[] WEBSPHERE_JTA_PLATFORM_CLASSES = {
"org.hibernate.engine.transaction.jta.platform.internal.WebSphereExtendedJtaPlatform",
"org.hibernate.service.jta.platform.internal.WebSphereExtendedJtaPlatform" };
private final HibernateProperties hibernateProperties;
private final HibernateDefaultDdlAutoProvider defaultDdlAutoProvider;
@ -157,20 +150,15 @@ class HibernateJpaConfiguration extends JpaBaseConfiguration {
private void configureJtaPlatform(Map<String, Object> vendorProperties)
throws LinkageError {
JtaTransactionManager jtaTransactionManager = getJtaTransactionManager();
if (jtaTransactionManager != null) {
if (runningOnWebSphere()) {
// We can never use SpringJtaPlatform on WebSphere as
// WebSphereUowTransactionManager has a null TransactionManager
// which will cause Hibernate to NPE
configureWebSphereTransactionPlatform(vendorProperties);
}
else {
configureSpringJtaPlatform(vendorProperties, jtaTransactionManager);
}
}
else {
// Make sure Hibernate doesn't attempt to auto-detect a JTA platform
if (jtaTransactionManager == null) {
vendorProperties.put(JTA_PLATFORM, getNoJtaPlatformManager());
}
// As of Hibernate 5.2, Hibernate can fully integrate with the WebSphere
// transaction manager on its own.
else if (!runningOnWebSphere()) {
configureSpringJtaPlatform(vendorProperties, jtaTransactionManager);
}
}
private void configureProviderDisablesAutocommit(
@ -193,15 +181,6 @@ class HibernateJpaConfiguration extends JpaBaseConfiguration {
getClass().getClassLoader());
}
private void configureWebSphereTransactionPlatform(
Map<String, Object> vendorProperties) {
vendorProperties.put(JTA_PLATFORM, getWebSphereJtaPlatformManager());
}
private Object getWebSphereJtaPlatformManager() {
return getJtaPlatformManager(WEBSPHERE_JTA_PLATFORM_CLASSES);
}
private void configureSpringJtaPlatform(Map<String, Object> vendorProperties,
JtaTransactionManager jtaTransactionManager) {
try {
@ -233,11 +212,7 @@ class HibernateJpaConfiguration extends JpaBaseConfiguration {
}
private Object getNoJtaPlatformManager() {
return getJtaPlatformManager(NO_JTA_PLATFORM_CLASSES);
}
private Object getJtaPlatformManager(String[] candidates) {
for (String candidate : candidates) {
for (String candidate : NO_JTA_PLATFORM_CLASSES) {
try {
return Class.forName(candidate).newInstance();
}
@ -245,7 +220,8 @@ class HibernateJpaConfiguration extends JpaBaseConfiguration {
// Continue searching
}
}
throw new IllegalStateException("Could not configure JTA platform");
throw new IllegalStateException("No available JtaPlatform candidates amongst"
+ Arrays.toString(NO_JTA_PLATFORM_CLASSES));
}
private static class NamingStrategiesHibernatePropertiesCustomizer

@ -35,7 +35,9 @@ import javax.transaction.UserTransaction;
import com.zaxxer.hikari.HikariDataSource;
import org.hibernate.boot.model.naming.ImplicitNamingStrategy;
import org.hibernate.boot.model.naming.PhysicalNamingStrategy;
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.junit.Test;
import org.springframework.beans.factory.BeanCreationException;
@ -52,6 +54,8 @@ import org.springframework.boot.autoconfigure.transaction.jta.JtaAutoConfigurati
import org.springframework.boot.orm.jpa.hibernate.SpringImplicitNamingStrategy;
import org.springframework.boot.orm.jpa.hibernate.SpringJtaPlatform;
import org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy;
import org.springframework.boot.test.context.assertj.AssertableApplicationContext;
import org.springframework.boot.test.context.runner.ContextConsumer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.orm.jpa.JpaTransactionManager;
@ -148,13 +152,7 @@ public class HibernateJpaAutoConfigurationTests
public void jtaDefaultPlatform() {
contextRunner()
.withConfiguration(AutoConfigurations.of(JtaAutoConfiguration.class))
.run((context) -> {
Map<String, Object> jpaPropertyMap = context
.getBean(LocalContainerEntityManagerFactoryBean.class)
.getJpaPropertyMap();
assertThat(jpaPropertyMap.get("hibernate.transaction.jta.platform"))
.isInstanceOf(SpringJtaPlatform.class);
});
.run(assertJtaPlatform(SpringJtaPlatform.class));
}
@Test
@ -164,14 +162,23 @@ public class HibernateJpaAutoConfigurationTests
"spring.jpa.properties.hibernate.transaction.jta.platform:"
+ TestJtaPlatform.class.getName())
.withConfiguration(AutoConfigurations.of(JtaAutoConfiguration.class))
.run((context) -> {
Map<String, Object> jpaPropertyMap = context
.run(assertJtaPlatform(TestJtaPlatform.class));
}
@Test
public void jtaNotUsedByTheApplication() {
contextRunner().run(assertJtaPlatform(NoJtaPlatform.class));
}
private ContextConsumer<AssertableApplicationContext> assertJtaPlatform(
Class<? extends JtaPlatform> expectedType) {
return (context) -> {
SessionFactoryImpl sessionFactory = context
.getBean(LocalContainerEntityManagerFactoryBean.class)
.getJpaPropertyMap();
assertThat((String) jpaPropertyMap
.get("hibernate.transaction.jta.platform"))
.isEqualTo(TestJtaPlatform.class.getName());
});
.getNativeEntityManagerFactory().unwrap(SessionFactoryImpl.class);
assertThat(sessionFactory.getServiceRegistry().getService(JtaPlatform.class))
.isInstanceOf(expectedType);
};
}
@Test

Loading…
Cancel
Save