[hibernate-issues] [Hibernate-JIRA] Created: (HHH-2827) RuntimeException from Connection.rollback/setAutoCommit Corrupts SessionFactory (on a per thread basis)

Mihai Danila (JIRA) noreply at atlassian.com
Wed Sep 5 19:52:14 EDT 2007


RuntimeException from Connection.rollback/setAutoCommit Corrupts SessionFactory (on a per thread basis)
-------------------------------------------------------------------------------------------------------

                 Key: HHH-2827
                 URL: http://opensource.atlassian.com/projects/hibernate/browse/HHH-2827
             Project: Hibernate3
          Issue Type: Bug
          Components: core
    Affects Versions: 3.1.3
         Environment: 3.1.3, WebLogic on Windows, DB2 JDBC Driver, DB2 UDB on Windows
            Reporter: Mihai Danila
         Attachments: HibernateClosedSessionBug.zip

When java.sql.Connection's rollback/setAutoCommit methods throw a RuntimeException, as is the case in some circumstances in WebLogic, the SessionFactory fails to correctly clean up the session.

The problem is in class org.hibernate.transaction.JDBCTransaction, lines 161-177. The block only raises afterTransactionCompletion if (a) the rollback operation within the try block succeeds or (b) the rollback operation fails with an SQLException. This is wrong, as reproduced by us in a WebLogic 8.1.3 environment, by causing a database outage at just the right time.

The net effect is that the session cleanup does not occur, and all subsequent attempts to use currentSession() on the same transaction factory from the same thread will fail miserably.

The fact that WebLogic raises a RuntimeException in case of a database outage is a WebLogic bug that we raised with them. However, according to Sun's document on Javadoc comments, (http://java.sun.com/j2se/javadoc/writingdoccomments/#throwstag) Hibernate should guard against an unchecked exception and still cleanup properly.

"Since there is no way to guarantee that a call has documented all of the unchecked exceptions that it may throw, the programmer must not depend on the presumption that a method cannot throw any unchecked exceptions other than those that it is documented to throw. In other words, you should always assume that a method can throw unchecked exceptions that are undocumented."

Attached is sample code that shows the problem. I believe the solution is to remove the fire event call from the try/catch blocks and add it into the finally block, guarding it with its own finally block, if necessary:

Instead of:
			try {
				rollbackAndResetAutoCommit();
				log.debug("rolled back JDBC Connection");
				rolledBack = true;
				afterTransactionCompletion(Status.STATUS_ROLLEDBACK);
			}
			catch (SQLException e) {
				log.error("JDBC rollback failed", e);
				afterTransactionCompletion(Status.STATUS_UNKNOWN);
				throw new TransactionException("JDBC rollback failed", e);
			}
			finally {
				if ( callback ) {
					jdbcContext.afterTransactionCompletion( false, this );
				}
				closeIfRequired();
			}

It would be:

			try {
				rollbackAndResetAutoCommit();
				log.debug("rolled back JDBC Connection");
				rolledBack = true;
			}
			catch (SQLException e) {
				log.error("JDBC rollback failed", e);
				throw new TransactionException("JDBC rollback failed", e);
			}
			finally {
				afterTransactionCompletion(rolledBack ? Status.STATUS_ROLLEDBACK : Status.STATUS_UNKNOWN);
				if ( callback ) {
					jdbcContext.afterTransactionCompletion( false, this );
				}
				closeIfRequired();
			}




-- 
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators: http://opensource.atlassian.com/projects/hibernate/secure/Administrators.jspa
-
For more information on JIRA, see: http://www.atlassian.com/software/jira

        



More information about the hibernate-issues mailing list