Javarevisited
Published in

Javarevisited

Scheduling methods to execute post transaction commit using Spring TransactionSynchronization

The annotation we all needed

The Problem

When using transactions in spring, often it is needed for some specific methods to run post the transaction is successfully committed, let's understand this with an example:-

Assume there are two microservices in a system, first one manages user lifecycle, let's call it User Management Service (UMS) and the other one prepares feed for the User (Feed Service).

UMS & Feed Service Interaction

When a New User signs up on the platform UMS does some validation and then pushes a message to create_feed Kafka topic. The feed service on the other hand listens to messages on create_feed topic and then calls UMS to get the interests of the user to prepare the feed. Do you see a huge problem in this flow!? What if any of the subsequent methods during sign up fail — the user details were never be saved in the system and the Feed service get user interest call will start failing. This issue gets amplified when are talking about multiple microservice interactions.

There could be many other requirements where it is needed for some specific methods to only execute post transaction commit, lets see how this can be solved elegantly!

The Solution 🚀

To execute a block of code after transaction commit afterCommit method of TransactionSynchronizationAdapter can be used, which should be something like this

While this works it requires one to add a lot of boilerplate code everywhere one use it and is simply not a very clean way of solving the problem.

Let's look at how to create an annotation (@PostCommit) and use spring AOP around advice to drive all this from the background. The idea is whenever a method with @PostCommit annotation on it is encountered the execution is wrapped inside a runnable and added for execution in a ThreadLocal, when the transaction is complete afterCommit of TransactionSynchronizationAdapter will be called and all the runables of ThreadLocal can be executed.

#1 Building the Annotation

This part is straightforward and similar to creating any other annotation in Java

#2 Building the PostCommitAdapter

The PostCommitAdapter will serve two functions

  1. It will register runnables on a ThreadLocal
  2. Override AfterCommit of TransactionSynchronizationAdapter to run all registered runnables on transaction commit

If the transaction is active the execute method registers runnables in ThreadLocal otherwise, it simply goes ahead and executes it. The afterCommit runs all the runnables that is inside the ThreadLocal

#3 Connecting the Adapter & Annotation using around advice

To hook the execute method of PostCommitAdapter with @PostCommit annotation, an around advice is created on @PostCommit annotation which at every join point encapsulates the method execution inside the runnable and calls execute of PostCommitAdapter

Usage

Once the boilerplate is written, the usage is as simple as it can get, whichever method is supposed to be executed post transaction commit one has to simply annotate it with PostCommit annotation.

Example: Consider two classes A & B having PostCommit annotated method

and a driver class which are calling these methods:

the expected output will be:

Conclusion

This blog tries to explain how we can leverage Spring’s TransactionSynchronization to execute a block of code after a transaction commit and how it can be hooked to a custom annotation using Spring AOP to drive everything from behind.

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store