How do I get informed in a stateless session bean that the transaction need to be rolled back? For example, I have a stateless EJB which is updating a LuceneIndex with some business data. The method is called in a transaction with several EJB calls. When some of the later EJBs rolls back the transaction, than how can I be informed about this issue so that I am able to roll back my already written LuceneIndex entry?
2 Answers
You can do this by injecting a reference to the current EJBContext and then querying it:
@Stateless
public class LuceneDriver {
@Resource
private EJBContext ejbContext;
public void performLuceneStuff(...) {
try {
...
// update lucene data
...
// update some business data
...
} catch (BusinessException e) {
if (ejbContext.getRollbackOnly()) {
// rollback lucene changes
}
}
}
...
}

- 18,876
- 5
- 34
- 37
-
But what if the rollBack was initialized by another EJB in the same transaction after my method performLuceneStuff() has already finished? – Ralph Jul 20 '17 at 17:36
-
1It does not matter. EJBs have always been highly transaction aware. The only time that `ejbContext.getRollbackOnly()` will not work is if the other EJB started a new transaction. A new transaction will only have been started if you explicitly configured it to do so. – Steve C Jul 21 '17 at 01:43
-
I may still be standing on the hose... What I am expecting is a mechanism to register a callback method which is called by the transaction manager when someone else in the same transaction (not my bean) failed. So that I can undo - my already written index files. – Ralph Jul 21 '17 at 16:47
-
Ok slowly I recognize my mistake. A stateless EJB can not be called for a rollback because of the missing state information. Maybe I need some kind of resource adapter to manage my Lucene index problem.... – Ralph Jul 21 '17 at 17:05
-
If you don't mind managing the life cycle you can use an @Stateful bean that implements the [javax.ejb.SessionSynchronization](http://docs.oracle.com/javaee/7/api/javax/ejb/SessionSynchronization.html) interface. That provides a callback. You could use the "state" of the EJB to provide the information necessary to rollback your Lucene changes – Steve C Jul 22 '17 at 02:12
-
Yes a @Stateful bean could be a solution. But in the moment I try to implement a JCA Connector.... – Ralph Jul 22 '17 at 09:00
If a session EJB is not transactional you won't be able to rollback in case of a failure. This is because of the missing state information of stateless session EJBs.
One solution to solve this issue is to use a @Stateful session bean that implements the javax.ejb.SessionSynchronization
interface. This interface allows you to react on a rollback.
Another solution is to work with custom EventLog entries written by the main transaction via JPA. With those eventLog entries another stateless session EJBs can verify if new EventLog entries exist and if, they can react on it. If the trancaction was rolled back, also the uncommitted EventLog entries will be removed by the transaction manager. So this is a solution to couple non-transactional functionality to a JPA container based transaction. See the question: How to react on a EJB3 transaction commit or rolleback?

- 4,500
- 9
- 48
- 87