H1101
H1101

Reputation: 193

Behavior when Spring Propagation.REQUIRES_NEW is nested in a Propagation.NESTED

I have code like so

@Transactional(propagation = Propagation.NESTED)
@TransactionConfiguration(transactionManager = "transactionManager", defaultRollback = true)
public class C1 {
...
   public void xxx() {
      try {
         obj.someMethod();
      } catch (Exception e) {
         C2.yyy();
      }
   }
}

public class C2 {
    @Transactional(propagation = Propagation.REQUIRES_NEW, readOnly = false)
    public void yyy() {
        ...
    }
}

My assumption is that when obj.someMethod(); throws a constraint violation exception C2.yyy() should still be able to save stuff to the DB.

However what I see is that when C2.yyy() is called Postgres reports

ERROR: current transaction is aborted, commands ignored until end of transaction block

Why should it do that? After all C2.yyy() should run in a different transaction that should be unaffected by the state of what happened in the invoking code. No?

Update

On further debugging here is what I found - let us say the call stack is like so

@Transactional(readOnly = false, propagation = Propagation.NESTED)
b1.m1()
       @Transactional(readOnly = false, propagation = Propagation.REQUIRES_NEW)
       b2.m2()
              b3.m3()
                      b4.m4()

My assumption was that the DB code in m4() would execute in a new transaction because of the annotation on b2.m2(). But it seems the code in TransactionAspectSupport.java looks at the transaction annotation only on the current method and not on the stack. When it does not find any @transactional on m4() it assumes REQUIRES. Isn't this incorrect?

Upvotes: 2

Views: 2289

Answers (1)

Alexander
Alexander

Reputation: 2888

As answered here DatabaseError: current transaction is aborted, commands ignored until end of transaction block : "This is what postgres does when a query produces an error and you try to run another query without first rolling back the transaction".

Meaning that you 'obj' should run in its own transaction and roll back on exception.

Regarding the question in the update: REQUIRES_NEW always creates a new transaction, it is both documented and tested.

Upvotes: 1

Related Questions