Container Managed Transaction, EJB 3 and Exceptions

Let‘s face it. Exceptions in Java have always been a nightmare because we‘ve never known how to handle them properly. Hundreads of articles and thousands of blogs have tried to help us on “how to use exceptions in Java“. We went from “all exception should be checked“ to “all shoud be unchecked“ and then to “business exception should be checked and technical exceptions unchecked“, “each layer should wrap the parent exception“, “just throw it to the client”… hummm… I‘m not even sure if I agree with all that.

On top of all that, Java EE 5 has arrived with a new annotation that can confuse even more the way exceptions should be handled. You can now annotate an exception with @ApplicationException. It is a nice way to distinguish application exceptions from system exceptions. Before we would assume that checked exception would be application exception and unchecked system exception. It‘s not the case. An application exception can be a subclass of java.lang.Exception (checked exception), or of java.lang.RuntimeException (unchecked exception). The only constraint is that an application exception cannot be a subclass of java.rmi.RemoteException (therefore javax.ejb.EJBException

In terms of transactions, how does it work? Let‘s take a simple example that I‘ve used in a previous post with two stateless EJBs. ABean (persists a A object) and BBean (persists a B object). ABean calls BBean both using the default TransactionAttributeType.REQUIRED

@Stateless
public class ABean implements ARemote {

    @PersistenceContext private EntityManager em;
    @EJB private BLocal bBean;

    public void createsA() {
        // Calls the BBean
        bBean.createsB();
        A a = new A(b);
        em.persist(a);
    }
}

@Stateless
public class BBean implements BLocal {

    @PersistenceContext private EntityManager em;

    @TransactionAttribute(TransactionAttributeType.NEVER)
    public void createsB() {
        B b = new B();
        em.persist(b);
        // Throws an exception
        throw new xxxException;   (1)
    }
}

On the BBean.createsB() method you can throw different kind of exceptions (1). The basic ones are as follow :

| Type of exception | is the transaction rollbacked |
| An EJBException | transaction is rollbacked |
| Exception | B is committed |
| RuntimeException | transaction is rollbacked |

That‘s what we are use to. A checked exception (java.lang.Exception) would not rollback the transaction, but an unchecked will.

Now with the @ApplicationException annotation you can specify if an exception is an application one and if you need to rollback or not. For that you just use the rollback parameter. If set to true, the transaction is rollbacked, is set to false, it is not. So you have 4 different choices :

| Type of exception | rollback parameter | is the transaction rollbacked |
| Exception | rollback=false | B is committed |
| Exception | rollback=true | transaction is rollbacked |
| RuntimeException | rollback=false | B is committed |
| RuntimeException | rollback=true | transaction is rollbacked |

And this is how to use the @ApplicationException annotation :

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

}

Categories: Java

1 Comment »

  1. We have a huge banking EJB application where ApplicationException is an user defined exception. And as we migrate to EJB3, we are not able to annotate ApplicationException with @ApplicationException(rollback=true). It just not easy to rename this exception. Anyway thanks for the info.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s