Transaction management in a reactive context

Hello guys,

We are facing an issue right now in our system that I would like to share here and get some feedback on.

We are using Axon 3.4 and as part of handling events in our services, we are making a call to an external service through HTTP using a non-blocking reactive client (org.springframework.web.reactive.function.client.WebClient) to perform such HTTP requests.

Simplifying it a lot, the code of the event processing looks like:

@EventHanlder
fun handle(e: Event) {
val entity = createEntity()
jpaRepo.save(entity)
client.post()
.publishOn(scheduler)
.doOnSuccess {
entity.someField = “changingIt”
jpaRepo.save(entity)
}
}

So, as you can see, we are saving an entity in our database, and then in a different thread, on the onSuccess block, we are updating the entity. What we are finding is that from time to time, the transaction that performed the initial save was not committed at the time of the execution of the onSuccess block, so the second save will not update the transaction (desired outcome), but save a second one (causing unexpected issues in the platform). As far as I understand, the only transaction manager Axon allows me to use is the SpringTransactionManager which only accepts a PlatformTransactionManager which keeps the transaction state in the ThreadLocal, which will not work with such reactive http client causing, at times, this issue.

Does Axon provide support for this kind of situation? Should we get rid of the reactive http clien maybe?

Any help or ideas would be appreciated!

Thanks,
Armando

Hi Armando,

Axon’s approach of finalizing a transaction is done through it’s TransactionManager, which is provided to the Unit of Work to correctly flow through the desired [prepare commit | commit | after commit | rollback | clean up] phases.
What Axon guarantees you, is that you do not have to programmatically define a transaction (like for example with the @Transactional annotation), as every message in the framework is dealt with through such a Unit of Work.
Having said that, you are right that Axon out of the box provides you the SpringTransactionManager, next to the plain interface (for you to implement) and the NoTransactionManager.

Due to this implementation I would indeed expect the Unit of Work to end once event handling is finalized, not taking into account Reactor’s Context notion (which replaces the ThreadLocal).
Finding a different solution would indeed be more reasonable at this point of time.
Note though that we have recently (this week) released the Axon Reactor Extension.
It doesn’t give you the solution you need right now, but it will, very likely, eventually.

Using the extension does require you to upgrade to a more recent version of Axon.
Version 3.4 is, to be honest, darned old already at the moment.
I would thus highly recommend to move over to the current version, which is 4.4.2.

Trusting this clarifies things for you Armando! Ow, and please note that the mailing list will be discontinued as specified in this thread.
Instead of this mailing list we have moved over to use a forum style of communication, findable at https://discuss.axoniq.io/.

Cheers,
Steven

Thank you so much for your reply Steven. We will consider migrating our system to the latest Axon version when we have time. In the meantime, we have been able to solve this with Spring’s TransactionSynchronizationManager.

As for this mailing list being discontinued, thank you very much for the heads up, I was not aware and will bookmark https://discuss.axoniq.io/ now.

Thanks and have a nice day!