List of usage examples for org.springframework.transaction.support DefaultTransactionStatus isNewTransaction
@Override public boolean isNewTransaction()
From source file:com.eclecticlogic.pedal.impl.JPATransactionWrapper.java
@Override protected void prepareSynchronization(DefaultTransactionStatus status, TransactionDefinition definition) { super.prepareSynchronization(status, definition); if (status.isNewTransaction()) { TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapterData()); TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapterTask()); }//from www . ja v a2 s . c o m }
From source file:com.newmainsoftech.spray.slingong.datastore.Slim3PlatformTransactionManager.java
@Override protected void doRollback(DefaultTransactionStatus defaultTransactionStatus) throws TransactionException { // Sanity check on precondition ----------------------------------------------------------- /* When logic flow got here, it should be not the case of participating existing transaction that * means the target method is the outer most transactional method what began a transaction process * at the first, and that also means newTransaction boolean member field of DefaultTransactionStatus * object should be true.//from w w w.j av a 2s . co m */ if (!defaultTransactionStatus.isNewTransaction()) { // Could be caused by unaware code change on org.springframework.transaction.support.AbstractPlatformTransactionManager throw new TransactionSystemException(String.format( "Unexpected system state: attempting to roll back from participation of an " + "existing transaction (of which GlobalTransacion Id is %1$s).", ((defaultTransactionStatus.getTransaction() instanceof GlobalTransaction) ? ((GlobalTransaction) defaultTransactionStatus.getTransaction()).getId() : "null"))); } // ---------------------------------------------------------------------------------------- // Check on GlobalTransaction instance ---------------------------------------------------- GlobalTransaction gtx = (GlobalTransaction) defaultTransactionStatus.getTransaction(); Set<GlobalTransactionState> gtxStateSet = getGlobalTransactionStates(gtx); if (!gtxStateSet.contains(GlobalTransactionState.GlobalTransactionInstance)) { throw new TransactionSystemException( "Inconsistent status: defaultTransactionStatus argument is not holding " + "GlobalTransaction instance."); } String gtxIdStr = gtx.getId(); Map<String, Slim3GlobalTransactionObject> slim3GtxObjMap = slim3GtxObjMapThreadLocal.get(); Slim3GlobalTransactionObject slim3GtxObj = slim3GtxObjMap.get(gtxIdStr); if (slim3GtxObj == null) { if (logger.isErrorEnabled()) { logger.error(String.format("Encountered inconsistent status: GlobalTransaction instance (ID:%1$s) " + "held by defaultTransactionStatus argument is not among ones managed " + "by %2$s.", gtxIdStr, this.getClass().getName())); } } if (!gtxStateSet.contains(GlobalTransactionState.ActiveGlobalTransaction)) { /* Reminder: gtx here can be inactive by the ConcurrentModificationException case. * However, it's not 100% certain that, in ConcurrentModificationException case, * gtx here will be always inactive. */ slim3GtxObjMapThreadLocal.get().remove(gtxIdStr); if (logger.isWarnEnabled()) { logger.warn(String.format("Skipping to perform roll back on GlobalTransaction (ID:%1$s) since " + "it has been already in inactive state.", gtxIdStr)); } return; } if (!(gtxStateSet.contains(GlobalTransactionState.CurrentGlobalTransaction))) { /* Changed from throwing TransactionSystemException to logging incident in order to * avoid leaving GlobalTransaction instance active as much as possible by proceeding further. */ GlobalTransaction currentGtx = Datastore.getCurrentGlobalTransaction(); if (logger.isErrorEnabled()) { logger.error(String.format( "Encountered inconsistent status: GlobalTransaction object (ID:%1$s) held " + "by defaultTransactionStatus argument is not current active GlobalTransaction " + "instance (ID:%2$s).", gtxIdStr, ((currentGtx instanceof GlobalTransaction) ? currentGtx.getId() : "null"))); } } // ---------------------------------------------------------------------------------------- try { if (logger.isInfoEnabled()) { logger.info(String.format("Rolling back on Slim3 GlobalTransaction (ID:%1$s)", gtxIdStr)); } /* Note: There are the cases that GlobalTransaction instance has already been rolled back by * Slim3 behind scene of Spring transaction framework when commit failed and GlobalTransaction * instance remains active state. Even the control flow reached in those cases, there should be * no harm being made by rolling back here again. */ gtx.rollback(); } catch (Throwable throwable) { String message = String.format("Rolling back on Slim3 GlobalTransaction (ID:%1$s) failed.", gtxIdStr); throw new TransactionSystemException(message, throwable); } finally { slim3GtxObjMapThreadLocal.get().remove(gtxIdStr); /* Not necessary to call defaultTransactionStatus.setCompleted method in this block because * it will be called later in cleanupAfterCompletion method. defaultTransactionStatus.setCompleted(); */ if (gtx.isActive()) { if (logger.isErrorEnabled()) { logger.error(String.format("Slim3 GlobalTransaction (ID:%1$s) remains active " + "after the attempt of rolling back.", gtxIdStr)); } } } }
From source file:com.newmainsoftech.spray.slingong.datastore.Slim3PlatformTransactionManagerTest.java
/** * @param transactionCommited: true when committed. false for not committed, but it's not for verifying * roll back./* www.j a va 2 s . co m*/ */ protected void verifyCommitProcess(boolean transactionCommited) { /* Mockito cannot spy on "final" method because it cannot mock "final" method: * @see http://docs.mockito.googlecode.com/hg/org/mockito/Mockito.html#13 mockedSlim3TxMangerInOrder.verify( slim3PlatformTransactionManager, Mockito.times( 1)) .commit( transactionStatusArgumentCaptor.capture()); */ // protected boolean shouldCommitOnGlobalRollbackOnly() // private void processCommit(DefaultTransactionStatus status) // protected void prepareForCommit(DefaultTransactionStatus status) // protected final void triggerBeforeCommit(DefaultTransactionStatus status) // protected final void triggerBeforeCompletion(DefaultTransactionStatus status) // If it's not new transaction (means not outer most transaction), then call public final boolean isFailEarlyOnGlobalRollbackOnly() ArgumentCaptor<DefaultTransactionStatus> defaultTransactionStatusArgumentCaptor = ArgumentCaptor .forClass(DefaultTransactionStatus.class); if (transactionCommited) { mockedSlim3TxMangerInOrder.verify(slim3PlatformTransactionManager, Mockito.times(1)) .doCommit(defaultTransactionStatusArgumentCaptor.capture()); DefaultTransactionStatus defaultTransactionStatus = (DefaultTransactionStatus) (defaultTransactionStatusArgumentCaptor .getValue()); Assert.assertTrue(defaultTransactionStatus.isCompleted()); // should be true since actually commit has already finished Assert.assertTrue(defaultTransactionStatus.isNewTransaction()); Assert.assertTrue(defaultTransactionStatus.hasTransaction()); Assert.assertTrue(defaultTransactionStatus.getTransaction() instanceof GlobalTransaction); ArgumentCaptor<GlobalTransaction> globalTransactionArgumentCaptor = ArgumentCaptor .forClass(GlobalTransaction.class); mockedSlim3TxMangerInOrder.verify(slim3PlatformTransactionManager, Mockito.times(1)) .getGlobalTransactionStates(globalTransactionArgumentCaptor.capture()); GlobalTransaction gtx = globalTransactionArgumentCaptor.getValue(); Assert.assertTrue(gtx instanceof GlobalTransaction); } else { mockedSlim3TxMangerInOrder.verify(slim3PlatformTransactionManager, Mockito.never()) .doCommit(defaultTransactionStatusArgumentCaptor.capture()); } // private void triggerAfterCommit(DefaultTransactionStatus status) // private void triggerAfterCompletion(DefaultTransactionStatus status, int completionStatus) // private void cleanupAfterCompletion(DefaultTransactionStatus status) // protected void doCleanupAfterCompletion(Object transaction) }
From source file:com.newmainsoftech.spray.slingong.datastore.Slim3PlatformTransactionManagerTest.java
protected void verifyRollbackProcess(boolean readOnlyEnabled, boolean roolBackOnlyEnabled, boolean debugEnabled) { // public final void rollback(TransactionStatus status) // private void processRollback(DefaultTransactionStatus status) // protected final void triggerBeforeCompletion(DefaultTransactionStatus status) ArgumentCaptor<DefaultTransactionStatus> defaultTransactionStatusArgumentCaptor = ArgumentCaptor .forClass(DefaultTransactionStatus.class); mockedSlim3TxMangerInOrder.verify(slim3PlatformTransactionManager, Mockito.times(1)) .doRollback(defaultTransactionStatusArgumentCaptor.capture()); DefaultTransactionStatus defaultTransactionStatus = defaultTransactionStatusArgumentCaptor.getValue(); Assert.assertTrue(defaultTransactionStatus.getTransaction() instanceof GlobalTransaction); GlobalTransaction gtx = (GlobalTransaction) defaultTransactionStatus.getTransaction(); Assert.assertTrue(defaultTransactionStatus.isNewTransaction()); Assert.assertTrue(defaultTransactionStatus.isCompleted()); // Should be true since actually transaction has already been finished Assert.assertEquals(readOnlyEnabled, defaultTransactionStatus.isReadOnly()); Assert.assertEquals(roolBackOnlyEnabled, defaultTransactionStatus.isRollbackOnly()); /* If defaultTransactionStatus.isRollbackOnly() returns true, then either * its isGlobalRollbackOnly() or its isLocalRollbackOnly() returns true. *//*from ww w.ja v a2 s. co m*/ if (defaultTransactionStatus.isRollbackOnly() && logger.isDebugEnabled()) { logger.debug("defaultTransactionStatus.isGlobalRollbackOnly() = " + defaultTransactionStatus.isGlobalRollbackOnly()); logger.debug("defaultTransactionStatus.isLocalRollbackOnly() = " + defaultTransactionStatus.isLocalRollbackOnly()); } Assert.assertEquals(debugEnabled, defaultTransactionStatus.isDebug()); Assert.assertFalse(defaultTransactionStatus.isTransactionSavepointManager()); Assert.assertTrue(defaultTransactionStatus.isNewSynchronization()); mockedSlim3TxMangerInOrder.verify(slim3PlatformTransactionManager, Mockito.times(1)) .getGlobalTransactionStates(Mockito.eq(gtx)); // private void triggerAfterCompletion(DefaultTransactionStatus status, int completionStatus) // private void cleanupAfterCompletion(DefaultTransactionStatus status) // protected void doCleanupAfterCompletion(Object transaction) }
From source file:com.newmainsoftech.spray.slingong.datastore.Slim3PlatformTransactionManager.java
@Override protected void doCommit(DefaultTransactionStatus defaultTransactionStatus) throws TransactionException { GlobalTransaction gtx = (GlobalTransaction) defaultTransactionStatus.getTransaction(); Set<GlobalTransactionState> gtxStateSet = getGlobalTransactionStates(gtx); // Sanity check on precondition ----------------------------------------------------------- /*//from w ww . java2s . com * This will be called at outermost transaction boundary (defaultTransactionStatus.isNewTransaction() * will return true). * When defaultTransactionStatus has been set for roll back, roll back doesn't need to be handled * within doCommit method. * When either defaultTransactionStatus's isGlobalRollbackOnly and shouldCommitOnGlobalRollbackOnly * returns true or its isLocalRollbackOnly returns true, then logic flow won't reach here and * roll back should have been performed by doRollback. */ if (defaultTransactionStatus.isRollbackOnly()) { throw new TransactionSystemException(String.format( "Unexpected system state: the transaction for the GlobalTransaction " + "instance (ID:%1$s) has been marked as roll-back only " + "(LocalRollbackOnly:%2$b, GlobalRollbackOnly:%3$b).", (gtxStateSet.contains(GlobalTransactionState.GlobalTransactionInstance) ? gtx.getId() : "null"), defaultTransactionStatus.isLocalRollbackOnly(), defaultTransactionStatus.isGlobalRollbackOnly())); } if (!defaultTransactionStatus.isNewTransaction()) { throw new TransactionSystemException(String.format( "Unexpected system state: attempted to commit from participation of an existing " + "transaction (of which GlobalTransacion Id is %1$s).", (gtxStateSet.contains(GlobalTransactionState.GlobalTransactionInstance) ? gtx.getId() : "null"))); } // ---------------------------------------------------------------------------------------- // Sanity check on gtx GlobalTransaction instance ----------------------------------------- if (!gtxStateSet.contains(GlobalTransactionState.ActiveGlobalTransaction)) { String message; if (!gtxStateSet.contains(GlobalTransactionState.GlobalTransactionInstance)) { message = "Unexpected system state: The GlobalTransaction object passed as the transaction " + "Object argument is null."; } else { message = String .format("Unexpected system state: The GlobalTransaction instance (ID:%1$s) passed as the " + "transaction Object argument is inactive.", gtx.getId()); } throw new IllegalTransactionStateException(message); } if (!gtxStateSet.contains(GlobalTransactionState.CurrentGlobalTransaction)) { /* The one possible case of the control flow reaching here is that GlobalTransaction object * is manually instantiated at the outside of Spring transaction framework, and it is left active. * * In nesting global transaction, easy to yield ConcurrentModificationException without care. * Nesting global transaction should be less necessary, since Slim3 isolate between (Global) * transactions and cannot change that isolation setting, and this uses Slim3 GlobalTransaction, * as GAE/J datastore API is not provide suspend feature as well. */ GlobalTransaction currentGtx = Datastore.getCurrentGlobalTransaction(); if (logger.isWarnEnabled()) { logger.warn(String.format( "Though active GlobalTransaction instance (ID:%1$s) is passed as transaction " + "Object argument, it's not current GlobalTransaction instance (ID:%2$s).", gtx.getId(), ((currentGtx instanceof GlobalTransaction) ? currentGtx.getId() : "null"))); } } // ---------------------------------------------------------------------------------------- boolean exceptionUp = false; try { gtx.commit(); slim3GtxObjMapThreadLocal.get().remove(gtx.getId()); if (logger.isInfoEnabled()) { logger.info(String.format("Slim3 GlobalTransaction (ID:%1$s) committed.", gtx.getId())); } } catch (Throwable throwable) { /* Set rollback only flag so calling processRollback method to roll back will occur at * commit method by AnnotationTransactionAspect, even for other exceptions than ones specified * for rollbackFor or rollbackForClassname attributes of @Transactional annotation. */ defaultTransactionStatus.setRollbackOnly(); exceptionUp = true; String message = String.format("Slim3 GlobalTransaction (ID:%1$s) failed on commit.", gtx.getId()); if ((throwable instanceof ConcurrentModificationException) || (throwable instanceof DeadlineExceededException)) { /* Slim3 should have already rolled back automatically on either * ConcurrentModificationException or DeadlineExceededException. * * About DeadlineExceededException case: It seems like no harm * will be made even active global transaction at * DeadlineExceededException case left behind. As looking * briefly through the Slim3 source codes, the locks by that * global transaction seems to be released while it rolls back * by DatastoreFilter, and itself seem to be removed from * TheadLocal stack of the global transactions. So, it won't be * returned by such Datastore.getCurrentGlobalTransaction() * method. See at * http://groups.google.com/group/slim3-user/browse_frm * /thread/e3d47d8f28c8e8d3 * /9e43553f3b56d1f2?tvc=1#9e43553f3b56d1f2 If it turns out * opposite, then that active global transaction can be cleared * some how at here for DeadlineExceededException case. */ message = String.format("Slim3 GlobalTransaction (ID:%1$s) failed on commit. %n" + "Slim3 must have already rolled back automatically behind " + "Spring transaction framework.", gtx.getId()); } throw new TransactionSystemException(message, throwable); } finally { if (gtx.isActive()) { if (exceptionUp) { if (logger.isInfoEnabled()) { logger.info(String.format( "GlobalTransaction instance (ID:%1$s) remains active after exception " + "durring commit attempt. That GlobalTransaction instance has not " + "been removed yet from slim3GtxObjMapThreadLocal member field.", gtx.getId(), this.getClass().getName())); } } else { if (logger.isWarnEnabled()) { logger.warn(String.format( "Unexpected system state: GlobalTransaction instance (ID:%1$s) " + "remains active even after commit attempt. That GlobalTransaction " + "instance was removed from slim3GtxObjMapThreadLocal member field.", gtx.getId(), this.getClass().getName())); } } } } }
From source file:org.springframework.transaction.support.AbstractPlatformTransactionManager.java
/** * Process an actual commit.//from w ww . j ava 2 s .c o m * Rollback-only flags have already been checked and applied. * @param status object representing the transaction * @throws TransactionException in case of commit failure */ private void processCommit(DefaultTransactionStatus status) throws TransactionException { try { boolean beforeCompletionInvoked = false; try { boolean unexpectedRollback = false; prepareForCommit(status); triggerBeforeCommit(status); triggerBeforeCompletion(status); beforeCompletionInvoked = true; if (status.hasSavepoint()) { if (status.isDebug()) { logger.debug("Releasing transaction savepoint"); } unexpectedRollback = status.isGlobalRollbackOnly(); status.releaseHeldSavepoint(); } else if (status.isNewTransaction()) { if (status.isDebug()) { logger.debug("Initiating transaction commit"); } unexpectedRollback = status.isGlobalRollbackOnly(); doCommit(status); } else if (isFailEarlyOnGlobalRollbackOnly()) { unexpectedRollback = status.isGlobalRollbackOnly(); } // Throw UnexpectedRollbackException if we have a global rollback-only // marker but still didn't get a corresponding exception from commit. if (unexpectedRollback) { throw new UnexpectedRollbackException( "Transaction silently rolled back because it has been marked as rollback-only"); } } catch (UnexpectedRollbackException ex) { // can only be caused by doCommit triggerAfterCompletion(status, TransactionSynchronization.STATUS_ROLLED_BACK); throw ex; } catch (TransactionException ex) { // can only be caused by doCommit if (isRollbackOnCommitFailure()) { doRollbackOnCommitException(status, ex); } else { triggerAfterCompletion(status, TransactionSynchronization.STATUS_UNKNOWN); } throw ex; } catch (RuntimeException | Error ex) { if (!beforeCompletionInvoked) { triggerBeforeCompletion(status); } doRollbackOnCommitException(status, ex); throw ex; } // Trigger afterCommit callbacks, with an exception thrown there // propagated to callers but the transaction still considered as committed. try { triggerAfterCommit(status); } finally { triggerAfterCompletion(status, TransactionSynchronization.STATUS_COMMITTED); } } finally { cleanupAfterCompletion(status); } }
From source file:org.springframework.transaction.support.AbstractPlatformTransactionManager.java
/** * Process an actual rollback.//from w w w.ja v a 2 s . c o m * The completed flag has already been checked. * @param status object representing the transaction * @throws TransactionException in case of rollback failure */ private void processRollback(DefaultTransactionStatus status, boolean unexpected) { try { boolean unexpectedRollback = unexpected; try { triggerBeforeCompletion(status); if (status.hasSavepoint()) { if (status.isDebug()) { logger.debug("Rolling back transaction to savepoint"); } status.rollbackToHeldSavepoint(); } else if (status.isNewTransaction()) { if (status.isDebug()) { logger.debug("Initiating transaction rollback"); } doRollback(status); } else { // Participating in larger transaction if (status.hasTransaction()) { if (status.isLocalRollbackOnly() || isGlobalRollbackOnParticipationFailure()) { if (status.isDebug()) { logger.debug( "Participating transaction failed - marking existing transaction as rollback-only"); } doSetRollbackOnly(status); } else { if (status.isDebug()) { logger.debug( "Participating transaction failed - letting transaction originator decide on rollback"); } } } else { logger.debug("Should roll back transaction but cannot - no transaction available"); } // Unexpected rollback only matters here if we're asked to fail early if (!isFailEarlyOnGlobalRollbackOnly()) { unexpectedRollback = false; } } } catch (RuntimeException | Error ex) { triggerAfterCompletion(status, TransactionSynchronization.STATUS_UNKNOWN); throw ex; } triggerAfterCompletion(status, TransactionSynchronization.STATUS_ROLLED_BACK); // Raise UnexpectedRollbackException if we had a global rollback-only marker if (unexpectedRollback) { throw new UnexpectedRollbackException( "Transaction rolled back because it has been marked as rollback-only"); } } finally { cleanupAfterCompletion(status); } }
From source file:org.springframework.transaction.support.AbstractPlatformTransactionManager.java
/** * Invoke {@code doRollback}, handling rollback exceptions properly. * @param status object representing the transaction * @param ex the thrown application exception or error * @throws TransactionException in case of rollback failure * @see #doRollback// w ww . ja va 2s.c o m */ private void doRollbackOnCommitException(DefaultTransactionStatus status, Throwable ex) throws TransactionException { try { if (status.isNewTransaction()) { if (status.isDebug()) { logger.debug("Initiating transaction rollback after commit exception", ex); } doRollback(status); } else if (status.hasTransaction() && isGlobalRollbackOnParticipationFailure()) { if (status.isDebug()) { logger.debug("Marking existing transaction as rollback-only after commit exception", ex); } doSetRollbackOnly(status); } } catch (RuntimeException | Error rbex) { logger.error("Commit exception overridden by rollback exception", ex); triggerAfterCompletion(status, TransactionSynchronization.STATUS_UNKNOWN); throw rbex; } triggerAfterCompletion(status, TransactionSynchronization.STATUS_ROLLED_BACK); }
From source file:org.springframework.transaction.support.AbstractPlatformTransactionManager.java
/** * Trigger {@code afterCompletion} callbacks. * @param status object representing the transaction * @param completionStatus completion status according to TransactionSynchronization constants *///from w w w .ja v a 2 s . com private void triggerAfterCompletion(DefaultTransactionStatus status, int completionStatus) { if (status.isNewSynchronization()) { List<TransactionSynchronization> synchronizations = TransactionSynchronizationManager .getSynchronizations(); TransactionSynchronizationManager.clearSynchronization(); if (!status.hasTransaction() || status.isNewTransaction()) { if (status.isDebug()) { logger.trace("Triggering afterCompletion synchronization"); } // No transaction or new transaction for the current scope -> // invoke the afterCompletion callbacks immediately invokeAfterCompletion(synchronizations, completionStatus); } else if (!synchronizations.isEmpty()) { // Existing transaction that we participate in, controlled outside // of the scope of this Spring transaction manager -> try to register // an afterCompletion callback with the existing (JTA) transaction. registerAfterCompletionWithExistingTransaction(status.getTransaction(), synchronizations); } } }
From source file:org.springframework.transaction.support.AbstractPlatformTransactionManager.java
/** * Clean up after completion, clearing synchronization if necessary, * and invoking doCleanupAfterCompletion. * @param status object representing the transaction * @see #doCleanupAfterCompletion// www . ja v a 2 s . co m */ private void cleanupAfterCompletion(DefaultTransactionStatus status) { status.setCompleted(); if (status.isNewSynchronization()) { TransactionSynchronizationManager.clear(); } if (status.isNewTransaction()) { doCleanupAfterCompletion(status.getTransaction()); } if (status.getSuspendedResources() != null) { if (status.isDebug()) { logger.debug("Resuming suspended transaction after completion of inner transaction"); } Object transaction = (status.hasTransaction() ? status.getTransaction() : null); resume(transaction, (SuspendedResourcesHolder) status.getSuspendedResources()); } }