hibernate/hibernate-orm · error · IllegalStateException

Transaction is not accessible when using JTA with JPA-compli

Error message

Transaction is not accessible when using JTA with JPA-compliant transaction access enabled

What it means

JPA forbids EntityManager.getTransaction() when transactions are JTA-managed, unless the provider option allows it. Hibernate computes this in isTransactionAccessible(): access is blocked when JTA is in use, JPA transaction compliance is enabled, and hibernate.jta.allowTransactionAccess (JtaTransactionAccessEnabled, default false in JPA bootstrap) is not set. getTransaction() then throws IllegalStateException instead of handing out an unusable Transaction object.

Source

Thrown at hibernate-core/src/main/java/org/hibernate/internal/AbstractSharedSessionContract.java:1334

		if ( !factoryOptions.isAllowOutOfTransactionUpdateOperations()
				&& !isTransactionInProgress() ) {
			throw new TransactionRequiredException( exceptionMessage );
		}
	}

	private boolean isTransactionAccessible() {
		// JPA requires that access not be provided to the transaction when using JTA.
		// This is overridden when SessionFactoryOptions isJtaTransactionAccessEnabled() is true.
		return factoryOptions.isJtaTransactionAccessEnabled() // defaults to false in JPA bootstrap
			|| !factoryOptions.getJpaCompliance().isJpaTransactionComplianceEnabled()
			|| !factory.transactionCoordinatorBuilder.isJta();
	}

	@Override
	@Nonnull
	public Transaction getTransaction() throws HibernateException {
		if ( !isTransactionAccessible() ) {
			throw new IllegalStateException(
					"Transaction is not accessible when using JTA with JPA-compliant transaction access enabled"
			);
		}
		return accessTransaction();
	}

	@Override
	@Nonnull
	public Transaction accessTransaction() {
		checkSessionReentrancy();
		if ( currentHibernateTransaction == null ) {
			currentHibernateTransaction = new TransactionImpl( getTransactionCoordinator(), this );
		}
		if ( isOpenOrWaitingForAutoClose() ) {
			transactionCoordinator.pulse();
		}
		return currentHibernateTransaction;
	}

View on GitHub (pinned to fad1729dce)

Solutions

  1. Use JTA demarcation instead: @Transactional (Jakarta/Spring) or UserTransaction begin/commit — never em.getTransaction() under JTA.
  2. If legacy behavior must be kept, set hibernate.jta.allowTransactionAccess=true to re-enable resource-local style access.
  3. Or configure the persistence unit as RESOURCE_LOCAL where you genuinely control transactions yourself.

Example fix

// before (JTA environment)
em.getTransaction().begin(); // IllegalStateException
// after
@Transactional
public void transfer(...) { ... }
// or manual JTA:
userTransaction.begin(); try { ...; userTransaction.commit(); } catch (Exception e) { userTransaction.rollback(); }
Defensive patterns

Strategy: validation

Validate before calling

// Detect JTA up front and use the right demarcation style
boolean jta = ((SessionFactoryImplementor) emf).getOptions()
        .getJpaCompliance().isJpaTransactionComplianceEnabled()
    && ((SessionFactoryImplementor) emf).getTransactionCoordinatorBuilder().isJta();
if (jta) {
    userTransaction.begin();  // JTA path: never em.getTransaction()
} else {
    em.getTransaction().begin(); // resource-local path: OK
}

Try / catch

try {
    em.getTransaction().begin();
} catch (IllegalStateException e) {
    if (e.getMessage().contains("JTA")) {
        throw new UnsupportedOperationException("Use UserTransaction/@Transactional under JTA", e);
    }
    throw e;
}

Prevention

When it happens

Trigger: Calling em.getTransaction().begin()/commit()/rollback() or session.getTransaction() in a JTA environment (WildFly, WebSphere, Spring with JtaTransactionManager) with default settings — typical in code ported from resource-local deployments (plain Tomcat/Spring default).

Common situations: Porting a resource-local application to an app server or JTA transaction manager; legacy Hibernate-native code using session.getTransaction(); toggling hibernate.jpa.compliance settings during JPA certification; framework tests using RESOURCE_LOCAL against a JTA-configured PU.

Related errors


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