I have a task which consists of 3 steps prepare
, execute
, update
. prepare
and update
need to work within a transaction, whereas execute
takes very long (i.e. several minutes up to hours). The task is part of an EJB, i.e.:
@Stateless
public class Task {
public void doTask() {
prepare();
execute();
update();
}
}
My question is, is there an (elegant) way to commit and finish the transaction after prepare
and start a new one before update
? I'd rather use container-managed transactions and possibly not switch to use UserTransaction
.
It is possible to split the tasks into single EJBs if it gains any advantage, but note that suspending the transaction for execute
(i.e. using @Transactional(TxType.NOT_SUPPORTED)
is not enough since this still triggers the timeout.
I tried to split it into a TaskExecute
class which has @Asynchronous @Transactional(NOT_SUPPORTED) public void execute()
and sending an event when done. But this doesn't seem to work either.
Is there a way to do this?
After some further testing let me conclude: Alexanders reply was absolutely correct. My understanding had to be altered. Foremost, I wasn't aware that @Transactional
does not work on EJBs, but only on CDI beans. For EJBs the annotation is called @TransactionAttribute
and can be set to basically the same values. A combination of @Asynchronous
and @TransactionAttribute(NOT_SUPPORTED)
does work (if not waiting for the result).
It depends on the version of Java EE you want to use. Here are three possible solutions.
execute
in the MDB (any version, but full profile required)execute
asynchronously (@Timeout
)The latter is probably what you are looking for, but only available in Java EE 7.0 and up. Otherwise, the JMS solutions is the cleanest, but if JMS is not an option, the Timer Service should work.