spring-projects / spring-projects/spring-framework
No well-defined advice order for @Transactional and @Async in AspectJ mode
Nobody has claimed this yet.
- Dominant language
- Java
- Stars
- 60.2k
- Forks
- 38.8k
- Avg merge
- 5d 2h
- Merged PRs (30d)
- 27
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))
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the linked async transaction demo and run mvn clean test to reproduce the missing transaction in Spring 5 with AdviceMode.ASPECTJ. Compare the Spring 4 and Spring 5 AJC advice-order output in the issue, then inspect the relevant spring-aspects transaction and async aspects. Done means the advice order is well-defined and the reported @Async method has the expected active transaction.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- java, spring
- Domain
- backend
- Issue type
- Bug
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Needs clarification
- Newbie friendliness
- 35/100