commons-user mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Jason Lea <ja...@kumachan.net.nz>
Subject Re: DBCP: Closed connections
Date Sat, 26 Apr 2003 00:47:53 GMT
Craig R. McClanahan wrote:
> 
> On Fri, 25 Apr 2003, Robert Egan wrote:
> 
> 
>>Date: Fri, 25 Apr 2003 14:00:30 -0400
>>From: Robert Egan <regan@ph.com>
>>Reply-To: Jakarta Commons Users List <commons-user@jakarta.apache.org>
>>To: 'Jakarta Commons Users List' <commons-user@jakarta.apache.org>
>>Subject: RE: DBCP: Closed connections
>>
>>In an effort to muddy the waters more, perhaps some clarification is in
>>order.
>>
>>If a Statement, PreparedStatement, or CallableStatement directly produces a
>>ResultSet (via SELECT) then that result set is closed when the associated
>>statement is closed.
>>
>>However, if a result set was produced another way (such as selecting into a
>>REF CURSOR) then that result set is not closed, at least in the Oracle
>>driver(s).
> 
> 
> One other important note -- although closing a Connection is supposed to
> close all the related Statements and ResultSets, that still doesn't help
> if you're using a connection pool like DBCP.  The reason for this is that
> Connection.close() simply puts the connection back into the pool -- the
> underlying connection won't actually be closed (because that would defeat
> the point of using a pool in the first place).  Therefore, any open
> statements and result sets are still open (even if the JDBC driver does
> the right thing).

Craig,

I agree with everyone about closing the ResultSets and Statements and do 
that myself.

I have just been looking at the code becuase I remember seeing that 
DelegateConnection had a method called passivate() that does close 
Statements and ResultSets.  I thought this was called when close()  was 
called on the DelegateConnection, but it's not, it is called later.

The process is as follows:

1. App gets Connection from pool
2. Pool provides a PoolableConnection (which extends DelegateConnection)
2. App uses Connection then calls close()
3. PoolableConnection overrides DelegateConnection's close(), because it 
actually closes the underlying connection, and uses pool.returnObject().
4. GenericObjectPool.returnObject() then calls factory.passivate() on 
the connection
5. PoolableConnectionFactory calls DelegateConnection.passivate() which 
closes all of the DelegateStatements and DelegateResultSets that belong 
to the DelegateConnection.

But looking at the code I think I found a situation where this doesn't 
happen.  At step 4 the GenericObjectPool.returnObject() code executes 
the following:

         if(_testOnReturn && !(_factory.validateObject(obj))) {
             success = false;
         } else {
             try {
                 _factory.passivateObject(obj);
             } catch(Exception e) {
                 success = false;
             }
         }

If we test our connections on return and the validation fails, then the 
object will be destroyed later on with factory.destroyObject().  But 
PoolableConnectionFactory.destroyObject() just calls 
PoolableConnection.reallyClose() which closes the underlying connection. 
  The passivate() code is not called and any open ResultSets and 
Statements are never closed.

So either GenericObjectPool should be calling passivate on everything 
returned, or DBCP's factory should call passivate when destroying 
objects (which sounds funny).


> 
> Moral of the story:  ALWAYS close your statements and result sets.
> 
> 
>>Regrettably, while the JDBC 3.0 specification formally addresses the former
>>case in chapter 13.1.3, it appears to be mute on the latter.
>>
>>
>>Robert Egan
> 
> 
> Craig
> 
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: commons-user-unsubscribe@jakarta.apache.org
> For additional commands, e-mail: commons-user-help@jakarta.apache.org
> 
> 


-- 
Jason Lea


Mime
View raw message