Hi,

can you give the latest version (not released yet) a try? (You'll have to checkout the code base and build it)



On 20/12/2024 15:35, Andreas Schufft wrote:
Hi,

we encountered the same problem as described in ticket DIRAPI-398 in older versions of the API (before 2.1.7). The connection pools filled up because the close method on the underlying LdapConnection simply closed the connection instead of returning the connection to the pool. We build a workaround for us based on Proxy.newProxyInstance( , new Class[]{LdapConnection.class}). This works fine for. Starting with the latest release 2.1.7 we wanted to remove our own proxy and use the pooling provided by the API but unfortunaly this doesn't work for us.

When an object becomes returned to the pool (by calling releaseConnection the underlying pool throws an exception:

IllegalStateException: Returned object not currently part of this pool

I checked also the PooledLdapConnectionTest which contains a test (closeReleasesToPool) but this test only ferifies that the releaseConnection method is called on the pool. Unfortunaly I didn't find any integration tests which would show the problem.

A simple test which is executed against a real LDAP shows the problem:

     @Test
    void closeReleasedToPoolValidating() throws IOException, LdapException {
         final LdapConnectionConfig config = new LdapConnectionConfig();
         config.setLdapHost( "testldap" );
         config.setLdapPort(389);
        final PooledObjectFactory factory = new DefaultPoolableLdapConnectionFactory(config);
         LdapConnectionPool pool = new LdapConnectionPool(factory);
         try
         {
             final LdapConnection connection = pool.getConnection();
             Assertions.assertDoesNotThrow(() -> connection.close());
         }
         catch( final Exception e ) {
             Assertions.fail(e);
         }
     }

This will fail with the following error:

org.opentest4j.AssertionFailedError: Unexpected exception thrown: java.lang.RuntimeException: java.lang.IllegalStateException: Returned object not currently part of this pool

    at org.junit.jupiter.api.AssertionFailureBuilder.build(AssertionFailureBuilder.java:152)     at org.junit.jupiter.api.AssertDoesNotThrow.createAssertionFailedError(AssertDoesNotThrow.java:84)     at org.junit.jupiter.api.AssertDoesNotThrow.assertDoesNotThrow(AssertDoesNotThrow.java:53)     at org.junit.jupiter.api.AssertDoesNotThrow.assertDoesNotThrow(AssertDoesNotThrow.java:36)     at org.junit.jupiter.api.Assertions.assertDoesNotThrow(Assertions.java:3199)     at org.apache.directory.ldap.client.api.PooledLdapConnectionTest.closeReleasedToPoolNonValidating(PooledLdapConnectionTest.java:84)
     at java.lang.reflect.Method.invoke(Method.java:498)
     at java.util.ArrayList.forEach(ArrayList.java:1259)
     at java.util.ArrayList.forEach(ArrayList.java:1259)
Caused by: java.lang.RuntimeException: java.lang.IllegalStateException: Returned object not currently part of this pool     at org.apache.directory.ldap.client.api.LdapConnectionPool.releaseConnection(LdapConnectionPool.java:189)     at org.apache.directory.ldap.client.api.PooledLdapConnection.close(PooledLdapConnection.java:49)     at org.apache.directory.ldap.client.api.PooledLdapConnectionTest.lambda$closeReleasedToPoolNonValidating$1(PooledLdapConnectionTest.java:84)     at org.junit.jupiter.api.AssertDoesNotThrow.assertDoesNotThrow(AssertDoesNotThrow.java:49)
     ... 6 more
Caused by: java.lang.IllegalStateException: Returned object not currently part of this pool     at org.apache.commons.pool2.impl.GenericObjectPool.returnObject(GenericObjectPool.java:1031)     at org.apache.directory.ldap.client.api.LdapConnectionPool.releaseConnection(LdapConnectionPool.java:176)
     ... 9 more

When I debug the test I can see that the object within the Pool

GenericObjectPool.allObjects contains the value DefaultPooledObject with a PooledLdapConnection as object. The PooledLdapConnection contains the attribute connection of type LdapNetworkConnection.

So the Pool contains objects of type PooledLdapConnection, but the PooledLdapConnection will try to release the underlying connection to the pool and this fails.


The LdapConnectionPool#getConnection borrows an object from the pool (type PooledLdapConnection), but the PooledLdapConnection#close method tries to return the connection attribute of the PooledLdapConnection.

The behaviour is a little bit different whether you use the final DefaultPoolableLdapConnectionFactory or a ValidatingPoolableLdapConnectionFactory. The error is the same, but the object in the pools are of a different type.

If you are using the DefaultPoolableLdapConnectionFactory the pool consists of PooledLdapConnection objects (wrapping LdapNetworkConnection objects). When you are using a ValidatingPoolableLdapConnectionFactory the pool consists of MonitoringLdapConnection object (wrapping PooledLdapConnection objects).

Our only solution to this problem is staying on version 2.1.6 with our dynamic proxy object.

Thanks

Andreas



---------------------------------------------------------------------
To unsubscribe, e-mail: api-unsubscr...@directory.apache.org
For additional commands, e-mail: api-h...@directory.apache.org


--
*Emmanuel Lécharny* P. +33 (0)6 08 33 32 61
elecha...@apache.org

---------------------------------------------------------------------
To unsubscribe, e-mail: api-unsubscr...@directory.apache.org
For additional commands, e-mail: api-h...@directory.apache.org

Reply via email to