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 APIs Connections Synchronous 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 APIs Connections Asynchronous 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 Errors 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 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.