diff --git a/documentation/src/main/asciidoc/userguide/chapters/transactions/Transactions.adoc b/documentation/src/main/asciidoc/userguide/chapters/transactions/Transactions.adoc index ae8c521d1d1c..57e9415a27dd 100644 --- a/documentation/src/main/asciidoc/userguide/chapters/transactions/Transactions.adoc +++ b/documentation/src/main/asciidoc/userguide/chapters/transactions/Transactions.adoc @@ -77,12 +77,14 @@ If that resolution does not work, or if you wish to provide a custom implementat Hibernate provides many implementations of the `JtaPlatform` contract, all with short names: `JBossAS`:: `JtaPlatform` for Arjuna/JBossTransactions/Narayana when used within the JBoss/WildFly Application Server. -`JBossTS`:: `JtaPlatform` for Arjuna/JBossTransactions/Narayana when used standalone. +`JBossTS`:: **deprecated**, use `Narayana` or `WildFlyStandAlone` instead. `Atomikos`:: `JtaPlatform` for Atomikos. `GlassFish`, `Payara`:: `JtaPlatform` for GlassFish or Payara. `Resin`:: `JtaPlatform` for the Resin Application Server. +`Narayana`:: `JtaPlatform` for Arjuna/Narayana when used outside the WildFly Application Server. `Weblogic`:: `JtaPlatform` for the Weblogic Application Server. `WebSphere`, `WebSphereLiberty`:: `JtaPlatform` for newer versions of the WebSphere Application Server. +`WildFlyStandAlone`:: `JtaPlatform` for WildFly Transaction Client when used outside the WildFly Application Server. [[transactions-api]] === Hibernate Transaction API diff --git a/hibernate-core/src/main/java/org/hibernate/boot/registry/selector/internal/DefaultJtaPlatformSelector.java b/hibernate-core/src/main/java/org/hibernate/boot/registry/selector/internal/DefaultJtaPlatformSelector.java index 5b6bef3931b8..928865dce313 100644 --- a/hibernate-core/src/main/java/org/hibernate/boot/registry/selector/internal/DefaultJtaPlatformSelector.java +++ b/hibernate-core/src/main/java/org/hibernate/boot/registry/selector/internal/DefaultJtaPlatformSelector.java @@ -4,16 +4,21 @@ */ package org.hibernate.boot.registry.selector.internal; +import java.util.List; import java.util.Objects; +import org.hibernate.cfg.AvailableSettings; import org.hibernate.engine.transaction.jta.platform.internal.AtomikosJtaPlatform; import org.hibernate.engine.transaction.jta.platform.internal.JBossAppServerJtaPlatform; import org.hibernate.engine.transaction.jta.platform.internal.JBossStandAloneJtaPlatform; +import org.hibernate.engine.transaction.jta.platform.internal.NarayanaJtaPlatform; import org.hibernate.engine.transaction.jta.platform.internal.ResinJtaPlatform; import org.hibernate.engine.transaction.jta.platform.internal.GlassFishJtaPlatform; import org.hibernate.engine.transaction.jta.platform.internal.WebSphereLibertyJtaPlatform; import org.hibernate.engine.transaction.jta.platform.internal.WeblogicJtaPlatform; +import org.hibernate.engine.transaction.jta.platform.internal.WildFlyStandAloneJtaPlatform; import org.hibernate.engine.transaction.jta.platform.spi.JtaPlatform; +import org.hibernate.internal.log.DeprecationLogger; public class DefaultJtaPlatformSelector implements LazyServiceResolver { @@ -29,12 +34,18 @@ else if ( name.startsWith( "org." ) ) { else { return switch ( name ) { case "JBossAS" -> JBossAppServerJtaPlatform.class; - case "JBossTS" -> JBossStandAloneJtaPlatform.class; + case "JBossTS" -> { + DeprecationLogger.DEPRECATION_LOGGER.logDeprecatedJtaPlatformSetting( + AvailableSettings.JTA_PLATFORM, name, List.of( "Narayana", "WildFlyStandadlone" ) ); + yield JBossStandAloneJtaPlatform.class; + } case "Weblogic" -> WeblogicJtaPlatform.class; case "WebSphere", "WebSphereLiberty" -> WebSphereLibertyJtaPlatform.class; case "Atomikos" -> AtomikosJtaPlatform.class; case "Resin" -> ResinJtaPlatform.class; case "GlassFish", "Payara", "SunOne" -> GlassFishJtaPlatform.class; + case "Narayana" -> NarayanaJtaPlatform.class; + case "WildFlyStandAlone" -> WildFlyStandAloneJtaPlatform.class; default -> null; }; } @@ -55,11 +66,19 @@ private static Class legacy( return JBossAppServerJtaPlatform.class; } case "org.hibernate.service.jta.platform.internal.JBossStandAloneJtaPlatform" -> { + DeprecationLogger.DEPRECATION_LOGGER.logDeprecatedJtaPlatformSetting( + AvailableSettings.JTA_PLATFORM, name, List.of( "Narayana", "WildFlyStandadlone" ) ); return JBossStandAloneJtaPlatform.class; } + case "org.hibernate.engine.transaction.jta.platform.internal.NarayanaJtaPlatform" -> { + return NarayanaJtaPlatform.class; + } case "org.hibernate.engine.transaction.jta.platform.internal.WebSphereLibertyJtaPlatform" -> { return WebSphereLibertyJtaPlatform.class; } + case "org.hibernate.engine.transaction.jta.platform.internal.WildFlyStandAloneJtaPlatform" -> { + return WildFlyStandAloneJtaPlatform.class; + } } //All other ones follow a pattern, beginning with the same prefix and ending with the same postfix, @@ -69,8 +88,8 @@ private static Class legacy( //All these follow the same pattern, allowing us to use recursion into the main method: if ( name.startsWith( LEGACY_PREFIX ) && name.endsWith( LEGACY_POSTFIX ) ) { - final String cleanName = name.substring( LEGACY_PREFIX.length(), name.length() - LEGACY_POSTFIX.length() ); - return defaultJtaPlatformSelector.resolve( cleanName ); + final String shortName = name.substring( LEGACY_PREFIX.length(), name.length() - LEGACY_POSTFIX.length() ); + return defaultJtaPlatformSelector.resolve( shortName ); } return null; } diff --git a/hibernate-core/src/main/java/org/hibernate/engine/transaction/jta/platform/internal/JBossStandAloneJtaPlatform.java b/hibernate-core/src/main/java/org/hibernate/engine/transaction/jta/platform/internal/JBossStandAloneJtaPlatform.java index 556309ea3c88..2091c09b905f 100644 --- a/hibernate-core/src/main/java/org/hibernate/engine/transaction/jta/platform/internal/JBossStandAloneJtaPlatform.java +++ b/hibernate-core/src/main/java/org/hibernate/engine/transaction/jta/platform/internal/JBossStandAloneJtaPlatform.java @@ -16,7 +16,9 @@ * * @author Emmanuel Bernard * @author Steve Ebersole + * @deprecated Use {@link WildFlyStandAloneJtaPlatform} or {@link NarayanaJtaPlatform} instead. */ +@Deprecated public class JBossStandAloneJtaPlatform extends AbstractJtaPlatform { public static final String JBOSS_TM_CLASS_NAME = "com.arjuna.ats.jta.TransactionManager"; diff --git a/hibernate-core/src/main/java/org/hibernate/engine/transaction/jta/platform/internal/NarayanaJtaPlatform.java b/hibernate-core/src/main/java/org/hibernate/engine/transaction/jta/platform/internal/NarayanaJtaPlatform.java new file mode 100644 index 000000000000..ed2e66214b83 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/engine/transaction/jta/platform/internal/NarayanaJtaPlatform.java @@ -0,0 +1,49 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * Copyright Red Hat Inc. and Hibernate Authors + */ +package org.hibernate.engine.transaction.jta.platform.internal; + +import jakarta.transaction.TransactionManager; +import jakarta.transaction.UserTransaction; +import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; +import org.hibernate.engine.transaction.jta.platform.spi.JtaPlatformException; + +/** + * Return a standalone JTA transaction manager for Narayana (Arjuna) Transactions. + * + * @author Emmanuel Bernard + * @author Steve Ebersole + */ +public class NarayanaJtaPlatform extends AbstractJtaPlatform { + + public static final String TM_CLASS_NAME = "com.arjuna.ats.jta.TransactionManager"; + public static final String UT_CLASS_NAME = "com.arjuna.ats.jta.UserTransaction"; + + @Override + protected TransactionManager locateTransactionManager() { + try { + return (TransactionManager) serviceRegistry().requireService( ClassLoaderService.class ) + .classForName( TM_CLASS_NAME ) + .getMethod( "transactionManager" ) + .invoke( null ); + } + catch ( Exception e ) { + throw new JtaPlatformException( "Could not obtain Narayana TransactionManager instance", e ); + } + } + + @Override + protected UserTransaction locateUserTransaction() { + try { + return (UserTransaction) serviceRegistry() + .requireService( ClassLoaderService.class ) + .classForName( UT_CLASS_NAME ) + .getMethod( "userTransaction" ) + .invoke( null ); + } + catch ( Exception e ) { + throw new JtaPlatformException( "Could not obtain Narayana UserTransaction instance", e ); + } + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/engine/transaction/jta/platform/internal/StandardJtaPlatformResolver.java b/hibernate-core/src/main/java/org/hibernate/engine/transaction/jta/platform/internal/StandardJtaPlatformResolver.java index 095a04fa65c5..499b6c319fba 100644 --- a/hibernate-core/src/main/java/org/hibernate/engine/transaction/jta/platform/internal/StandardJtaPlatformResolver.java +++ b/hibernate-core/src/main/java/org/hibernate/engine/transaction/jta/platform/internal/StandardJtaPlatformResolver.java @@ -62,20 +62,11 @@ public JtaPlatform resolveJtaPlatform(Map configurationValues, ServiceRegis catch (ClassLoadingException ignore) { } - - // JBoss ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Narayana ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ try { - classLoaderService.classForName( JBossStandAloneJtaPlatform.JBOSS_TM_CLASS_NAME ); - classLoaderService.classForName( JBossStandAloneJtaPlatform.JBOSS_UT_CLASS_NAME ); - - // we know that the JBoss TS classes are available - // if neither of these look-ups resulted in an error (no such class), then JBossTM is available on - // the classpath - // - // todo : we cannot really distinguish between the need for JBossStandAloneJtaPlatform versus JBossApServerJtaPlatform - // but discussions with David led to the JtaPlatformProvider solution above, so inside JBoss AS we - // should be relying on that - return new JBossStandAloneJtaPlatform(); + classLoaderService.classForName( NarayanaJtaPlatform.TM_CLASS_NAME ); + classLoaderService.classForName( NarayanaJtaPlatform.UT_CLASS_NAME ); + return new NarayanaJtaPlatform(); } catch (ClassLoadingException ignore) { } diff --git a/hibernate-core/src/main/java/org/hibernate/internal/log/DeprecationLogger.java b/hibernate-core/src/main/java/org/hibernate/internal/log/DeprecationLogger.java index 1a710831a140..0f78e6051fe9 100644 --- a/hibernate-core/src/main/java/org/hibernate/internal/log/DeprecationLogger.java +++ b/hibernate-core/src/main/java/org/hibernate/internal/log/DeprecationLogger.java @@ -6,6 +6,7 @@ import java.lang.annotation.Annotation; import java.lang.invoke.MethodHandles; +import java.util.List; import org.hibernate.Internal; import org.hibernate.boot.jaxb.SourceType; @@ -226,4 +227,11 @@ void recognizedObsoleteHibernateNamespace( value = "Encountered deprecated hint [%s], use [%s] instead" ) void deprecatedHint(String deprecatedHint, String replacementHint); + + @LogMessage(level = WARN) + @Message( + id = 90000038, + value = "Encountered deprecated value for JtaPlatform setting [%s]: [%s]; use a non-deprecated value among %s instead" + ) + void logDeprecatedJtaPlatformSetting(String settingName, String deprecatedValue, List replacements); } diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/strategyselectors/JtaPlatformSelectorTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/strategyselectors/JtaPlatformSelectorTest.java index bff81b733f72..a1870f8d2e6b 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/strategyselectors/JtaPlatformSelectorTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/strategyselectors/JtaPlatformSelectorTest.java @@ -8,10 +8,12 @@ import org.hibernate.engine.transaction.jta.platform.internal.AtomikosJtaPlatform; import org.hibernate.engine.transaction.jta.platform.internal.JBossAppServerJtaPlatform; import org.hibernate.engine.transaction.jta.platform.internal.JBossStandAloneJtaPlatform; +import org.hibernate.engine.transaction.jta.platform.internal.NarayanaJtaPlatform; import org.hibernate.engine.transaction.jta.platform.internal.ResinJtaPlatform; import org.hibernate.engine.transaction.jta.platform.internal.GlassFishJtaPlatform; import org.hibernate.engine.transaction.jta.platform.internal.WebSphereLibertyJtaPlatform; import org.hibernate.engine.transaction.jta.platform.internal.WeblogicJtaPlatform; +import org.hibernate.engine.transaction.jta.platform.internal.WildFlyStandAloneJtaPlatform; import org.hibernate.engine.transaction.jta.platform.spi.JtaPlatform; import org.junit.jupiter.api.Test; @@ -93,6 +95,19 @@ public void verifyAllJtaPlatformResolve() { "org.hibernate.engine.transaction.jta.platform.internal.WebSphereLibertyJtaPlatform" ); + testJtaPlatformResolves( + strategySelector, + WildFlyStandAloneJtaPlatform.class, + "WildFlyStandAlone", + "org.hibernate.engine.transaction.jta.platform.internal.WildFlyStandAloneJtaPlatform" + ); + + testJtaPlatformResolves( + strategySelector, + NarayanaJtaPlatform.class, + "Narayana", + "org.hibernate.engine.transaction.jta.platform.internal.NarayanaJtaPlatform" + ); } private static void testJtaPlatformResolves(final DefaultJtaPlatformSelector strategySelector, final Class expectedType, final String shortname, final String longname) {