EntityManager access in new Thread

I have wired my Axon app using Spring Boot annotations.
I use JPA for event store persistence.
Getting JPA to work with Axon took some experimentation, and while it appears to work OK, I may have got something wrong...

I now need to have a Java 8 file Watcher looking for a file to be dropped for ingest. My plan is to use that file to ingest json serialized commands.
My main application uses SpringMVC restul endpoints, each declaring an @Transaction boundary.

I create the new file watcher in a thread managed by a ThreadPoolTaskExecutor.
The watcher wakes up when the file appears, reads it, deserializes commands OK, and then I send a command at a time into the CommandGateway autowired into my watcher thread.

The command goes into the command bus - fine.
The events get fired etc - all fine.

Until it gets to the JPA event store, and I get an exception :

javax.persistence.TransactionRequiredException : No transactional EntityManager available
org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:275)
etc
etc

Any ideas?

I’m interested too - I hit the same issue but didn’t delve into it. Switched over to the file system event store to test other stuff and planned to come back to this later.

How exactly have you configured your command bus? I have fought the framework for a long time until I realized that I simply misconfigured the command bus. Right now I’m using the xml support for axon even though I’m using JavaConfig for the rest of the application. So now it is configured like this:

<axon:command-bus id=“commandBus” transaction-manager=“transactionManager” />
Along with @EnableTransactionManagement on my Configuration.

Hmmm. I think my config must be off kilter.

I have worked around my initial problem by making my Watcher invoke a restful endpoint on my app with the file name to ingest as a request param, so it is the @Controller making the calls to insert commands into the bus now and Axon is happy.

But .. I am not seeing transaction management working with my app - an insert failure in a batch of these ingested commands does not force a rollback as I had hoped.

I have @EnableTransactionManagment on my main application config class, with @Transactional on my @Controller methods. I was expecting all work kicked off from the Controller to form one transaction, but an insert failure as mentioned does not force rollback.

Could you post details regarding your JPA Axon config please Paul - I would like to see how you have wired up the datasource, entity manager and transaction manager specifically?

Regards

Phil

Hello Phil,

I’m still using the automatically configured Transaction Manager along with the following entityManagerFactory:

@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory(DataSource dataSource) {
LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
em.setDataSource(dataSource);
em.setPackagesToScan(“org.axonframework.eventstore.jpa”, “org.axonframework.saga.repository.jpa”);

JpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
em.setJpaVendorAdapter(vendorAdapter);

final Properties jpaProps = new Properties();
jpaProps.setProperty(“hibernate.hbm2ddl.auto”, “create-drop”);
em.setJpaProperties(jpaProps);

return em;
}

This works fine with the automatically configured datasource (when you have H2 in your classpath).

But as I said the key to my problem was passing the automatically configured transaction manager to the commandbus.

Most likely, the automatically configured transaction manager has a well defined name. My lucky shot: “transactionManager” or “txManager”.
If you use JavaConfig to configure the command bus, you can add a PlatformTransactionManager as a parameter to the bean definition method. Spring will autowire it.

Cheers,

Allard