Example usage for org.springframework.transaction.support DefaultTransactionStatus setRollbackOnly

List of usage examples for org.springframework.transaction.support DefaultTransactionStatus setRollbackOnly

Introduction

In this page you can find the example usage for org.springframework.transaction.support DefaultTransactionStatus setRollbackOnly.

Prototype

@Override
    public void setRollbackOnly() 

Source Link

Usage

From source file:net.sf.mmm.orient.db.impl.OrientPlatformTransactionManager.java

@Override
protected void doSetRollbackOnly(DefaultTransactionStatus status) throws TransactionException {

    status.setRollbackOnly();
    OrientTx.of(status).setRollbackOnly();
}

From source file:org.ops4j.orient.spring.tx.OrientTransactionManager.java

@Override
protected void doSetRollbackOnly(DefaultTransactionStatus status) throws TransactionException {
    status.setRollbackOnly();
}

From source file:com.newmainsoftech.spray.slingong.datastore.Slim3PlatformTransactionManager.java

@Override
protected void doSetRollbackOnly(DefaultTransactionStatus status) throws TransactionException {
    String message = String.format("Setting roll-back-only flag(s) up:");

    /*//from  w w  w.  ja va  2  s.  c o  m
     * Set AbstractTransactionStatus's rollbackOnly member field to true
     * what will make DefaultTransactionStatus's isLocalRollbackOnly method
     * returns true. AbstractPlatformTransactionManager's commit method
     * initiate roll back when its isLocalRollbackOnly method returns true.
     * 
     * However, the analysis of the AbstractPlatformTransactionManager's
     * logic flow makes me doubt calling this method will never occurs:
     * 
     * About the case called by processRollback method (that will be called
     * by commit method): commit method calls processRollback method when
     * DefaultTransactionStatus's isLocalRollbackOnly method returns true.
     * DefaultTransactionStatus's isLocalRollbackOnly method is also called by
     * processRollback method, in order for participating transaction to set
     * rollbackOnly member field what is done by calling this
     * doSetRollbackOnly method. Hence, it doesn't make much sense for this
     * case since, in that logic only, this will never be called.
     * 
     * About the case called by doRollbackOnCommitException method (that
     * will be called by processRollback method): When it's participating
     * transaction and globalRollbackOnParticipationFailure flag value is
     * true, then this method is called by doRollbackOnCommitException
     * method. The default value of globalRollbackOnParticipationFailure
     * flag is true what means that the transaction originator cannot make
     * the transaction commit anymore once the transaction marked globally
     * as rollback-only. However, doRollbackOnCommitException method is
     * called by processCommit method and, according to Spring's
     * AbstractPlatformTransactionManager document (@see
     * http://static.springsource
     * .org/spring/docs/current/api/org/springframework
     * /transaction/support/AbstractPlatformTransactionManager
     * .html#setRollbackOnCommitFailure%28boolean%29) the roll back on
     * commit failure typically not necessary and thus to be avoided, as it
     * can potentially override the commit exception with a subsequent
     * rollback exception. I would take this as it means rather
     * intentionally initiating roll back after recognizing commit failure
     * is the recommended way than letting Spring automatically roll back
     * after commit failure, however it does not make sense since, because
     * commit is automatically handled by Spring, how it can know when and
     * how to roll back. It should be automatically rolled back by Spring
     * when failure occurs on the commit that Spring automatically performs.
     */
    status.setRollbackOnly();
    message = message + String.format("%n%tDefaultTransactionStatus object is marked as roll-back-only.");

    GlobalTransaction gtx = (GlobalTransaction) status.getTransaction();
    if (gtx instanceof GlobalTransaction) {
        String gtxIdStr = gtx.getId();
        Slim3GlobalTransactionObject slim3GtxObj = slim3GtxObjMapThreadLocal.get().get(gtxIdStr);
        if (slim3GtxObj != null) {
            slim3GtxObj.setRollbackOnly(true);
            slim3GtxObjMapThreadLocal.get().put(gtxIdStr, slim3GtxObj);
            message = message + String
                    .format("%n%tSlim3GlobalTransactionObject object for GlobalTransaction instance (ID:%1$s) "
                            + "is marked as roll-back-only.", gtxIdStr);
        } else {
            if (logger.isWarnEnabled()) {
                logger.warn(
                        String.format("Inconsistent system state: GlobalTransaction instance (ID:%1$s) held "
                                + "by state DefaultTransactionStatus argument is not among ones managed "
                                + "by %2$s.", gtxIdStr, this.getClass().getName()));
            }
        }
    }

    if (logger.isInfoEnabled())
        logger.info(message);

}

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 -----------------------------------------------------------
    /*/* w  w  w .j a  va 2  s  .c  o  m*/
     * 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.batch.core.step.item.FaultTolerantStepFactoryBeanUnexpectedRollbackTests.java

@Test
@Ignore //FIXME/*from  w  w  w.  java 2s . c o  m*/
public void testTransactionException() throws Exception {

    final SkipWriterStub<String> writer = new SkipWriterStub<String>();
    FaultTolerantStepFactoryBean<String, String> factory = new FaultTolerantStepFactoryBean<String, String>();
    factory.setItemWriter(writer);

    @SuppressWarnings("serial")
    DataSourceTransactionManager transactionManager = new DataSourceTransactionManager(dataSource) {
        private boolean failed = false;

        @Override
        protected void doCommit(DefaultTransactionStatus status) throws TransactionException {
            if (writer.getWritten().isEmpty() || failed || !isExistingTransaction(status.getTransaction())) {
                super.doCommit(status);
                return;
            }
            failed = true;
            status.setRollbackOnly();
            super.doRollback(status);
            throw new UnexpectedRollbackException("Planned");
        }
    };

    factory.setBeanName("stepName");
    factory.setTransactionManager(transactionManager);
    factory.setCommitInterval(2);

    ItemReader<String> reader = new ListItemReader<String>(Arrays.asList("1", "2"));
    factory.setItemReader(reader);

    JobRepositoryFactoryBean repositoryFactory = new JobRepositoryFactoryBean();
    repositoryFactory.setDataSource(dataSource);
    repositoryFactory.setTransactionManager(transactionManager);
    repositoryFactory.afterPropertiesSet();
    JobRepository repository = repositoryFactory.getObject();
    factory.setJobRepository(repository);

    JobExecution jobExecution = repository.createJobExecution("job", new JobParameters());
    StepExecution stepExecution = jobExecution.createStepExecution(factory.getName());
    repository.add(stepExecution);

    Step step = factory.getObject();

    step.execute(stepExecution);
    assertEquals(BatchStatus.FAILED, stepExecution.getStatus());

    assertEquals("[]", writer.getCommitted().toString());
}