Description
Affects: 5.x.x
Since Spring 5 (spring-aspects 5.x.x), it looks like @Transactional
is ignored on the method with @Async
when using AdviceMode.ASPECTJ
for both @EnableTransactionManagement
and @EnableAsync
.
Please take a look on following demo: https://github.com/kklepacz/spring-async-transaction-demo
After running mvn clean test
you should see following output:
2020-01-07 12:02:50.729 INFO 29454 --- [ async-thread-1] c.e.asynctransactiondemo.AsyncListener : Transaction in async listener? false
So even if @Transactional
annotation is present on handle
method, transaction is not active.
Now, let's change Spring version. Update pom to use Spring 4 + Spring Boot 1.5.x
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.22.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
Run mvn clean test
again. Output:
2020-01-07 12:06:38.082 DEBUG 29675 --- [ async-thread-1] o.s.orm.jpa.JpaTransactionManager : Creating new transaction with name [com.example.asynctransactiondemo.AsyncListener.handle]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT
2020-01-07 12:06:38.082 DEBUG 29675 --- [ async-thread-1] o.s.orm.jpa.JpaTransactionManager : Opened new EntityManager [org.hibernate.jpa.internal.EntityManagerImpl@3bcd99f8] for JPA transaction
2020-01-07 12:06:38.083 DEBUG 29675 --- [ async-thread-1] o.s.orm.jpa.JpaTransactionManager : Exposing JPA transaction as JDBC transaction [org.springframework.orm.jpa.vendor.HibernateJpaDialect$HibernateConnectionHandle@350a70f1]
2020-01-07 12:06:38.083 INFO 29675 --- [ async-thread-1] c.e.asynctransactiondemo.AsyncListener : Transaction in async listener? true
2020-01-07 12:06:38.085 DEBUG 29675 --- [ async-thread-1] o.s.orm.jpa.JpaTransactionManager : Initiating transaction commit
2020-01-07 12:06:38.085 DEBUG 29675 --- [ async-thread-1] o.s.orm.jpa.JpaTransactionManager : Committing JPA transaction on EntityManager [org.hibernate.jpa.internal.EntityManagerImpl@3bcd99f8]
2020-01-07 12:06:38.085 DEBUG 29675 --- [ async-thread-1] o.s.orm.jpa.JpaTransactionManager : Closing JPA EntityManager [org.hibernate.jpa.internal.EntityManagerImpl@3bcd99f8] after transaction
Transaction is active.
Is it a bug or a feature and I need some extra configuration to have my Spring Boot 2 version working as expected?
Is it related to AJC compilation anyhow? I can see a difference between an order of compilation in maven output.
For Spring Aspects 5.x:
[INFO] Showing AJC message detail for messages of types: [error, warning, fail]
[INFO] Join point 'method-execution(void com.example.asynctransactiondemo.AsyncListener.handle(com.example.asynctransactiondemo.SomeEntitySaved))' in Type 'com.example.asynctransactiondemo.AsyncListener' (AsyncListener.java:19) advised by around advice from 'org.springframework.scheduling.aspectj.AnnotationAsyncExecutionAspect' (spring-aspects-5.1.9.RELEASE.jar!AbstractAsyncExecutionAspect.class:65(from AbstractAsyncExecutionAspect.aj))
[INFO] Join point 'method-execution(void com.example.asynctransactiondemo.AsyncListener.handle(com.example.asynctransactiondemo.SomeEntitySaved))' in Type 'com.example.asynctransactiondemo.AsyncListener' (AsyncListener.java:19) advised by around advice from 'org.springframework.transaction.aspectj.AnnotationTransactionAspect' (spring-aspects-5.1.9.RELEASE.jar!AbstractTransactionAspect.class:66(from AbstractTransactionAspect.aj))
For Spring Aspects 4.x - order is different:
[INFO] Showing AJC message detail for messages of types: [error, warning, fail]
[INFO] Join point 'method-execution(void com.example.asynctransactiondemo.AsyncListener.handle(com.example.asynctransactiondemo.SomeEntitySaved))' in Type 'com.example.asynctransactiondemo.AsyncListener' (AsyncListener.java:19) advised by around advice from 'org.springframework.transaction.aspectj.AnnotationTransactionAspect' (spring-aspects-4.3.25.RELEASE.jar!AbstractTransactionAspect.class:66(from AbstractTransactionAspect.aj))
[INFO] Join point 'method-execution(void com.example.asynctransactiondemo.AsyncListener.handle(com.example.asynctransactiondemo.SomeEntitySaved))' in Type 'com.example.asynctransactiondemo.AsyncListener' (AsyncListener.java:19) advised by around advice from 'org.springframework.scheduling.aspectj.AnnotationAsyncExecutionAspect' (spring-aspects-4.3.25.RELEASE.jar!AbstractAsyncExecutionAspect.class:65(from AbstractAsyncExecutionAspect.aj))