Description
Steve Storey opened SPR-13089 and commented
Requires Hibernate 4, Spring 4, JDBC DataSourceTransactionManager:
H4 SpringSessionSynchronization#beforeCompletion doesn't put a try/finally around the session operations (in particular session.disconnect() ), and leaves the
TransactionSynchronizationManager.unbindResource(this.sessionFactory);
call until after the disconnect. If the disconnect throws a SQLException (as can happen if a org.springframework.jdbc.datasource.DataSourceTransactionManager is in place), then the TSM's thread local is left with a closed Session, from which the org.springframework.orm.hibernate4.SpringSessionContext will never recover.
H3 support didn't have the same problem because:
- the SpringSessionSynchronization would only call disconnect (or anything) before deregistering from the TSM if a JTA transaction was in progress
- Even if there were such a problem, the H3 SessionHolder used getValidatedSession to ensure it was valid (returning null it not) and the H3 SessionFactoryUtils#doGetSession would deal with the possibility that the SessionHolder would return null and automatically open a new Session.
Suggested fix is to put a try/finally in the beforeCompletion() method (not sure whether or not the SpringSessionContext should check Session.isOpen() before returning since it should never really be in that state?)
The attached test case can be run with "mvn test". It can trivially be fixed by using the HibernateTransactionManager instead, or by not throwing the exception during the close() method. We discovered this having upgraded our code to H4, and having a SQL Server reboot on us at which point the threads that had open connections all broke until the app server was restarted.
Affects: 4.1.6
Attachments:
- spring-hibernate-disconnect-bug.tar.gz (4.22 kB)
Issue Links:
- Hibernate4 version of SpringSessionContext.currentSession() does not create a session if TransactionSynchronizationManager does not contain one [SPR-9020] #13659 Hibernate4 version of SpringSessionContext.currentSession() does not create a session if TransactionSynchronizationManager does not contain one
Activity
spring-projects-issues commentedon Jun 1, 2015
Juergen Hoeller commented
Good point! We're unbinding in a finally block there now, just like we do in afterCompletion already.
Juergen