Commit 833e39ee authored by Stephane Nicoll's avatar Stephane Nicoll

Let Hibernate configure the transaction manager on WebSphere

Closes gh-8926
parent fc4340c5
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
package org.springframework.boot.autoconfigure.orm.jpa; package org.springframework.boot.autoconfigure.orm.jpa;
import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
...@@ -75,14 +76,6 @@ class HibernateJpaConfiguration extends JpaBaseConfiguration { ...@@ -75,14 +76,6 @@ class HibernateJpaConfiguration extends JpaBaseConfiguration {
"org.hibernate.engine.transaction.jta.platform.internal.NoJtaPlatform", "org.hibernate.engine.transaction.jta.platform.internal.NoJtaPlatform",
"org.hibernate.service.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 HibernateProperties hibernateProperties;
private final HibernateDefaultDdlAutoProvider defaultDdlAutoProvider; private final HibernateDefaultDdlAutoProvider defaultDdlAutoProvider;
...@@ -157,20 +150,15 @@ class HibernateJpaConfiguration extends JpaBaseConfiguration { ...@@ -157,20 +150,15 @@ class HibernateJpaConfiguration extends JpaBaseConfiguration {
private void configureJtaPlatform(Map<String, Object> vendorProperties) private void configureJtaPlatform(Map<String, Object> vendorProperties)
throws LinkageError { throws LinkageError {
JtaTransactionManager jtaTransactionManager = getJtaTransactionManager(); JtaTransactionManager jtaTransactionManager = getJtaTransactionManager();
if (jtaTransactionManager != null) { // Make sure Hibernate doesn't attempt to auto-detect a JTA platform
if (runningOnWebSphere()) { if (jtaTransactionManager == null) {
// 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 {
vendorProperties.put(JTA_PLATFORM, getNoJtaPlatformManager()); 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( private void configureProviderDisablesAutocommit(
...@@ -193,15 +181,6 @@ class HibernateJpaConfiguration extends JpaBaseConfiguration { ...@@ -193,15 +181,6 @@ class HibernateJpaConfiguration extends JpaBaseConfiguration {
getClass().getClassLoader()); 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, private void configureSpringJtaPlatform(Map<String, Object> vendorProperties,
JtaTransactionManager jtaTransactionManager) { JtaTransactionManager jtaTransactionManager) {
try { try {
...@@ -233,11 +212,7 @@ class HibernateJpaConfiguration extends JpaBaseConfiguration { ...@@ -233,11 +212,7 @@ class HibernateJpaConfiguration extends JpaBaseConfiguration {
} }
private Object getNoJtaPlatformManager() { private Object getNoJtaPlatformManager() {
return getJtaPlatformManager(NO_JTA_PLATFORM_CLASSES); for (String candidate : NO_JTA_PLATFORM_CLASSES) {
}
private Object getJtaPlatformManager(String[] candidates) {
for (String candidate : candidates) {
try { try {
return Class.forName(candidate).newInstance(); return Class.forName(candidate).newInstance();
} }
...@@ -245,7 +220,8 @@ class HibernateJpaConfiguration extends JpaBaseConfiguration { ...@@ -245,7 +220,8 @@ class HibernateJpaConfiguration extends JpaBaseConfiguration {
// Continue searching // 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 private static class NamingStrategiesHibernatePropertiesCustomizer
......
...@@ -35,7 +35,9 @@ import javax.transaction.UserTransaction; ...@@ -35,7 +35,9 @@ import javax.transaction.UserTransaction;
import com.zaxxer.hikari.HikariDataSource; import com.zaxxer.hikari.HikariDataSource;
import org.hibernate.boot.model.naming.ImplicitNamingStrategy; import org.hibernate.boot.model.naming.ImplicitNamingStrategy;
import org.hibernate.boot.model.naming.PhysicalNamingStrategy; 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.engine.transaction.jta.platform.spi.JtaPlatform;
import org.hibernate.internal.SessionFactoryImpl;
import org.junit.Test; import org.junit.Test;
import org.springframework.beans.factory.BeanCreationException; import org.springframework.beans.factory.BeanCreationException;
...@@ -52,6 +54,8 @@ import org.springframework.boot.autoconfigure.transaction.jta.JtaAutoConfigurati ...@@ -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.SpringImplicitNamingStrategy;
import org.springframework.boot.orm.jpa.hibernate.SpringJtaPlatform; import org.springframework.boot.orm.jpa.hibernate.SpringJtaPlatform;
import org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy; 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.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.orm.jpa.JpaTransactionManager; import org.springframework.orm.jpa.JpaTransactionManager;
...@@ -148,13 +152,7 @@ public class HibernateJpaAutoConfigurationTests ...@@ -148,13 +152,7 @@ public class HibernateJpaAutoConfigurationTests
public void jtaDefaultPlatform() { public void jtaDefaultPlatform() {
contextRunner() contextRunner()
.withConfiguration(AutoConfigurations.of(JtaAutoConfiguration.class)) .withConfiguration(AutoConfigurations.of(JtaAutoConfiguration.class))
.run((context) -> { .run(assertJtaPlatform(SpringJtaPlatform.class));
Map<String, Object> jpaPropertyMap = context
.getBean(LocalContainerEntityManagerFactoryBean.class)
.getJpaPropertyMap();
assertThat(jpaPropertyMap.get("hibernate.transaction.jta.platform"))
.isInstanceOf(SpringJtaPlatform.class);
});
} }
@Test @Test
...@@ -164,14 +162,23 @@ public class HibernateJpaAutoConfigurationTests ...@@ -164,14 +162,23 @@ public class HibernateJpaAutoConfigurationTests
"spring.jpa.properties.hibernate.transaction.jta.platform:" "spring.jpa.properties.hibernate.transaction.jta.platform:"
+ TestJtaPlatform.class.getName()) + TestJtaPlatform.class.getName())
.withConfiguration(AutoConfigurations.of(JtaAutoConfiguration.class)) .withConfiguration(AutoConfigurations.of(JtaAutoConfiguration.class))
.run((context) -> { .run(assertJtaPlatform(TestJtaPlatform.class));
Map<String, Object> jpaPropertyMap = context }
.getBean(LocalContainerEntityManagerFactoryBean.class)
.getJpaPropertyMap(); @Test
assertThat((String) jpaPropertyMap public void jtaNotUsedByTheApplication() {
.get("hibernate.transaction.jta.platform")) contextRunner().run(assertJtaPlatform(NoJtaPlatform.class));
.isEqualTo(TestJtaPlatform.class.getName()); }
});
private ContextConsumer<AssertableApplicationContext> assertJtaPlatform(
Class<? extends JtaPlatform> expectedType) {
return (context) -> {
SessionFactoryImpl sessionFactory = context
.getBean(LocalContainerEntityManagerFactoryBean.class)
.getNativeEntityManagerFactory().unwrap(SessionFactoryImpl.class);
assertThat(sessionFactory.getServiceRegistry().getService(JtaPlatform.class))
.isInstanceOf(expectedType);
};
} }
@Test @Test
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment