We observed an unexpected behavior when using nested @TransactionalEventListeners together with Propagation.REQUIRES_NEW.
Environment
- Spring Boot: 3.5.14
- Spring Framework: 6.2.19
- Hibernate ORM: 6.6.53.Final
- HikariCP
- JpaTransactionManager
- Java 21
Scenario
The application has the following event flow:
@Transactional
└── publish(Event1)
└── @TransactionalEventListener(AFTER_COMMIT)
├── @Transactional(REQUIRES_NEW)
│ └── publish(Event2)
└── transaction commits
└── @TransactionalEventListener(BEFORE_COMMIT)
└── @Transactional(REQUIRES_NEW)
The project attached below is a minimal reproducer.
Repository:
https://github.com/aytacdereli/spring-transactional-event-bug
Expected behavior
Every REQUIRES_NEW transaction should complete normally and release its JDBC connection back to HikariCP after commit.
Actual behavior
Occasionally one of the JDBC connections remains checked out after the transaction has completed.
After several executions, Hikari's active connection count increases and eventually the pool becomes exhausted.
No exception is thrown.
Additional observations
- Removing the intermediate
@TransactionalEventListener completely eliminates the issue.
- Using only a single transactional event listener does not reproduce the problem.
REQUIRES_NEW is executed in a different Spring bean (proxy is applied correctly).
- No
@Async is used for the BEFORE_COMMIT listener.
- The behavior is reproducible with the attached minimal project.
At this point I am not sure whether this is an intended limitation of nested @TransactionalEventListeners or a transaction lifecycle issue in Spring Framework.
Any guidance would be appreciated.
We observed an unexpected behavior when using nested
@TransactionalEventListeners together withPropagation.REQUIRES_NEW.Environment
Scenario
The application has the following event flow:
The project attached below is a minimal reproducer.
Repository:
https://github.com/aytacdereli/spring-transactional-event-bug
Expected behavior
Every
REQUIRES_NEWtransaction should complete normally and release its JDBC connection back to HikariCP after commit.Actual behavior
Occasionally one of the JDBC connections remains checked out after the transaction has completed.
After several executions, Hikari's active connection count increases and eventually the pool becomes exhausted.
No exception is thrown.
Additional observations
@TransactionalEventListenercompletely eliminates the issue.REQUIRES_NEWis executed in a different Spring bean (proxy is applied correctly).@Asyncis used for theBEFORE_COMMITlistener.At this point I am not sure whether this is an intended limitation of nested
@TransactionalEventListeners or a transaction lifecycle issue in Spring Framework.Any guidance would be appreciated.