EJB: How To Catch javax.persistence.OptimisticLockException 📎
Exceptions like javax.persistence.OptimisticLockException
may occur at commit time and so after the execution of an EJB method. Therefore some occurrences are impossible to catch with the convenient "Container Managed Transactions" configuration.
The method DataStore#update
fails, because SomeEntity
changes are going to be recognized at commit time and so after the execution of this method.
@Stateless
public class DataStore {
@PersistenceContext
EntityManager em;
public void update(String id) {
SomeEntity forUpdate = this.em.find(SomeEntity.class, id);
forUpdate.makeDirty();
}
}
The exception: "javax.ejb.EJBException: Transaction marked for rollback
" is raised after the execution of the EJB and can be only caught in the presentation layer.
However, transactions can be started and committed, and so handled, in an interceptor:
public class TXEnforcer {
@Resource
UserTransaction tx;
private final static Logger LOG = Logger.getLogger(TXEnforcer.class.getName());
@AroundInvoke
public Object beginAndCommit(InvocationContext ic) throws Exception {
try {
tx.begin();
Object retVal = ic.proceed();
tx.commit();
return retVal;
} catch (RollbackException e) {
LOG.severe("-----------------Caught (in interceptor): " + e.getCause());
throw e;
} catch (RuntimeException e) {
tx.rollback();
throw e;
}
}
}
The EJB needs to use the TXEnforcer
interceptor to handle transactions and has to switch to the "Bean Managed Transactions" strategy (otherwise you get a: Caused by: javax.naming.NameNotFoundException: Lookup of java:comp/UserTransaction not allowed for Container managed Transaction beans
):
@Stateless
@Interceptors(TXEnforcer.class)
@TransactionManagement(TransactionManagementType.BEAN)
public class DataStore {
}
In this example the DataStore EJB is a boundary which always initiates a new transaction. Therefore there is no need to handle existing transactions.
Thanks Marian S. for asking the question!
[See also Boundary pattern in the "Real World Java EE Patterns--Rethinking Best Practices" book (Second Iteration, "Green Book"), page 57 in, chapter "Boundary"]
The project catchemall was checked in into http://kenai.com/projects/javaee-patterns