Chapter 4. Using the LDAP SDK

Table of Contents
4.1. Synchronous & Asynchronous Operations
4.2. Managing Errors

As LDAP relies on a connection from the client to the directory server, the starting point for working with the LDAP SDK is a new LDAPConnectionFactory, from which you then get either a synchronous connection, or pass in a handler to an asynchronous connection. You then use the connection to make requests and get responses from the directory server.

4.1. Synchronous & Asynchronous Operations

For synchronous operations your application gets a connection from the LDAPConnectionFactory and requests operations on the connection. When finished, your application closes the connection.

final LDAPConnectionFactory factory = new LDAPConnectionFactory(host, port);
Connection connection = null;

try {
    connection = factory.getConnection();

    // Perform operations on the connection, such as connection.bind(),
    // connection.search(), connection.modify(), etc.

    } catch (final ErrorResultException e) {
        System.err.println(e.getMessage());
        System.exit(e.getResult().getResultCode().intValue());
        return;
    } finally {
        if (connection != null) {
            connection.close();
        }
    }

For a complete example in context, see Search.java, one of the OpenDJ LDAP SDK examples.

For asynchronous operations, your application passes a result handler to LDAPConnectionFactory.getConnectionAsync() that implements the ResultHandler<Connection> interface.

private static final class ConnectResultHandlerImpl
        implements ResultHandler<Connection> {
    @Override
    public void handleErrorResult(final ErrorResultException error) {
        ...
    }

    @Override
    public void handleResult(final Connection connection) {
        // Connect succeeded: save connection and initiate bind.
        SearchAsync.connection = connection;

        final BindRequest request =
                Requests.newSimpleBindRequest(userName, password.toCharArray());
        connection.bindAsync(request, null, new BindResultHandlerImpl());
    }
}

// Main method initiates async operations by getting a connection...
final LDAPConnectionFactory factory = new LDAPConnectionFactory(hostName, port);
factory.getConnectionAsync(new ConnectResultHandlerImpl());

...

if (connection != null) {
    connection.close();
}

When the connection result handler gets a connection, your application can pass result handlers for other operations using methods on the connection named *Async(). For most operations, your application implements ResultHandler. For searches, your application implements SearchResultHandler. The result handler is notified upon completion of the operation.

Asynchronous methods are non-blocking, returning a FutureResult whose get() method lets you retrieve the result. Your application must coordinate concurrency when you use asynchronous operations.

For a complete example in context, see SearchAsync.java, one of the OpenDJ LDAP SDK examples.

4.2. Managing Errors

LDAP defines many result codes to deal with conditions other than success. The ResultCode class encapsulates the LDAP codes and additional client-side codes specific to the SDK.

Your application deals with most non-success result codes when it catches one of the LDAP SDK exceptions corresponding to the operation you requested. ErrorResultException is a common way for the SDK to indicate a non-successful result. Your application can then take remedial action based on the result code, as in the following synchronous excerpt.

final LDAPConnectionFactory factory = new LDAPConnectionFactory(host, port);
Connection connection = null;

try {
    connection = factory.getConnection();
    connection.bind(name, password);

    // Perform operations on the connection...

} catch (final ErrorResultException e) {

    // Take remedial action based on the result code...
    // e.getResult().getResultCode() returns the code for you to interpret.

} finally {
    if (connection != null) {
        connection.close();
    }
}

Also notice the methods ResultCode.getName() that provides a short, human-readable version of the result code, and Result.getDiagnosticMessage() that can also help debug problems after the fact.