EJB: Avoid Transaction rollback
Asked Answered
S

2

24

When a (transactional) method of an EJB calls another (transactional) method of another EJB, and an exception is thrown in the second, but catched in the first one, it seems that the transaction is automatically rolled back when the second one returns, even if the first one catches it, is this true? how can I avoid it?

The scenario is the following one:

@Stateless
class ClassA {
   @EJB
   ClassB objectB;

   methodA() { 
       try { 
            objectB.methodB(); 
       }
       catch(Exception e) {
            //Here the transaction started in this method is 
            //automatically rolled back. Is this avoidable?
       } 
   }
}

@Stateless
class ClassB {
   methodB() throws Exception { throw new Exception() }
}
Simas answered 13/12, 2011 at 14:16 Comment(0)
M
28

Transaction is rolled back in case you throw a RuntimeException or any Exception which have @ApplicationException annotation with rollback attribute set to true, so:

@ApplicationException(rollback=true)
public class MyException extends Exception {
    // ...
}

will rollback the current transaction.

By default ApplicationException doesn't rollback your transaction.

If you don't want to methodB to rollback your transaction you can either change the rollback behavior of your ApplicationException or prevent the transaction sharing.

The latter is achievable by changing the TransactionAttribute of methodB i.e. to RequiresNew. Then methodA transaction (Tx1) will be suspendend and in case methodB throws an exception which results in rollback of its transaction (Tx2), you can still catch it in methodA and prevent rollback of your methodA transaction (Tx1).

Mathia answered 13/12, 2011 at 15:19 Comment(1)
If in the latter, you catch methodB exception, then do some logging etc, but also throw that same exception again, it will rollback the methodA normally?Illness
D
12

Yes, it's true, if the exception is a runtime exception. Checked exceptions don't cause a transaction rollback.

To avoid it, just make sure that the code in methodB doesn't throw any runtime exception. A runtime exception normally indicates a bug, or a state which doesn't allow for continuing the work.

Denazify answered 13/12, 2011 at 14:23 Comment(7)
My bad, sorry, i modified the question to note that it is throwing a checked exception, is the transaction rolled back also in this scenario?Simas
No, it shouldn't be rolled back if the exception is a checked exception.Denazify
If all you know is that the Exception is checked you cannot say if it will or won't rollback your transaction. If it's @ApplicationException(rollback=true) it might rollback your transaction.Mathia
@Piotr: you're right. Unless annotated with @ApplicationException(rollback=true), a checked exception won't rollback the transaction. Unless annotated with @ApplicationException(rollback=false), a runtime exceoption will rollback the transaction.Denazify
@JBNizet +1 for brining the case of RuntimeException with rollback=false.Mathia
@JBNizet : what about Spring transaction. how to tackle this problem ?Pimental
@MohdAdnan: Spring has a similar mechanism, and similar defaults. They're described in the documentation: static.springsource.org/spring/docs/3.1.x/…Denazify

© 2022 - 2024 — McMap. All rights reserved.