commons-user mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Extance, Paul" <paul.exta...@spirent.com>
Subject [pool] Possible Bug (and fix) with testOnBorrow...
Date Wed, 30 Jul 2003 00:39:08 GMT
Hello, 
 
I'm using the latest CVS build of commons-pool and commons-dbcp with Tomcat
4.1.24 and used the connection pool as a DataSource for container
authentication.
 
With this current build, if all the connections in the pool are
'invalidated' (ie the DBA kills them or restarts the database) I want
connection pool to makes sure the connection is 'valid' before returning it.
In theory this is what the 'testOnBorrow' should do for me.
 
I'm using Oracle 9i, I have the following in tomcat/server.xml
 
<Resource
    name = "dbcp/aura4d"
    auth = "Container"
    type = "javax.sql.DataSource"
/>
<ResourceParams name = "dbcp/aura4d">
     <parameter>
         <name>debug</name>
         <value>1</value>
     </parameter>
     <parameter>
         <name>factory</name>
          <value>org.apache.commons.dbcp.BasicDataSourceFactory</value>
     </parameter>
     <parameter>
         <name>username</name>
         <value>xxxx</value>
     </parameter>
     <parameter>
         <name>password</name>
         <value>xxxx</value>
     </parameter>
     <parameter>
         <name>driverClassName</name>
         <value>oracle.jdbc.driver.OracleDriver</value>
     </parameter>
     <parameter>
         <name>url</name>
         <value>jdbc:oracle:thin:@xxx:1521:xxx</value>
     </parameter>
     <parameter>
         <name>maxActive</name>
         <value>5</value>
     </parameter>
     <parameter>
         <name>maxIdle</name>
         <value>2</value>
     </parameter>
     <parameter>
         <name>maxWait</name>
         <value>100</value>
     </parameter>
     <parameter>
         <name>testOnBorrow</name>
         <value>true</value>
     </parameter>
     <parameter>
         <name>testOnReturn</name>
         <value>true</value>
     </parameter>
     <parameter>
         <name>validationQuery</name>
         <value>select 1 from dual</value>
     </parameter>
</ResourceParams>
 
 
The problem is that in
pool\src\java\org\apache\commons\pool\impl\GenericObjectPool.java an
SQLException is thrown before the testOnBorrow is reached (see below)
 
java.sql.SQLException: ORA-00028: your session has been killed
 
      at oracle.jdbc.dbaccess.DBError.throwSqlException(DBError.java:180)
      at oracle.jdbc.ttc7.TTIoer.processError(TTIoer.java:208)
      at oracle.jdbc.ttc7.Ocommoncall.receive(Ocommoncall.java:140)
      at oracle.jdbc.ttc7.TTC7Protocol.setAutoCommit(TTC7Protocol.java:441)
      at
oracle.jdbc.driver.OracleConnection.setAutoCommit(OracleConnection.java:996)
      at
org.apache.commons.dbcp.DelegatingConnection.setAutoCommit(DelegatingConnect
ion.java:243)
      at
org.apache.commons.dbcp.PoolableConnectionFactory.activateObject(PoolableCon
nectionFactory.java:271)
      at
org.apache.commons.pool.impl.GenericObjectPool.borrowObject(GenericObjectPoo
l.java:757)
      at
org.apache.commons.dbcp.PoolingDataSource.getConnection(PoolingDataSource.ja
va:108)
      at
org.apache.commons.dbcp.BasicDataSource.getConnection(BasicDataSource.java:4
03)
 
It looks like the setAutoCommit() called via the
GenericObjectPool.borrowObject() causes a 'ping' to the database before it
even gets to the _factory.validateObject() method which does the test for
the database connection.
 
I have made a local patch to GenericObjectPool.borrowObject() method
changing the following code...
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
            _factory.activateObject(pair.value);
            if(_testOnBorrow && !_factory.validateObject(pair.value)) {
                _factory.destroyObject(pair.value);
                if(newlyCreated) {
                    throw new NoSuchElementException("Could not create a
validated object");
                } // else keep looping
            } else {
                _numActive++;
                return pair.value;
            }
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
to the following 
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
            try {
                _factory.activateObject(pair.value);
                if(_testOnBorrow && !_factory.validateObject(pair.value)) {
                            // Kill off this object and keep looping
                              try {
                                  _factory.destroyObject(pair.value);
                          } catch (Exception ex) {
                                    // ignore
                          }
                    if(newlyCreated) {
                        throw new NoSuchElementException("Could not create a
validated object");
                    } // else keep looping
                } else {
                    _numActive++;
                    return pair.value;
                }
                  } catch(java.sql.SQLException e) {
                        // thrown if there is an error in activateObject
                        // Kill off this object and keep looping
                        try {
                            _factory.destroyObject(pair.value);
                      } catch (Exception ex) {
                              // ignore
                      }
                  }
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
 
This way the SQLException is caught and the bad connection is removed from
the pool, and a valid connection is still returned. Testing this under
tomcat I can restart my database while tomcat is running and the container
authentication works fine.
 
If this patch makes sense to do, can someone apply this to the CVS
repository, or is there a better patch you can apply to fix this.
 
Thanks
 
Paul Extance
 

Mime
  • Unnamed multipart/alternative (inline, None, 0 bytes)
View raw message