Announcement Announcement Module
Collapse
No announcement yet.
Rollbacking nested transactions Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Rollbacking nested transactions

    Imagine the following situation:

    Code:
    public class C1 implements I1{
       private I2 i2;
    
       public void method(){//[1]
          try{
              i2.method2();
          }
          catch (SomeRuntimeException ex){
            //It is normal situation in this case, just continue our work.
          }
          //[5]
       }
    }
    
    public class C2 implements I2{
       public void method2() throws SomeRuntimeException{//[2]
          throw new SomeRuntimeException();//[3]
       }//[4]
    }
    Both interfaces are proxied with transactions with PROPAGATION_REQUIRED attribute.

    So if we call I1 method, the transaction begins at point [1], call to I2 joins this transaction at point [2] and do not create a new one. Then exception is thrown at point [3] and transaction interceptor marks transacation as rollback-only at point [4]. And so at point [5] we recieve a failure if we touch the database.

    Well, that was the situation. I do know about REQUIRES_NEW, about checked exceptions and so on. The question is different:
    Is it Ok for transaction interceptor to roll the transaction back if and only if we leave the same method which created this transacation (the outer-most method)? And if method which throws an exception has merely joined some existing transaction then this method won't touch this transaction.

  • #2
    Originally posted by nikem View Post
    ............
    Is it Ok for transaction interceptor to roll the transaction back if and only if we leave the same method which created this transacation (the outer-most method)? And if method which throws an exception has merely joined some existing transaction then this method won't touch this transaction.
    Yes, I guess you are completely right. But till this functionality will be corrected (if ever) easy workaround exists - annotate i2.method2 not
    with simple @Transactional, but with

    @Transactional(noRollbackFor={SomeRuntimeException .class})


    Regards,

    Oleksandr Alesinskyy

    Comment


    • #3
      Unfortunately, your suggestions is not applicable in this case method2 is called directly from the web as well, so it should be runtime decision, whether to roll back or not.

      But well, it is easy enough to write my own Transaction Interceptor

      Comment


      • #4
        Originally posted by nikem View Post
        Unfortunately, your suggestions is not applicable in this case method2 is called directly from the web as well, so it should be runtime decision, whether to roll back or not.

        But well, it is easy enough to write my own Transaction Interceptor
        Even easier is to write wrapper around method2

        @Transactional
        void wrappedMethod2() {
        method2();
        }

        @Transactional(noRollbackFor=SomeRuntimeException. class)
        void method2() {
        ...
        }

        or, even better

        @Transactional
        void method2() {
        doMethod2();
        }

        // No transactional annotation here
        void doMethod2() {
        ...
        }

        and call doMethod2 from i1.method1()

        Concerning interceptor - it may be not so easy - not because it is complicated, but because interfaces that it called are not very stable, for example some method names/signatures/behavior in them have changed from 3.0 RC3 to 2.0 final. I'm afraid that you would have touch your interceptor with each new minor version of Spring. But, probably, somebody from Spring Team may comment on it.

        Regards,

        Oleksandr Alesinskyy

        Comment

        Working...
        X