Weblogic 12.1.3 opens a transaction even with TransactionAttributeType.NEVER or NOT_SUPPORTED

The problem

An stateless EJB is used to process lot of records, one by one, without using a global transaction that envelopes everything.

Well, here the initial solution is to annotate the EJB with:

@TransactionAttribute(TransactionAttributeType.NEVER)

An example of this kind of class would be:

@Stateless
@LocalBean
@TransactionAttribute(TransactionAttributeType.REQUIRES_NEVER)
public class EJBThatProcessAll {
    @EJB
    private EJBThatProcessRecord ejbThatProcessRecord;

    public List<Result> processRecords(List<Record> records) {
        return records.parallelStream()
                      .map(EJBThatProcessRecord::processRecord)
                      .collect(Collectors.toList());
    }
}

Then the method which process the records calls (for every record) another EJB that is anotated with:

@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)

So every record is processed in its own transaction.

@Stateless
@LocalBean
@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
public class EJBThatProcessRecord {
    public Result processRecord(Record record) {
        return doSomethingWithRecord(record);
    }
}

Issues found

Even every call to process a record was less than 1 sec. at some moment I always got a TransactionTimeoutException. The container was complaining that some transaction lasted more than 60 s (which was the timeout set for this application).

Attempt 1

Well, I tried several things. The first one was changing TransactionAttriibuteType.NEVER by TransactionAttriibuteType.NOT_SUPPORTED. Failed with same error.

Attempt 2

Since I was not sure about the parallel processing, I tried to change parallelStream() to stream(). Failed with same error.

Attempt 3

A mate read somewhere that if the EJB was asynchronous, it could avoid the transaction, so I annotated the EJB with:

@Asynchronous

And changed the method to return a Future<List<Result>>. But the result was the same. Failed.

Good solution

Finally I changed the main EJB so the transactions were bean managed:

@TransactionManagement(TransactionManagementType.BEAN)

And it worked!. No need anything else but a good comment above the annotation about why I did it, because I know that sooner or later another developer will find it weird and would try to change it by the initial solution.

Testing

At the beginning the initial solution was tested through JUnit and it worked fine. I found the bug while testing the actual web application, so it’s clear that it’s the container that creates a transaction when the EJBThatProcessAll is called, even when it’s annotated to not use transactions at all. And it this case the application container was Weblogic 12.1.3 I don’t know what happens in other containers like JBoss.