Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Transaction synchronization in Spring Boot

I have a small Spring Boot application with spring-boot-starter-web, spring-boot-starter-data-jpa, and postgresql as dependencies.

I'm able to use the @Transactional annotation and use JPA to fetch and save entities to the database. However, if I were to add afterCommit/afterCompletion hooks via registering a synchronization, it gives an IllegalStateException saying that Transaction synchronization is not active.

TransactionSynchronizationManager.registerSynchronization(
     new TransactionSynchronizationAdapter() {
        @Override
        public void afterCommit() {
            //this doesn't get called
            log.info("do something here");
        }
    });

Doing TransactionSynchronizationManager.initSynchronization(); gets rid of the error, but the hooks don't get called (eg: the afterCommit hook doesn't get called even though the transaction has committed.)

Any clues on how to debug this?

like image 457
Pradyumna Avatar asked Feb 23 '18 15:02

Pradyumna


People also ask

What is transaction synchronization Spring?

Spring provides support for synchronizing resources with transactions since the earliest versions. We often use it to synchronize transactions managed by multiple transaction managers. For example, we can synchronize a JMS commit with a JDBC commit.

Why do we use @transactional in Spring boot?

The @Transactional annotation is the metadata that specifies the semantics of the transactions on a method. We have two ways to rollback a transaction: declarative and programmatic. In the declarative approach, we annotate the methods with the @Transactional annotation.

What is @transactional in Spring boot?

The @Transactional annotation is metadata that specifies that an interface, class, or method must have transactional semantics; for example, "start a brand new read-only transaction when this method is invoked, suspending any existing transaction".

How is transaction maintained in Spring boot?

Spring Boot implicitly creates a proxy for the transaction annotated methods. So for such methods the proxy acts like a wrapper which takes care of creating a transaction at the beginning of the method call and committing the transaction after the method is executed.


1 Answers

It turned out that I had forgotten to include the build plugin that is used to create the AoP-proxies for beans having @Transactional annotations.

In the absence of this plugin, no proxies would get generated, and the code would run non-transactionally; except for when it enters the JpaRepository methods where it would create a short-lived transaction for the duration of the call (such as save/findAll/delete).

This is the plugin that I missed including in my pom.xml (this got generated in the pom output by the spring initializr (https://start.spring.io/) but I didn't notice it at first and didn't copy it over into my pom)

<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
        </plugin>
    </plugins>
</build>
like image 185
Pradyumna Avatar answered Oct 22 '22 21:10

Pradyumna