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 { }
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.
Thanks.. very good!
It’s help me to understand better about Exception on Java EE, thank you