Uploaded image for project: 'IronJacamar'
  1. IronJacamar
  2. JBJCA-1396

dataSource.getConnection() returns broken connection after XAResource#commit() failed in the same thread

    XMLWordPrintable

Details

    • Bug
    • Resolution: Done
    • Major
    • None
    • WildFly/IronJacamar 1.4.2.Final
    • JDBC
    • None
    • Hide

      reproducer.zip attached. please check readme.txt.

      Show
      reproducer.zip attached. please check readme.txt.
    • Workaround Exists
    • Hide

      ivnoke Connection#close() before Usertransaction#commit().

      Show
      ivnoke Connection#close() before Usertransaction#commit().

    Description

      When retrying Usertransaction on same thread after XAResource#commit() failed, DataSource#getConnection() returns closed connection in new Usertransaction. [1]

      [1]

      // 1st attempt.
      UserTransaction.begin();
      Connection conn = dataSource.getConnection();
      Statemnt stmt = conn.createStatement();
      stmt.executeUpdate("...");
      UserTransaction.commit(); // XAResource#commit() failure with ARJUNA016039.
      
      // retry transaction.
      UserTransaction.begin();
      Connection conn = dataSource.getConnection(); // returned same physical connection of the previous transaction.
      Statemnt stmt = conn.createStatement();       // SQLException thrown by the connection is already closed.
      

      The stacktrace [2] is as follows.

      [2]

      // 1st attempt
      WARN  [com.arjuna.ats.jta] (default task-1) ARJUNA016039: onePhaseCommit on < formatId=131077, gtrid_length=29, bqual_length=36, tx_uid=0:ffff7f000001:21fea082:5dc8ed99:f, node_name=1, branch_uid=0:ffff7f000001:21fea082:5dc8ed99:14, subordinatenodename=null, eis_name=java:jboss/datasources/ExampleDS > (LocalXAResourceImpl@6cb4daa9[connectionListener=6a0eecdd connectionManager=36f87501 warned=false currentXid=null productName=H2 productVersion=@PROJECT_VERSION@ (2016-10-31) jndiName=java:jboss/datasources/ExampleDS]) failed with exception XAException.XA_RBROLLBACK: org.jboss.jca.core.spi.transaction.local.LocalXAException: IJ001156: Could not commit local transaction
      	at org.jboss.jca.core.tx.jbossts.LocalXAResourceImpl.commit(LocalXAResourceImpl.java:182)
      	at com.arjuna.ats.internal.jta.resources.arjunacore.XAOnePhaseResource.commit(XAOnePhaseResource.java:120)
      	at com.arjuna.ats.internal.arjuna.abstractrecords.LastResourceRecord.topLevelOnePhaseCommit(LastResourceRecord.java:172)
      	at com.arjuna.ats.arjuna.coordinator.BasicAction.onePhaseCommit(BasicAction.java:2386)
      	at com.arjuna.ats.arjuna.coordinator.BasicAction.End(BasicAction.java:1497)
      	at com.arjuna.ats.arjuna.coordinator.TwoPhaseCoordinator.end(TwoPhaseCoordinator.java:96)
      	at com.arjuna.ats.arjuna.AtomicAction.commit(AtomicAction.java:162)
      	at com.arjuna.ats.internal.jta.transaction.arjunacore.TransactionImple.commitAndDisassociate(TransactionImple.java:1287)
      	at com.arjuna.ats.internal.jta.transaction.arjunacore.BaseTransaction.commit(BaseTransaction.java:126)
      	at com.arjuna.ats.jbossatx.BaseTransactionManagerDelegate.commit(BaseTransactionManagerDelegate.java:94)
      	at org.wildfly.transaction.client.LocalTransaction.commitAndDissociate(LocalTransaction.java:75)
      	at org.wildfly.transaction.client.ContextTransactionManager.commit(ContextTransactionManager.java:71)
      	at org.wildfly.transaction.client.LocalUserTransaction.commit(LocalUserTransaction.java:53)
      	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
      	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
      	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
      	at java.lang.reflect.Method.invoke(Method.java:498)
      	at org.jboss.weld.util.reflection.Reflections.invokeAndUnwrap(Reflections.java:410)
      	at org.jboss.weld.bean.builtin.CallableMethodHandler.invoke(CallableMethodHandler.java:42)
      	at org.jboss.weld.bean.proxy.EnterpriseTargetBeanInstance.invoke(EnterpriseTargetBeanInstance.java:56)
      	at org.jboss.weld.bean.proxy.ProxyMethodHandler.invoke(ProxyMethodHandler.java:106)
      	at org.jboss.weldx.transaction.UserTransaction$$Proxy$_$$_Weld$Proxy$.commit(Unknown Source)
      	at com.example.HelloServlet.doGet(HelloServlet.java:65)
      	at javax.servlet.http.HttpServlet.service(HttpServlet.java:686)
          ...
      
      // 2nd attempt 
      ERROR [stderr] (default task-1) org.h2.jdbc.JdbcSQLException: The object is already closed [90007-193]
      ERROR [stderr] (default task-1) 	at org.h2.message.DbException.getJdbcSQLException(DbException.java:345)
      ERROR [stderr] (default task-1) 	at org.h2.message.DbException.get(DbException.java:179)
      ERROR [stderr] (default task-1) 	at org.h2.message.DbException.get(DbException.java:155)
      ERROR [stderr] (default task-1) 	at org.h2.message.DbException.get(DbException.java:144)
      ERROR [stderr] (default task-1) 	at org.h2.jdbc.JdbcConnection.checkClosed(JdbcConnection.java:1480)
      ERROR [stderr] (default task-1) 	at org.h2.jdbc.JdbcConnection.checkClosed(JdbcConnection.java:1458)
      ERROR [stderr] (default task-1) 	at org.h2.jdbc.JdbcConnection.createStatement(JdbcConnection.java:202)
      ERROR [stderr] (default task-1) 	at org.jboss.jca.adapters.jdbc.WrappedConnection$1.produce(WrappedConnection.java:357)
      ERROR [stderr] (default task-1) 	at org.jboss.jca.adapters.jdbc.WrappedConnection$1.produce(WrappedConnection.java:355)
      ERROR [stderr] (default task-1) 	at org.jboss.jca.adapters.jdbc.SecurityActions.executeInTccl(SecurityActions.java:97)
      ERROR [stderr] (default task-1) 	at org.jboss.jca.adapters.jdbc.WrappedConnection.createStatement(WrappedConnection.java:355)
      ERROR [stderr] (default task-1) 	at com.example.HelloServlet.doGet(HelloServlet.java:59)
      ...
      

      The following document [3] indicates the XAResource#commit() with onePhase=true has possibility to close the connection when the commit fails. So the connection closing seems to be correct.

      [3]

          "If the resource manager did not commit the transaction and the paramether onePhase is set to true, the resource manager may throw one of the XA_RB* exceptions. 
          Upon return, the resource manager has rolled back the branch's work and has released all held resources."
          https://docs.oracle.com/javase/8/docs/api/javax/transaction/xa/XAResource.html#commit-javax.transaction.xa.Xid-boolean-
      

      And if java.sql.Connection#close() is called before Usertransaction#commit() on 1st attempt, DataSource returns a valid/useful connection on 2nd Usertransaction. [4]
      But it seems to be difficult to know for user why getConnection() returns closed connection when the above issue occurred.

      [4]

      // 1st attempt.
      UserTransaction.begin();
      Connection conn = dataSource.getConnection();
      Statemnt stmt = conn.createStatement();
      stmt.executeUpdate("...");
      conn.close(); // connection close is called before commit.
      UserTransaction.commit(); // XAResource#commit() failure with ARJUNA016039.
      
      // retry transaction.
      UserTransaction.begin();
      Connection conn = dataSource.getConnection(); // valid connection will be returned.
      

      Attachments

        Issue Links

          Activity

            People

              thofman Tomas Hofman
              thofman Tomas Hofman
              Votes:
              0 Vote for this issue
              Watchers:
              1 Start watching this issue

              Dates

                Created:
                Updated:
                Resolved: