SqlMapTransactionManager.setUserConnection(null) does not completely restore 
previous transaction state
-------------------------------------------------------------------------------------------------------

         Key: IBATIS-259
         URL: http://issues.apache.org/jira/browse/IBATIS-259
     Project: iBatis for Java
        Type: Bug
  Components: SQL Maps  
    Versions: 2.1.5, 2.1.6, 2.1.7    
    Reporter: Paul Wilton


SqlMapTransactionManager.setUserConnection(null) does not completely restore 
previous transaction state:


// 0) ... transaction manager setup as below

    <transactionManager type="JDBC">
        <dataSource type="JNDI">
            <property name="DBInitialContext" value="java:comp/env"/>
            <property name="DBLookup" value="/jdbc/dbname"/>
        </dataSource>
    </transactionManager>


PSEUDO CODE DEMONSTRATING PROBLEM AS FOLLOWS:

// 1) ... start transaction using DaoManager
        DaoManager.startTransaction()
        // perform some query using this transaction:
          getSqlMapExecutor().queryForList(statementName, parameterObject);

// 2) ... perform some query with userConnection:       

        SqlMapExecutor executor = getSqlMapExecutor();
        SqlMapTransactionManager tm = getSqlMapTransactionManager();
        Connection userConn = null;

        try {
            // get a new connection from pool and set it to autocommit mode 
true for this query
            userConn = tm.getDataSource().getConnection();

            tm.setUserConnection(userConn);
            // execute the query
            list = executor.queryForList(statementName, parameterObject);

        } catch (SQLException e) {
            // do something

        } finally {
            try {
                // close the user connection
                if (userConn!=null)
                    userConn.close();

                // set the user connection back to null, so any transaction on 
the other connection can be continued
                tm.setUserConnection(null);   // THIS SHOULD RESTORE THE 
ORGINAL TRANSACTION STATE

            } catch (SQLException e) {      
                // do something
            }
        }


// 3) ... perform another query using orginal transaction:

          getSqlMapExecutor().queryForList(statementName, parameterObject);

        // THIS FAILS -  stacktracing with null pointer exception as follows:
        java.lang.NullPointerException
        at 
com.ibatis.sqlmap.engine.impl.SqlMapExecutorDelegate.autoEndTransaction(SqlMapExecutorDelegate.java:860)
        at 
com.ibatis.sqlmap.engine.impl.SqlMapExecutorDelegate.queryForList(SqlMapExecutorDelegate.java:617)
        at 
com.ibatis.sqlmap.engine.impl.SqlMapExecutorDelegate.queryForList(SqlMapExecutorDelegate.java:584)
        at 
com.ibatis.sqlmap.engine.impl.SqlMapSessionImpl.queryForList(SqlMapSessionImpl.java:101)
        at 
com.ibatis.sqlmap.engine.impl.SqlMapClientImpl.queryForList(SqlMapClientImpl.java:78)
        at 
nz.govt.nzqa.web.persistence.ibatis.sqlmap.BaseDaoImpl.executeQueryForList(BaseDaoImpl.java:63)


// 4) .. end original transaction using DaoManager - commit or rollback 
        DaoMoanager.commitTransaction();
        DaoMoanager.endTransaction();

        // This never executes due to previous failure

------------------
This failure appears to be caused by 
SqlMapTransactionManager.setUserConnection(null) failing to restore the 
original transaction state. 
In the following methods of class SqlMapExecutorDelegate, pushSession(session) 
resets the session thus setting the transaction manager for the session to 
NULL. Consequently when step 3 (above) is executed ibatis stack traces.

  public void setUserProvidedTransaction(SessionScope session, Connection 
userConnection) {
    if (session.getTransactionState() == TransactionState.STATE_USER_PROVIDED) {
      session.recallTransactionState();
    }
    if (userConnection != null) {
      Connection conn = userConnection;
      session.saveTransactionState();
      session.setTransaction(new UserProvidedTransaction(conn));
      session.setTransactionState(TransactionState.STATE_USER_PROVIDED);
    } else {
      session.setTransaction(null);
      pushSession(session);
    }
  }

  protected void pushSession(SessionScope session) {
    session.reset();
    sessionPool.push(session);
  }


EXPECTED OPERATION:
What I expect to happen when setUserConnection(null) is called is that the 
original transaction (and thus connection) is restored in its entirety so that 
subsequent queries can be made, and the transaction can be commited (or rolled 
back) as a unit - with the query made on the user connection outside of this 
transaction scope.


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

Reply via email to