hibernate/hibernate-orm · error · HibernateException

Could not obtain TransactionManager from JtaPlatform

Error message

Could not obtain TransactionManager from JtaPlatform

What it means

With hibernate.current_session_context_class=jta, JTASessionContext.currentSession() asks the JtaPlatform service for the JTA TransactionManager to key sessions by transaction. If retrieveTransactionManager() returns null — typically because the default NoJtaPlatform is in effect since no real JTA environment was detected or configured — this HibernateException is thrown before any session is built.

Source

Thrown at hibernate-core/src/main/java/org/hibernate/context/internal/JTASessionContext.java:64

public class JTASessionContext extends AbstractCurrentSessionContext {

	private transient final Map<Object, Session> currentSessionMap = new ConcurrentHashMap<>();

	/**
	 * Constructs a JTASessionContext
	 *
	 * @param factory The factory this context will service
	 */
	public JTASessionContext(SessionFactoryImplementor factory) {
		super( factory );
	}

	@Override
	public Session currentSession() throws HibernateException {
		final var jtaPlatform = factory().getServiceRegistry().requireService( JtaPlatform.class );
		final var transactionManager = jtaPlatform.retrieveTransactionManager();
		if ( transactionManager == null ) {
			throw new HibernateException( "Could not obtain TransactionManager from JtaPlatform" );
		}

		final var txn = getTransaction( transactionManager );
		final Object txnIdentifier = jtaPlatform.getTransactionIdentifier( txn );

		Session currentSession = currentSessionMap.get( txnIdentifier );
		if ( currentSession == null ) {
			currentSession = buildOrObtainSession();
			registerSynchronization( txn, txnIdentifier, currentSession );
			currentSessionMap.put( txnIdentifier, currentSession );
		}
		else {
			validateExistingSession( currentSession );
		}

		return currentSession;
	}

View on GitHub (pinned to fad1729dce)

Solutions

  1. Set a concrete platform: hibernate.transaction.jta.platform=org.hibernate.service.jta.platform.internal.JBossStandAloneJtaPlatform (or the matching class for your TM/server)
  2. Add a real JTA provider to the classpath (org.jboss.narayana:arjuna + JTA artifacts) so platform resolution can succeed
  3. If you do not actually use JTA, switch to hibernate.current_session_context_class=thread (SE) or remove the property in full EE containers where it is derived automatically
  4. Verify the container's JNDI names for the TransactionManager (java:/TransactionManager, java:comp/UserTransaction) match what the chosen platform expects

Example fix

// before
Map<String, Object> cfg = new HashMap<>();
cfg.put("hibernate.current_session_context_class", "jta");
// no JTA provider -> getCurrentSession() throws

// after
cfg.put("hibernate.current_session_context_class", "jta");
cfg.put("hibernate.transaction.jta.platform",
        "org.hibernate.service.jta.platform.internal.JBossStandAloneJtaPlatform");
Defensive patterns

Strategy: validation

Validate before calling

org.hibernate.service.jta.platform.spi.JtaPlatform platform =
        sessionFactory.getServiceRegistry().requireService(org.hibernate.service.jta.platform.spi.JtaPlatform.class);
if (platform.retrieveTransactionManager() == null) {
    throw new IllegalStateException("No JTA TransactionManager available; set hibernate.transaction.jta.platform before using current sessions");
}

Try / catch

try {
    return sessionFactory.getCurrentSession();
} catch (org.hibernate.HibernateException e) {
    if (e.getMessage().contains("Could not obtain TransactionManager")) {
        throw new IllegalStateException("JTA platform misconfigured: no TransactionManager. Check hibernate.transaction.jta.platform and JTA provider on classpath", e);
    }
    throw e;
}

Prevention

When it happens

Trigger: sessionFactory.getCurrentSession() on a factory configured for JTA current-session context while the resolved JtaPlatform is NoJtaPlatform: plain JVM/SE setup with no transaction manager, missing/typo'd hibernate.transaction.jta.platform property, or JNDI lookups failing outside the app server.

Common situations: Unit tests run in the IDE without the Arjuna/Narayana JTA provider on the classpath; Spring Boot apps setting the context to 'jta' without enabling JTA; migrating an app from WildFly to SE while keeping the JTA setting; typo in the JtaPlatform FQCN silently falling back to the default.

Related errors


AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22). Data as JSON: /api/errors/004094e9d62b796a. Report an issue: GitHub.