04.05.2016 | Paulin Nguimdoh | comment icon 3 Comments

How to start a new transaction inside a single EJB

When invoking a method of an EJB we get features like transactions, security or monitoring for free. Method calls within the same bean do not enjoy this benefits. This post shows by example how a method can be isolated from the current running EJB transaction and processed in a new separated one.

To start a new transaction in an EJB-Context we use the attribute TransactionAttributeType.REQUIRES_NEW, which can be annotated to a method in the following example:

However, this can be a little bit tricky if we want to call such a method from another method in a single EJB. Imagine we have two methods cleanEntities() and delete() in an EJB. The method cleanEntities deletes records from a database table by calling the delete for every record, which should be processed in a new transaction as shown in listing 2.

If we run this code, we’ll be surprised that the method delete will never run in a new separated transaction as expected. The container will ignore the TransactionAttributeType.REQUIRES_NEW from the EJB. The reason of this behaviour is that the call of delete inside method cleanEntities will be treated as a normal Java invocation and not as an EJB method invocation and we’ll not get any warning from the container preventing that a new transaction haven’t being started.

There are several approaches to solve this problem:
The first way is to have a new EJB reference of the class. We call the method with the injected reference of the EJB itself as shown in listing 3:

In this example the call of the method delete from the EJB itself will start a separated new transaction.

* The second way is to get an instance of type SessionContext that can be used to invoke the current bean through a particular business interface. The code below shows how to archive this.

 

ejb java ee SessionContext stateless transaction
  1. Fighting the Transaction Reaper - Exxeta Blog
    Posted on
    […] I used the command pattern to separate the business logic. So, the concrete service call will be implemented in method Command#execute(). The worker runs this code in a new transaction. When execution is done we check for possible rollbacks and invoke callback method Command#onRollback() – again this implementation is service specific. In our scenario we sent an E-Mail. The call to execute the rollback code runs in another new transaction. Usage of SessionContext is based on a hack described in Paulin’s post. […]
  2. Intermediate commit within transaction - Exxeta Blog
    Posted on
    […] call flushToDatabase directly. Paulin’s post describes this problem and solution in detail: start new transaction inside single ejb). Afterwards we call em.refresh(task) to reload the entity to bring the surrounding transaction in […]
  3. markiewb
    Posted on
    Why don't you annotate cleanEntities() with @TransactionAttribute(value = TransactionAttributeType.REQUIRES_NEW) ?

Leave a Comment