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

SQLException.getSQLState() and getCause() are null with XADatasource connection for postgresql during network failure

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Done
    • Icon: Major Major
    • None
    • None
    • JDBC
    • None
    • Hide

      reproducer.zip attached.

      1. start-up postgreSQL
      2. start-up EAP and deploy reproducer. A XA connection need to be created by prefill. (it need to create an connection before execute statement.)
      3. shut down postgreSQL. then the pooled connection was staled.
      4. invoke servlet as reproducer (SelectXAServlet, SelectServlet), the reproducer will do getConnection and statement.execute.

      /selectxa -> using xa connection. SQLException#getSQLState() will be null.
      /select -> using non-xa conneciton. SQLException#getSQLState() will be not-null such as 08006.

      Those results would be out to System.out.

      If setting valid-on-match, the application needs to sleep between getConnection and statement.execute.
      While the application sleeping, shutting down the postgreSQL instance.
      You can see the same issue with the step.
      The reproducer includes the servlets with sleep (SleepServlet, SleepXAServlet).

      Show
      reproducer.zip attached. 1. start-up postgreSQL 2. start-up EAP and deploy reproducer. A XA connection need to be created by prefill. (it need to create an connection before execute statement.) 3. shut down postgreSQL. then the pooled connection was staled. 4. invoke servlet as reproducer (SelectXAServlet, SelectServlet), the reproducer will do getConnection and statement.execute. /selectxa -> using xa connection. SQLException#getSQLState() will be null. /select -> using non-xa conneciton. SQLException#getSQLState() will be not-null such as 08006. Those results would be out to System.out. If setting valid-on-match, the application needs to sleep between getConnection and statement.execute. While the application sleeping, shutting down the postgreSQL instance. You can see the same issue with the step. The reproducer includes the servlets with sleep (SleepServlet, SleepXAServlet).
    • Hide

      none

      Show
      none

      When using staled connection of xa datasource, the connection throws SQLException.
      Then SQLException.getSQLState() and getCause() returns null if using XA datasource.

      The SQLException is re-created in the following stack.

      #####: java.sql.SQLException: Error
      	at org.jboss.jca.adapters.jdbc.WrappedConnection.checkException(WrappedConnection.java:2033)
      	at org.jboss.jca.adapters.jdbc.WrappedStatement.checkException(WrappedStatement.java:1436)
      	at org.jboss.jca.adapters.jdbc.WrappedPreparedStatement.executeQuery(WrappedPreparedStatement.java:509)
      	at com.example.SelectXaServlet.doGet(SelectXaServlet.java:41)
      
      • adapters/src/main/java/org/jboss/jca/adapters/jdbc/WrappedConnection.java
           protected SQLException checkException(Throwable t) throws SQLException
           {
              Throwable result = null;
              if (t instanceof AbstractMethodError)
              {
                 t = new SQLFeatureNotSupportedException(bundle.methodNotImplemented(), t);
              }
        
              if (mc != null)
                 result = mc.connectionError(t);
        
              if (result instanceof SQLException)
              {
                 throw (SQLException) result;
              }
              else
              {
                 throw new SQLException("Error", result); // If the managed connection is null, create a new SQLException.
              }
        
           }
        

      In the above, the managed connection is null.
      This is because that the ConnectionEventListener#connectionErrorOccurred() fired by the Postgresql driver.
      (oracle driver doesn't fire the event during executing statement, so this issue doen't occur.)

      	at org.jboss.jca.adapters.jdbc.WrappedConnection.setManagedConnection(WrappedConnection.java:120) // null set
      	at org.jboss.jca.adapters.jdbc.BaseWrapperManagedConnection.cleanup(BaseWrapperManagedConnection.java:339)
      	- locked <0x00000000f9ea3560> (a java.util.HashSet)
      	at org.jboss.jca.core.connectionmanager.pool.mcp.SemaphoreConcurrentLinkedDequeManagedConnectionPool.returnConnection(SemaphoreConcurrentLinkedDequeManagedConnectionPool.java:666)
      	at org.jboss.jca.core.connectionmanager.pool.mcp.SemaphoreConcurrentLinkedDequeManagedConnectionPool.returnConnection(SemaphoreConcurrentLinkedDequeManagedConnectionPool.java:611)
      	at org.jboss.jca.core.connectionmanager.pool.AbstractPool.returnConnection(AbstractPool.java:847)
      	at org.jboss.jca.core.connectionmanager.AbstractConnectionManager.returnManagedConnection(AbstractConnectionManager.java:725)
      	at org.jboss.jca.core.connectionmanager.listener.AbstractConnectionListener.connectionErrorOccurred(AbstractConnectionListener.java:472)
      	at org.jboss.jca.adapters.jdbc.BaseWrapperManagedConnection.broadcastConnectionError(BaseWrapperManagedConnection.java:673)
      	at org.jboss.jca.adapters.jdbc.xa.XAManagedConnection.broadcastConnectionError(XAManagedConnection.java:203)
      	at org.jboss.jca.adapters.jdbc.xa.XAManagedConnection$1.connectionErrorOccurred(XAManagedConnection.java:91)
      	at org.postgresql.ds.PGPooledConnection.fireConnectionFatalError(PGPooledConnection.java:183)
      	at org.postgresql.ds.PGPooledConnection.fireConnectionError(PGPooledConnection.java:237)
      	at org.postgresql.ds.PGPooledConnection.access$200(PGPooledConnection.java:38)
      	at org.postgresql.ds.PGPooledConnection$StatementHandler.invoke(PGPooledConnection.java:428)
      	at com.sun.proxy.$Proxy64.executeQuery(Unknown Source)
      	at org.jboss.jca.adapters.jdbc.WrappedPreparedStatement.executeQuery(WrappedPreparedStatement.java:504)
      	at com.example.SelectXaServlet.doGet(SelectXaServlet.java:41)
      

      adapters/src/main/java/org/jboss/jca/adapters/jdbc/xa/XAManagedConnection.java

         public XAManagedConnection(XAManagedConnectionFactory mcf, XAConnection xaConnection, Properties props,
                                    int transactionIsolation, int psCacheSize) throws SQLException
         {
            super(mcf, xaConnection.getConnection(), props, transactionIsolation, psCacheSize);
      
            this.xaConnection = xaConnection;
            xaConnection.addConnectionEventListener(new javax.sql.ConnectionEventListener()
            {
               ...<snip>
      
               public void connectionErrorOccurred(javax.sql.ConnectionEvent ce)
               {
                  SQLException ex = ce.getSQLException();
                  broadcastConnectionError(ex);          // cleanup and return this connection when this event fired.
               }
            });
      

              istudens@redhat.com Ivo Studensky
              istudens@redhat.com Ivo Studensky
              Votes:
              0 Vote for this issue
              Watchers:
              1 Start watching this issue

                Created:
                Updated:
                Resolved: