Why Your Spring @Transactional Doesn’t Rollback: AOP Aspect Order Conflict Explained
An in‑depth analysis of a Spring transaction failure caused by a custom AOP aspect interfering with the default TransactionInterceptor, detailing the symptom, root cause, and step‑by‑step solutions—including adjusting aspect order, rethrowing exceptions, and manual rollback—to ensure reliable transaction management.
1. Background
During a system feature development we introduced a custom AOP aspect ( MyAspect) to log business method calls, while the business layer methods used Spring’s @Transactional annotation for transaction management. After deployment, some transactions did not roll back as expected, causing data inconsistency. Investigation revealed a conflict between the custom aspect and the transaction aspect execution order; the exception handling in the custom aspect masked the rollback condition, rendering the transaction ineffective.
2. Fault Phenomenon
Problem description A business method (e.g., a transfer operation) throws an exception, but the transaction does not roll back, so partial data updates are still committed.
Reproduction steps
Simulate an exception in the business method (e.g., throw RuntimeException).
The custom aspect MyAspect catches the exception and logs it, but does not re‑throw it.
The transaction does not roll back, leading to inconsistent database state.
3. Root Cause Analysis
3.1 Core Issue: Aspect Execution Order Conflict
Spring AOP aspect priority mechanism Spring’s transaction management is implemented via AOP. The default transaction aspect ( TransactionInterceptor) has a low priority (Order = Integer.MAX_VALUE), while a custom aspect without an explicit @Order gets a higher priority based on class name ordering.
3.2 Code Example
// Custom aspect (MyAspect)
@Aspect
@Component
public class MyAspect {
@Around("execution(* transfer(..))")
public Object around(ProceedingJoinPoint pjp) throws Throwable {
try {
return pjp.proceed(); // execute target method
} catch (Throwable e) {
e.printStackTrace(); // log but do not rethrow
return null;
}
}
}
// Business service (Service3)
@Service
public class Service3 {
@Autowired
private AccountMapper accountMapper;
@Transactional(rollbackFor = Exception.class)
public void transfer(int from, int to, int amount) throws FileNotFoundException {
// simulate exception
new FileInputStream("nonexistent.txt");
}
}3.3 Problem Root
The @Around advice of MyAspect executes before the transaction aspect; swallowing the exception prevents the transaction aspect from triggering rollback.
Spring’s transaction aspect relies on exception propagation; if an upstream aspect intercepts and does not re‑throw, the transaction becomes ineffective.
4. Solution
4.1 Adjust Aspect Priority
Option 1: Lower custom aspect priority Add @Order to ensure the transaction aspect runs first:
@Aspect
@Component
@Order(Ordered.LOWEST_PRECEDENCE - 1) // lower than transaction aspect
public class MyAspect {
// ...
}Option 2: Raise transaction aspect priority If configurable, set a higher priority for the transaction advisor.
4.2 Fix Exception Handling Logic
Option 1: Re‑throw the exception in the custom aspect
@Around("execution(* transfer(..))")
public Object around(ProceedingJoinPoint pjp) throws Throwable {
try {
return pjp.proceed();
} catch (Throwable e) {
e.printStackTrace();
throw e; // re‑throw
}
}Option 2: Manually trigger rollback
@Around("execution(* transfer(..))")
public Object around(ProceedingJoinPoint pjp) throws Throwable {
TransactionStatus status = TransactionAspectSupport.currentTransactionStatus();
try {
return pjp.proceed();
} catch (Throwable e) {
status.setRollbackOnly(); // force rollback
return null;
}
}4.3 Verify Effect
After fixing, the transaction aspect correctly captures exceptions and triggers rollback, ensuring data consistency.
5. Follow‑up Measures
Code standards
Declare @Order on custom aspects to avoid default priority conflicts.
Handle exceptions in transactional methods carefully to ensure proper propagation.
Documentation update
Add a guideline “AOP Aspect Priority and Transaction Management” describing priority rules and exception handling requirements.
Team training
Conduct training on Spring AOP and transaction mechanisms to reinforce understanding of aspect ordering and transaction propagation.
Automated testing
Introduce unit tests that verify interaction between custom aspects and transaction aspects, confirming expected exception propagation and rollback behavior.
6. Summary
The root cause was a conflict between the custom aspect and the transaction aspect execution order, which invalidated the transaction. Adjusting aspect priority and correcting exception handling restored proper rollback. Future work should strengthen coding standards, documentation, training, and automated tests to prevent recurrence.
Lesson : Transaction aspects depend on exception propagation; any upstream aspect must ensure exceptions are correctly passed on, and custom aspect priorities must be coordinated with transaction aspects to avoid interference.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Cognitive Technology Team
Cognitive Technology Team regularly delivers the latest IT news, original content, programming tutorials and experience sharing, with daily perks awaiting you.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
