Closing EntityManager with an active transaction causes JTA connection leak
Description
Due to the way Spring transaction management works with Hibernate's EntityManager impementation (now the same as the Session implementation), in a JTA transaction the entity manager is lazily initialized (see org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler). When the JTA EntityManager is created, the necessary information is bound to the thread (see org.springframework.orm.jpa.EntityManagerFactoryUtils) including a synchronization that causes the EntityManager to be closed before transaction completion. Hibernate has code that delays the actual EntityManager/Session closure until after transaction completes, in order to allow the persistent context to commit successfully.
This code, however, marks the Session as closed. For this reason, when actual closure is attempted after transaction completes, the code that closes/releases the DB connection is not invoked because it sees the session already closed. As such, the connection does not return to the pool but remains idle. It's unclear to me whether extrernal factors (e.g. idle timeouts) would force a connection back to the pool.
Repeated JTA transactions will cause easily connection pool exhaustion.
The attached Eclipse project showcases this behavior and should help in reproducing/diagnosing the issue. Just launch the com.main.ServiceLocator's main function as Java application in Eclipse and watch the console. All the dependent libraries and their version are listed in the project pom file, the relevant libraries used are mentioned in this issue's environment field. Note: the code is a stripped down version from the real project where I've identified the problem and hasn't been cleaned up/simplified very well.
Attachments
1
Activity
Show:
Former userSeptember 26, 2016 at 7:41 PM
I've confirmed that this does not affect 5.1 or 5.0.
Vlad MihalceaSeptember 19, 2016 at 3:12 PM
Applied PR upstream. , this issue might affect 5.1 and 5.0 as well.
Due to the way Spring transaction management works with Hibernate's EntityManager impementation (now the same as the Session implementation), in a JTA transaction the entity manager is lazily initialized (see
org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler
). When the JTAEntityManager
is created, the necessary information is bound to the thread (seeorg.springframework.orm.jpa.EntityManagerFactoryUtils
) including a synchronization that causes the EntityManager to be closed before transaction completion. Hibernate has code that delays the actual EntityManager/Session closure until after transaction completes, in order to allow the persistent context to commit successfully.This code, however, marks the Session as closed. For this reason, when actual closure is attempted after transaction completes, the code that closes/releases the DB connection is not invoked because it sees the session already closed. As such, the connection does not return to the pool but remains idle. It's unclear to me whether extrernal factors (e.g. idle timeouts) would force a connection back to the pool.
Repeated JTA transactions will cause easily connection pool exhaustion.
The attached Eclipse project showcases this behavior and should help in reproducing/diagnosing the issue. Just launch the
com.main.ServiceLocator
's main function as Java application in Eclipse and watch the console.All the dependent libraries and their version are listed in the project pom file, the relevant libraries used are mentioned in this issue's environment field.
Note: the code is a stripped down version from the real project where I've identified the problem and hasn't been cleaned up/simplified very well.