private void createOrResumeXidTransaction(final XidTransactionID xidTransactionID) throws Exception { final TransactionManager transactionManager = this.ejbRemoteTransactionsRepository.getTransactionManager(); final Transaction alreadyCreatedTx = this.ejbRemoteTransactionsRepository.getTransaction(xidTransactionID); if (alreadyCreatedTx != null) { // resume the already created tx transactionManager.resume(alreadyCreatedTx); } else { // begin a new tx and add it to the tx repository // TODO: Fix the tx timeout (which currently is passed as 300 seconds) // TODO: Also it appears that the TransactionReaper isn't cleared of the ReaperElement, // after the subordinate tx is committed/rolledback. @see // com.arjuna.ats.internal.jta.transaction.arjunacore.subordinate.SubordinateAtomicAction // constructor which accepts the timeout value. The subordinate action is added to the reaper // but never removed // later final Transaction newSubOrdinateTx = SubordinationManager.getTransactionImporter() .importTransaction(xidTransactionID.getXid(), 300); // associate this tx with the thread transactionManager.resume(newSubOrdinateTx); this.ejbRemoteTransactionsRepository.addTransaction(xidTransactionID, newSubOrdinateTx); } }
@Override protected void manageTransaction() throws Throwable { // first associate the tx on this thread, by resuming the tx final Transaction transaction = this.transactionsRepository.getImportedTransaction(this.xidTransactionID); if (transaction == null) { if (EjbLogger.EJB3_INVOCATION_LOGGER.isDebugEnabled()) { // this happens if no ejb invocations where made within the TX EjbLogger.EJB3_INVOCATION_LOGGER.debug( "Not forgetting transaction " + this.xidTransactionID + " as is was not found on the server"); } return; } this.resumeTransaction(transaction); // "forget" final Xid xid = this.xidTransactionID.getXid(); try { // get the subordinate tx final SubordinateTransaction subordinateTransaction = SubordinationManager.getTransactionImporter().getImportedTransaction(xid); if (subordinateTransaction == null) { throw new XAException(XAException.XAER_INVAL); } // invoke forget subordinateTransaction.doForget(); } catch (Exception ex) { final XAException xaException = new XAException(XAException.XAER_RMERR); xaException.initCause(ex); throw xaException; } finally { SubordinationManager.getTransactionImporter().removeImportedTransaction(xid); // disassociate the tx that was associated (resumed) on this thread. // This needs to be done explicitly because the SubOrdinationManager isn't responsible // for clearing the tx context from the thread this.transactionsRepository.getTransactionManager().suspend(); } }
@Override protected void manageTransaction() throws Throwable { // first associate the tx on this thread, by resuming the tx final Transaction transaction = this.transactionsRepository.removeTransaction(this.xidTransactionID); this.resumeTransaction(transaction); try { // invoke the beforeCompletion final Xid xid = this.xidTransactionID.getXid(); // Courtesy: com.arjuna.ats.internal.jta.transaction.arjunacore.jca.XATerminatorImple final SubordinateTransaction subordinateTransaction = SubordinationManager.getTransactionImporter().getImportedTransaction(xid); if (subordinateTransaction == null) { throw new RuntimeException("No subordinate transaction present with xid " + xid); } // do beforeCompletion() subordinateTransaction.doBeforeCompletion(); } finally { // disassociate the tx that was associated (resumed) on this thread. // This needs to be done explicitly because the SubOrdinationManager isn't responsible // for clearing the tx context from the thread this.transactionsRepository.getTransactionManager().suspend(); } }