{"record":{"id":"e64c9d1a2d2ea0d9","repo":"hibernate/hibernate-orm","slug":"explicitly-joining-a-jta-transaction-requires-a-jt","errorCode":null,"errorMessage":"Explicitly joining a JTA transaction requires a JTA transaction be currently active","messagePattern":"Explicitly joining a JTA transaction requires a JTA transaction be currently active","errorType":"exception","errorClass":"TransactionRequiredException","httpStatus":null,"severity":"error","filePath":"hibernate-core/src/main/java/org/hibernate/internal/AbstractSharedSessionContract.java","lineNumber":1416,"sourceCode":"\t\t\t}\n\t\t\tcatch (HibernateException e) {\n\t\t\t\tthrow e;\n\t\t\t}\n\t\t\tcatch (RuntimeException e) {\n\t\t\t\tthrow new HibernateException( \"Exception pulsing TransactionCoordinator\", e );\n\t\t\t}\n\t\t}\n\t}\n\n\t@Override\n\tpublic void joinTransaction() {\n\t\tcheckOpen();\n\t\ttry {\n\t\t\t// For a non-JTA TransactionCoordinator, this just logs a WARNing\n\t\t\ttransactionCoordinator.explicitJoin();\n\t\t}\n\t\tcatch ( TransactionRequiredForJoinException e ) {\n\t\t\tthrow new TransactionRequiredException( e.getMessage() );\n\t\t}\n\t\tcatch ( HibernateException he ) {\n\t\t\tthrow getExceptionConverter().convert( he );\n\t\t}\n\t}\n\n\t@Override\n\tpublic boolean isJoinedToTransaction() {\n\t\tcheckOpen();\n\t\treturn transactionCoordinator.isJoined();\n\t}\n\n\tprotected void delayedAfterCompletion() {\n\t\tif ( transactionCoordinator instanceof JtaTransactionCoordinatorImpl jtaTransactionCoordinator ) {\n\t\t\tjtaTransactionCoordinator.getSynchronizationCallbackCoordinator().processAnyDelayedAfterCompletion();\n\t\t}\n\t}\n","sourceCodeStart":1398,"sourceCodeEnd":1434,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-core/src/main/java/org/hibernate/internal/AbstractSharedSessionContract.java#L1398-L1434","documentation":"joinTransaction()/EntityManager.joinTransaction() asks the JTA TransactionCoordinator to explicitly join the current JTA transaction. The coordinator raises TransactionRequiredForJoinException when no JTA transaction is active on the thread; AbstractSharedSessionContract converts it to jakarta.persistence.TransactionRequiredException with this message. Joining is only meaningful when a JTA transaction exists to join.","triggerScenarios":"em.joinTransaction() called with no active JTA transaction: inside @TransactionAttribute(NOT_SUPPORTS/NEVER), before the container started the transaction, from background threads, or in code assuming a transaction that the caller never started.","commonSituations":"Porting between app servers or to Quarkus/Spring; defensively calling joinTransaction 'for safety' in scheduled jobs or batch steps; unit tests without a transactional context; a JTA TransactionManager configured but the business method not annotated @Transactional.","solutions":["Call joinTransaction() only inside an active JTA transaction — annotate the method @Transactional (REQUIRED) so the container starts one.","If the work legitimately needs no transaction, drop the joinTransaction() call entirely.","Check JTA status first via UserTransaction/TransactionManager and skip the join when STATUS_NO_TRANSACTION."],"exampleFix":"// before\npublic void run() { em.joinTransaction(); process(); } // throws if no JTA tx\n// after\n@Transactional\npublic void run() { em.joinTransaction(); process(); } // tx active, join succeeds","handlingStrategy":"validation","validationCode":"if (userTransaction.getStatus() != Status.STATUS_NO_TRANSACTION) {\n    em.joinTransaction();\n} // else: nothing to join; proceed without or start a transaction first","typeGuard":null,"tryCatchPattern":"try {\n    em.joinTransaction();\n} catch (TransactionRequiredException e) {\n    // decide: start a transaction, or skip the join — never ignore silently\n    userTransaction.begin();\n    em.joinTransaction();\n}","preventionTips":["Call joinTransaction() only from methods already demarcated @Transactional","In jobs and batch steps, start the JTA transaction explicitly before joining","Delete defensive joinTransaction() calls in code that has no transaction semantics"],"tags":["hibernate","jta","transactions","jointransaction","entitymanager"],"backgroundTag":"transaction-required","analyzedSha":"fad1729dce015f908198d57a8d80274a30f905a5","analyzedAt":"2026-08-22T04:13:57.527Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}