2.1 - Connection and disconnection

LDAP is a protocol which requires the user to be connected - and likely identified - in order to be able to send requests to the server. We maintain this connection potentially forever. What make the LDAP protocol different from, say, the HTTP protocol is that the connection must be issued explicitly. Let's see how we do that.

Opening a connection

We can open a secure or a standard connection.

Standard connection

We can first establish a standard connection, where the data are sent and received in clear text (encoded in ASN.1 BER, but still not encrypted). This example expose the way it's done :

LdapConnection connection = new LdapNetworkConnection( "localhost", 389 );

Here, we just created an unsafe connection locally, using the 389 port. Quite simple...

Secure connection

Although the LDAPS (LDAP over SSL) is now considered as deprecated, many people continue to use it. The big advantage of not using LDAPS is that you don't need to setup two different listening ports (one for LDAP -389- and another one for LDAPS -636- ).

The only difference with the previous example is that we have to tell the connection that it has to use SSL, by passing true as a third parameter (incidentally, passing false set a unsafe connection).

Here is an example

LdapConnection connection = new LdapNetworkConnection( "localhost", 636, true );

Maintaining the connection opened

We keep the connection opened for a limited period of time, defaulting to 30 seconds. This might be not long enough, so one can change this delay by calling the setTimeOut() method :

LdapConnection connection = new LdapNetworkConnection( "localhost", 389 );
connection.setTimeOut( 0 );
...
connection.close();

Note: Setting a value equal or below 0 will keep the connection opened for ever (or a soon as the connection is not explicitly closed).

Closing the connection

Once you don't need to use the connection anymore (remember that hodling a connection keeps a session opened on the server, and a socket opened between the client and the server), then you have to close it. This is done by calling the close() method :

LdapConnection connection = new LdapNetworkConnection( "localhost", 389 );
...
connection.close();

Using a pool of connections

Creating a connection is expensive. If that connection will be reused, or if your application needs multiple connections, you may want to consider using a connection pool.

This process is slightly more complex given that there are many parameters that can be used to tune the pool. Here is an example:

LdapConnectionConfig config = new LdapConnectionConfig();
config.setLdapHost( hostname );
config.setLdapPort( port );
config.setName( adminDn );
config.setCredentials( adminPassword );

DefaultLdapConnectionFactory factory = new DefaultLdapConnectionFactory( config );
factory.setTimeOut( connectionTimeout );

// optional, values below are defaults
GenericObjectPool.Config poolConfig = new GenericObjectPool.Config();
poolConfig.lifo = true;
poolConfig.maxActive = 8;
poolConfig.maxIdle = 8;
poolConfig.maxWait = -1L;
poolConfig.minEvictableIdleTimeMillis = 1000L * 60L * 30L;
poolConfig.minIdle = 0;
poolConfig.numTestsPerEvictionRun = 3;
poolConfig.softMinEvictableIdleTimeMillis = -1L;
poolConfig.testOnBorrow = false;
poolConfig.testOnReturn = false;
poolConfig.testWhileIdle = false;
poolConfig.timeBetweenEvictionRunsMillis = -1L;
poolConfig.whenExhaustedAction = GenericObjectPool.WHEN_EXHAUSTED_BLOCK;

LdapConnectionPool pool = new LdapConnectionPool(
    new DefaultPoolableLdapConnectionFactory( factory ), poolConfig ) );

This will create a pool of connections that will be pre-authenticated. If you do not setName and setCredentials, then the pool will contain unauthenticated connections.

The DefaultPoolableLdapConnectionFactory is sufficient for many cases. However, certain operations result in modifications to the connection itself. For example, when the pool is created, a bind operation will occur with the credentials supplied as part of the config. If you borrow a connection and perform a bind yourself, that would result in the connection being re-bound as a different user. The next time that connection gets borrowed, things are likely to break. If you perform any operation that results in a modification of the connection, you should instead use ValidatingPoolableLdapConnectionFactory:

...
LdapConnectionPool pool = new LdapConnectionPool(
    new ValidatingPoolableLdapConnectionFactory( factory ), poolConfig ) );
...

A connection pool using this factory will unbind and rebind any connection that was modified while it was borrowed (see the javadoc for more detail). This will be slower due to the additional operations, but not too significantly.