Using the LDAP SDK
As LDAP relies on a connection
from the client application to the directory server,
the starting point for working with the LDAP SDK is
a new LDAPConnectionFactory.
The connection factory allows an application to get a connection
either synchronously or asynchronously.
The application then uses the connection
to make requests and to get responses from the directory server.
Synchronous vs. Asynchronous APIs
The LDAP SDK offers synchronous and asynchronous APIs.
The difference is that synchronous APIs
wait for each task to complete before starting the next task,
whereas asynchronous APIs
allow another task to start before the current one finishes.
Synchronous APIsConnectionsSynchronous
For synchronous operations the application gets a connection
from a connection factory,
and then requests operations on the connection in sequence.
When finished, the application closes the connection
as shown in the following example:
[jcp:org.forgerock.opendj.examples.Search:--- JCite ---]
For the complete example in context, see
Search.java.
Asynchronous APIsConnectionsAsynchronous
Asynchronous code can be tricky to read and to write.
To make coding easier,
the asynchronous APIs use promises.
Promises might be familiar to JavaScript developers.
A promise is the result of a task that might or might not be complete.
Fluent code style, which strings together chains of methods,
works well with promises.
The following code outline chains asynchronous calls together:
() {
@Override
public Promise apply(Connection connection)
throws LdapException {
SearchAsync.connection = connection;
return AsyncApp.bindAsync(
Requests.newSimpleBindRequest(bindDn, password));
}
})
// When the bind completes, perform an LDAP operation,
// returning a promise with the result of the operation.
// Here the bind result is consumed, and the next result produced.
.thenAsync(new AsyncFunction() {
@Override
public Promise apply(BindResult bindResult)
throws LdapException {
// Return a promise from an asynchronous method.
// return connection.***Async(...);
}
})
// An application might chain several more calls together.
// .thenAsync(new AsyncFunction() {...
// .thenAsync(new AsyncFunction() {...
// ...
// Handle the result, if any.
.thenOnResult(new ResultHandler() {
@Override
public void handleResult(Result result) {
// Handle the result.
}
})
// Handle any exceptions that arise.
.thenOnException(new ExceptionHandler() {
@Override
public void handleException(LdapException e) {
// Handle exceptions.
}
});
closeSilently(connection);
return;
}
}
]]>
The following example demonstrates a search using the asynchronous APIs:
[jcp:org.forgerock.opendj.examples.SearchAsync:--- Using Promises ---]
When the factory gets a connection,
the application passes an AsyncFunction
to apply to the connection to handle the bind
by using the thenAsync() method in the fluent style.
The application uses thenAsync() again
to pass another AsyncFunction to perform the operation.
In the sample shown here, the second call to thenAsync()
passes a function that performs a search,
using a handler to deal with the search results returned by the server.
The call to thenOnResult() handles the final result,
with the call to thenOnException() dealing with exceptions.
The application must coordinate concurrency when using asynchronous APIs.
For the complete example in context, see
SearchAsync.java.
Managing ErrorsErrorsLDAP 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
by catching LdapException objects
or handling them when supplied to FailureHandler objects
passed to onFailure() methods.
Your application can then take remedial action based on the result code,
as in the following synchronous example.
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 LdapException 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 help to debug problems after the fact.
When you have completely finished with a connection,
then use the close() method on it.