EJB: How to start a new transaction for a call on this()

Sometimes it is necessary to start a new transaction in a stateless sessionbean with container managed transactions (CMT). For that, usually a new SLSB is created and given the transactionattribute REQUIRES_NEW. Unknown to many is the fact that from a SLSB, methods on this() can be called that also start a new transaction.
The reason why this doesn’t work out-of-the-box is that a call on this() is a POJO-call and thus the container is unaware of the call and has no chance to handle transactions. So the solution is to make the container aware of the call by obtaining a reference to this() through the SessionContext.
Here is an example for it:

@javax.ejb.Stateless
@javax.ejb.Local(SomeInterface.class)
public class SomeInterfaceImpl implements SomeInterface {
    @javax.annotation.Resource
    private SessionContext sessionContext;

    @Override //has the TX-Attribute REQUIRED
    public List<String> doSomething(){
        sessionContext.getBusinessObject(SomeInterface.class).doInNewTx();
        throw new RuntimeException(); //Abort the Transaction
    }

    @Override
    @javax.ejb.TransactionAttribute(REQUIRES_NEW)
    public void doInNewTx(){
        /* persist something with the EntityManager, it will be persisted
           although the caller rolls back its Tx, cause this method runs
           in its own transaction */
    }
}

To try this out, create SomeInterfaceImpl and SomeInterface, and call doSomething() via an EJB-call. It will internally call doInNewTx() in a new transaction and then abort the current transaction by throwing a RuntimeException. Everything persisted in doInNewTx() will be written to the database, as it uses a new transaction that is committed independently.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.