I have a task to complete that involves rolling back changes to a non-transactional database in the event that my EJB transaction is rolled back.
The project uses container managed transactions, and the business logic involves calls to EJB methods that themselves call other EJB methods, so the transaction crosses method boundaries and involves multiple EJBs.
The EJB transaction rollback is working fine, but I need to be able to detect that it has occurred and then fire of a method that will attempt to rollback the other non-transactional database.
I wondered about using an interceptor but it seems that I can only intercept a particular method call, or a particular EJB lifecycle event. This is not really enough for my purpose. I need to intercept the transaction rollback event. Is this possible? Am I barking up the wrong tree? Perhaps there is another approach that would better suit my purpose.
I saw a related question but it doesn't really help me as I have many entry points, many nested methods and I can't just intercept a single method.
EJB Interceptors and transaction lifecycle OR how to intercept a commit/failure event?
If you are using Container Managed Transactions, then when the EJB method call succeeds, it is guaranteed that the transaction has been commited, and if you get an exception, then it is ensured that the transaction has been rolled back.
So one possible way that I see is using a EJB wrapper around the actual EJB call (REQUIRES_NEW
is important here).
@Stateless
public class EJBWrapper {
@EJB
private EJBService service;
public void wrapperMethod() {
try {
service.actualMethod(); // the real work is done here
} catch (RuntimeException) {
// transaction has been rolled back here
}
}
}
@Stateless
public class EJBService {
@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
public void actualMethod() {
// do your work here
}
}
You would need to put a wrapper around each relevant service.