{"record":{"id":"47dfbbb9d39bceff","repo":"hibernate/hibernate-orm","slug":"transaction-is-not-accessible-when-using-jta-with","errorCode":null,"errorMessage":"Transaction is not accessible when using JTA with JPA-compliant transaction access enabled","messagePattern":"Transaction is not accessible when using JTA with JPA-compliant transaction access enabled","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"hibernate-core/src/main/java/org/hibernate/internal/AbstractSharedSessionContract.java","lineNumber":1334,"sourceCode":"\t\tif ( !factoryOptions.isAllowOutOfTransactionUpdateOperations()\n\t\t\t\t&& !isTransactionInProgress() ) {\n\t\t\tthrow new TransactionRequiredException( exceptionMessage );\n\t\t}\n\t}\n\n\tprivate boolean isTransactionAccessible() {\n\t\t// JPA requires that access not be provided to the transaction when using JTA.\n\t\t// This is overridden when SessionFactoryOptions isJtaTransactionAccessEnabled() is true.\n\t\treturn factoryOptions.isJtaTransactionAccessEnabled() // defaults to false in JPA bootstrap\n\t\t\t|| !factoryOptions.getJpaCompliance().isJpaTransactionComplianceEnabled()\n\t\t\t|| !factory.transactionCoordinatorBuilder.isJta();\n\t}\n\n\t@Override\n\t@Nonnull\n\tpublic Transaction getTransaction() throws HibernateException {\n\t\tif ( !isTransactionAccessible() ) {\n\t\t\tthrow new IllegalStateException(\n\t\t\t\t\t\"Transaction is not accessible when using JTA with JPA-compliant transaction access enabled\"\n\t\t\t);\n\t\t}\n\t\treturn accessTransaction();\n\t}\n\n\t@Override\n\t@Nonnull\n\tpublic Transaction accessTransaction() {\n\t\tcheckSessionReentrancy();\n\t\tif ( currentHibernateTransaction == null ) {\n\t\t\tcurrentHibernateTransaction = new TransactionImpl( getTransactionCoordinator(), this );\n\t\t}\n\t\tif ( isOpenOrWaitingForAutoClose() ) {\n\t\t\ttransactionCoordinator.pulse();\n\t\t}\n\t\treturn currentHibernateTransaction;\n\t}","sourceCodeStart":1316,"sourceCodeEnd":1352,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-core/src/main/java/org/hibernate/internal/AbstractSharedSessionContract.java#L1316-L1352","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","solutions":["Use JTA demarcation instead: @Transactional (Jakarta/Spring) or UserTransaction begin/commit — never em.getTransaction() under JTA.","If legacy behavior must be kept, set hibernate.jta.allowTransactionAccess=true to re-enable resource-local style access.","Or configure the persistence unit as RESOURCE_LOCAL where you genuinely control transactions yourself."],"exampleFix":"// before (JTA environment)\nem.getTransaction().begin(); // IllegalStateException\n// after\n@Transactional\npublic void transfer(...) { ... }\n// or manual JTA:\nuserTransaction.begin(); try { ...; userTransaction.commit(); } catch (Exception e) { userTransaction.rollback(); }","handlingStrategy":"validation","validationCode":"// Detect JTA up front and use the right demarcation style\nboolean jta = ((SessionFactoryImplementor) emf).getOptions()\n        .getJpaCompliance().isJpaTransactionComplianceEnabled()\n    && ((SessionFactoryImplementor) emf).getTransactionCoordinatorBuilder().isJta();\nif (jta) {\n    userTransaction.begin();  // JTA path: never em.getTransaction()\n} else {\n    em.getTransaction().begin(); // resource-local path: OK\n}","typeGuard":null,"tryCatchPattern":"try {\n    em.getTransaction().begin();\n} catch (IllegalStateException e) {\n    if (e.getMessage().contains(\"JTA\")) {\n        throw new UnsupportedOperationException(\"Use UserTransaction/@Transactional under JTA\", e);\n    }\n    throw e;\n}","preventionTips":["Centralize transaction begin/commit in one helper that knows the environment","When porting to JTA, grep the codebase for getTransaction() and replace with @Transactional","Document whether each persistence unit is JTA or RESOURCE_LOCAL next to its config"],"tags":["hibernate","jta","jpa","transactions","entitymanager"],"backgroundTag":"jta-transaction-access","analyzedSha":"fad1729dce015f908198d57a8d80274a30f905a5","analyzedAt":"2026-08-22T04:13:57.527Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}