Thread-Model, Transactionhandling and JPA under Java EE

Hello everybody,

I started using Axon under java EE (Wildfly). Since the EE support is not as good documented as the spring support I have some questions regarding thread-model, transaction handling together with using JPA this setting.

EE has (historically) a thread-per-request model, transactions are normally handled declarativly and request context is normally also transaction context. EntityManager is injected into the request context (so you have a pooled session-per thread handling behind the scenes). Als this is controlled by the container behind the scenes. As such creation of custom threads was long formally forbidden (and only recently relaxed) since everything within such threads was outside the application server control and could even disturb it processing.

Looking at Axon and under the asumption that commands are triggered from “normal” EE requests (likle REST calls, JSF frontend, message driven beans or similar) handling of commands, persisting to the event store and using subscribing event processors should be safe to use in the context of EE, because no threads are created and everything works synchronous in the context of the request. I thus can use EntityManager injection and declarative transaction handling, I just make sure that the NoTransactionManager is used for this, so that EE transactions are in control and custom transaction do not interfer (though if Axon calls the TransactionManageer to commit() it will actually not commit, the commit will come later at the end of the request processing).

Correct so far? Does this make sense? Any problem with this, especially the potential “late” commit?

TrackingEventProcessor (further called TEP) however is another beast, since it works asynchronously, does spawn its own threads thus does not process within a “normal” request context. Luckely EE now in the current days hopefully has something to handle this :slight_smile:

I thus assume that TrackingEventprocessor can work EE compatible under the following asumptions:

Any comment on this solution? Should this work? Any experiences with it?

Hi Tim,

managing a Transaction outside of the scope of a Unit of Work may lead to problems. Reason is that the lifecycle of the Unit of Work takes transactions into account. The “onCleanup” phase is designed to be executed after a commit or rollback. In this phase, locks are released, for example.
When managing the Transaction outside of the unit of work, it is possible that locks are released while a transaction is still active, which may result in more ConcurrencyExceptions being raised.

Regarding threading, Axon allows configuration of a ThreadFactory (or Executor) in all component that work asynchronously. You can easily provide one that uses JEE managed threads.

Hope this clarifies things.
Cheers,

Allard

Hello Allard,

thanks for your response. Some further questions to better understand your answer and to make sure I choose the right approach.

managing a Transaction outside of the scope of a Unit of Work may lead to problems. Reason is that the lifecycle of the Unit of Work takes transactions into account. The “onCleanup” phase is designed to be executed after a commit or rollback. In this phase, locks are released, for example.

I interpret your answer this way, that I should not rely on the transaction control of the EE container in the first case I mentionend (processing of commands, aggregates handling up to synchronous event handling using a subscribing event processor), because the transaction region as created by thr EE container is too big and might interfer with the expected transaction handling (and cleanup) expected in the context of the unit of work concept. I suggested to use a NoTransactionManager in this case, but your response hint to using a custom transaction manager that assures a new (user) transaction is created and commited/rolllbacked if called. I do not need to assign a EE based thread factory in this case because no new threads a created during command processing, aggregation handling and processing of subscribing event processors. Everything is done in the contect of the calling thread, which is already (normally) EE based. Right? Corrections from your side?

In turn I assume that the solution is described for thread handling and transaction handling in the context of a tracking event processor is (in principle) correct?

When managing the Transaction outside of the unit of work, it is possible that locks are released while a transaction is still active, which may result in more ConcurrencyExceptions being raised.
Regarding threading, Axon allows configuration of a ThreadFactory (or Executor) in all component that work asynchronously. You can easily provide one that uses JEE managed threads.

OK.

Hi Tim,

all your assumptions are correct.

Allard