Search code examples
javatransactionsjava-ee-6

EjbConetxt setRollbackOnly vs ApplicationException rollback true


I have a method which throws an application exception with rollback true. I wonder if I have to explicitly call ejbContext.setRollbackOnly() or not?

The docs here says that we need not call the EjbContext's setRollbackOnly when the exception is marked as rollback=true.

In my case I catch a ApplicationException whose rollback attribute is set to true. Then I explicitly call ejbContext.setRollbackOnly() because I throw another exception in the catch block and this exception will be propagated to the client. Below is my code snippet

try {
   ....
} catch (XYZDirectoryException e) { // ApplicationException marked as rollback=true
   ejbContext.setRollbackOnly();  // Is this necessary?
   // log exception trace
   throw new ServerInternalException("Something bad happened. Please try again or contact administrator. Check logs for more details"); // ApplicationException marked as rollback=false
}

Solution

  • An exception will not cause a rollback if it's thrown and caught inside a EJB transactional method. It has just to be thrown from a EJB transactional method in order to be caught by the transactional proxy around the EJB instance, otherwise, the container is completely unaware of the exception and thus won't rollback:

    public void someEjbTransactionalMethod() {
        // will cause a rollback
        throw new XYZDirectoryException();
    }
    
    public void someOtheEjbTransactionalMethod() {
        // will NOT cause a rollback
        try {
            throw new XYZDirectoryException();
        }
        catch (XYZDirectoryException) {
            ...
        }
    }
    

    So, in your case, since the exception doesn't cross the boundary of any transactional EJB method, the container won't be aware of this exception, and won't rollback, unless you throw another "rollback=true" exception from the catch block, or explicitely mark the transaction as rollbackOnly.