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
I thus assume that TrackingEventprocessor can work EE compatible under the following asumptions:
- I would assign a ManagedThreadFactory (see https://docs.oracle.com/javaee/7/api/javax/enterprise/concurrent/ManagedThreadFactory.html), which implements ThreadFactory to the TEP. This should make sure that the threads it creates are still EE-compatible threads.
- I would implement a TransactionManager, that creates a UserTransaction and make comit()/rollback() work on it (see the ManagedThreadFactory for a simple example regarding UserTransactions).
- I can then inject an EntityManager as normal to use JPA to create my persistent read model.
- It should also be possible to just inject an Java EE Bean and call one of its methods to delegate processing and keep as much of the code in the EE world (See also https://martinsdeveloperworld.wordpress.com/2014/02/25/using-java-ees-managedexecutorservice-to-asynchronously-execute-transactions/)
Any comment on this solution? Should this work? Any experiences with it?