Java Ninja Chronicles By Norris Shelton

Things I learned in the pursuit of code

We normally use @Transactional to declaratively control transactions. Sometimes, that doesn’t quite give us the flexibility we need. I had a case where I needed the ability to write data to a database within a transaction, but I couldn’t use an exception to indicate a rollback was necessary because there was information within the method that I would need. Specifically, I needed the information related to the failure. In order for this to work. I had to use a Springframework TransactionTemplate. Like most Spring Template objects, it’s fairly easy to use. Note that an exception will cause an automatic rollback, just like the normal transactional processing.

First, you need to declare the TransactionManager and the TransactionTemplate. In this case, my transaction manager gets it’s database connection from an EntityManagerFactory because I am using JPA.

    <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"
          p:entityManagerFactory-ref="entityManagerFactory"/>

    <bean id="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate"
          p:transactionManager-ref="transactionManager"/>

Once the TransactionTemplate is declared, it can be injected like any other spring bean.

    @Autowired
    private TransactionTemplate transactionTemplate;

A TransactionTemplate exposes it’s functionality via a callback method. One implementation does not have a return type and the other has a return type that can be expressed as a generic.

Here is an example of using the callback method that doesn’t have a return type. This is implemented by implementing an anonymous inner-class of type TransactionCallbackWithoutResult. This is an abstract class with one method, doInTransactionWithoutResult. The TransactionStatus object is used to rollback the transaction. This is caused by calling setRollbackOnly().

transactionTemplate.execute(new TransactionCallbackWithoutResult() {
    @Override
    protected void doInTransactionWithoutResult(TransactionStatus status) {
        // do this
        // do that
        // if some sort of state exists
        status.setRollbackOnly();;
        // }
    }
});

If you need to return data from inside the callback method, then use the TransactionCallback. This works like the other callback method, but allows a value to be returned. Note that the Boolean return type is a generic and can be specified as whatever you need it to be.

boolean returnValue = transactionTemplate.execute(new TransactionCallback<Boolean>() {
    @Override
    public Boolean doInTransaction(TransactionStatus status) {
        // do this
        // do that
        // if some sort of state exists
        status.setRollbackOnly();
        // }
        return myObject.getMyBoolean();
    }
});

If you need a return value and you are on JDK8, you can use a Lambda expression to make the code even smaller.

boolean returnValue = transactionTemplate.execute(status -> {
    // do this
    // do that
    // if some sort of state exists
    status.setRollbackOnly();
    // }
    return null;
});

August 5th, 2015

Posted In: Java, java ninja, Javaninja, Spring

Tags: , , , , ,

Leave a Comment

WP to LinkedIn Auto Publish Powered By : XYZScripts.com