[ 
https://issues.apache.org/jira/browse/DBCP-216?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#action_12543792
 ] 

Phil Steitz commented on DBCP-216:
----------------------------------

>From commons-dev post by Stephane Demurget 13-nov-07.  Shows not removing 
>listener when connection is removed from pc map causes an exception when a 
>connection is returned when maxIdle is reached.  

Thread [pool-5-thread-4] (Suspended (exception IllegalStateException))
       KeyedCPDSConnectionFactory.connectionClosed(ConnectionEvent) line:
265
       SybPooledConnection.notifyListeners(SQLException) line: 225
       SybConnectionProxy.close() line: 106
       SybPooledConnection.close() line: 166
       KeyedCPDSConnectionFactory.destroyObject(Object, Object) line: 175

       GenericKeyedObjectPool.returnObject(Object, Object) line: 997
       KeyedCPDSConnectionFactory.connectionClosed(ConnectionEvent) line:
268
       SybPooledConnection.notifyListeners(SQLException) line: 225
       SybConnectionProxy.close() line: 106
       ... (i'm calling close on the SQL Connection here, when the thread
is finished)

After analyzing it a bit I understand the pool wants to destroy the object
because my pool can not support any more idle connection (I'm at the point
where active=maxActive=maxIdle=5).
What I do not understand is why the destroyObject method does:

public void destroyObject(Object key, Object obj) throws Exception {
       if (obj instanceof PooledConnectionAndInfo) {
           PooledConnection pc =
((PooledConnectionAndInfo)obj).getPooledConnection();
           pcMap.remove(pc);
           pc.close();
       }
   }

Which means it removes the mapping and close the PooledConnection. At this
point, the listener is still active and it calls the listener which will
obviously fail:

public void connectionClosed(ConnectionEvent event) {
       PooledConnection pc = (PooledConnection)event.getSource();
       // if this event occured becase we were validating, ignore it
       // otherwise return the connection to the pool.
       if (!validatingMap.containsKey(pc)) {
           PooledConnectionAndInfo info =
               (PooledConnectionAndInfo) pcMap.get(pc);
           if (info == null) {
               throw new IllegalStateException(NO_KEY_MESSAGE);   //
<--------- the Exception which is thrown
           }



> Improvement of error recovery in KeyedCPDSConnectionFactory
> -----------------------------------------------------------
>
>                 Key: DBCP-216
>                 URL: https://issues.apache.org/jira/browse/DBCP-216
>             Project: Commons Dbcp
>          Issue Type: Improvement
>    Affects Versions: 1.2.2
>         Environment: Windows XP, Java 1.5.0_06-b05, Sybase ASE 12.5.4, 
> jConnect 6.0.5 EBF 13862, Commons Pool 1.3
>            Reporter: Marcos Sanz
>             Fix For: 1.3
>
>         Attachments: KeyedCPDSConnectionFactory.java.diff
>
>
> Attached you'll find a patch that improves the recovery of the class in 
> different error situations.
> 1. The addition of removeConnectionEventListener() in destroyObject() ensures 
> that the listener is removed, which is not guaranteed to have happened upon 
> call of destroyObject(). We are for sure not interested any more in events, 
> since we are about to destroy.
> 2. The same addition is made to connectionClosed(). Additionally, we have 
> substituted there the call to destroyObject() with a call to 
> pool.invalidateObject(). This is necessary because otherwise the object is 
> destroyed but not removed from the pool.
> 3. The same substitution is made in connectionErrorOccurred(), otherwise the 
> object might remain in the pool.

-- 
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.

Reply via email to