Announcement Announcement Module
No announcement yet.
Transactions: Is this the right behaviour? Page Title Module
Move Remove Collapse
Conversation Detail Module
  • Filter
  • Time
  • Show
Clear All
new posts

  • Transactions: Is this the right behaviour?

    I have this following issue with transactions and I wonder if it is correct transactional behaviour or I am using transactions in the wrong way. I hope that somebody could give me a hint.

    I am using
    Spring Framework 1.2.7
    Hibernate 3.0.5
    Java 1.5.0_06

    In generaral, I have a manager class and a DAO class. They both use transactions declared with Annotations.
    Here are the classes:

    @Transactional(rollbackFor = DAOException.class, propagation=Propagation.REQUIRED)
    public interface BaseDAO
    public void persist(Object vo) throws DAOException;
    public void flush() throws DAOException;

    @Transactional(rollbackFor = {ProcessingException.class}, propagation=Propagation.REQUIRED)
    public interface UserManager
    public void addUser(User user) throws ProcessingException, DAOException;

    public class UserManagerImpl
    public void addUser(User user)
    throws ProcessingException, DAOException
    ...... //some business logic

    So I have the following user case.
    I am invoking the addUser(user) method of the UserManager which then invokes the dao methods. The second invokation, the flush() method throws DAOException.
    The exception is being propagated, but at the end in the method which invoked the manager class I get the following exception:

    org.springframework.transaction.UnexpectedRollback Exception: Transaction has been rolled back because it has been marked
    as rollback-only

    When debugging I can see two TransactionInterceptors, one for the manager class and one for the DAO class
    The inner interceptor(DAO) rolls back the transaction and rethrows DAOException.
    But then, the second Interceptor tries to commit the transaction and throws the o.s.t.UnexpectedRollbackException.
    This seems to be a bit strange to me as there should be only one transaction... When I checked the txInfo.transactionStatus.completed flag, they were different for the both TransactionInterceptors. It was true for the inner interceptor(DAO) and false for the out(Manager)

    Later I tried to change the Manager interface like this
    @Transactional(rollbackFor = {ProcessingException.class, DAOException.class}, propagation=Propagation.REQUIRED)
    public interface UserManager

    Namely, I added the DAOException to the rollbackFor property of the @Transacitonal annotation.

    Now I get my DAOException.
    The question is shouldn't I get it in the first case too as there should be only one transaction, because I am using Propogation.REQUIRED.

    If this is a problem I was glad two help. If this is misunderstanding of how transactions should behave. I would be glad if somebody enlightened me.

    Best Regards,
    Dragomir Nikolov

  • #2
    Re: Transactions: Is this the right behaviour?

    Can anyone comment on this? The question in a more general case boils down to the following when using Spring's JtaTransactionManager and declarative transactions (using Spring 1.2.8):

    - Method A starts a transaction, and invokes method B, which has a transaction attribute of PROPOGATION_REQUIRED.
    - Method B rolls back the transaction, but method A does not (i.e. by catching the Exception from method B)
    - The transaction interceptor will try to commit when method A returns (apparently not detecting that the transaction was already rolled back by method B), and throws an Exception when trying to commit.

    Here is a rough sketch of what the code would look like:

    class Service1 {
        public void method1() {
            try {
            } catch(RuntimeException e) {
    class Service2 {
        public void method2() { ... }
    Is this the intended behavior? Should method1 be trying to commit when method2 caused a rollback on the propogated transaction, thus throwing an UnexpectedRollbackException?

    Thanks in advance,
    Brett Borchardt


    • #3
      You can control this behavior with the property 'globalRollbackOnParticipationFailure' of 'AbstractPlatformTransactionManager'.

      MfG Mirko