UnboundID LDAP SDK for Java

Ping Identity
Product Information

Frequently-Asked Questions

General Questions

  1. What is the UnboundID LDAP SDK for Java?
  2. What advantages does the UnboundID LDAP SDK have over other LDAP APIs?
  3. How can I get the LDAP SDK?
  4. Where can I find the documentation for the LDAP SDK?
  5. Does the LDAP SDK work with any LDAP directory server?
  6. What LDAP specifications does the LDAP SDK support?
  7. Does the LDAP SDK support LDAPv2?

Licensing and Legal Questions

  1. Is the LDAP SDK free to use?
  2. Can I redistribute the LDAP SDK with my application? What do I need to include?
  3. What license does the LDAP SDK use?
  4. Why is the LDAP SDK available under multiple licenses? Which should I choose for my application?
  5. Is the LDAP SDK open source?
  6. Can the LDAP SDK be used in closed source or proprietary applications?
  7. Can the LDAP SDK be used in applications which are intended only for private use and will not be redistributed?

Support Questions

  1. How can I get help, ask questions, report bugs, or provide feedback?
  2. How can I keep up to date with new releases and the latest news about the LDAP SDK?
  3. How can I debug problems in which the LDAP SDK isn't behaving as I expected?

API Questions

  1. Is the LDAP SDK suitable for production use?
  2. Is backward compatibility maintained between releases?
  3. Is the LDAP SDK threadsafe?
  4. Is the LDAP SDK extensible?
  5. How can I determine the version number for the LDAP SDK build that I have?

Usage Questions

  1. Where can I find examples that demonstrate how to use the LDAP SDK?
  2. How do I create a connection to an LDAP directory server?
  3. How do I create secure connections?
  4. How do I perform searches?
  5. How do I modify entries?
  6. How do I add new entries?
  7. How do I use connection pools?
  8. How do I process asynchronous operations?
  9. How do I read and write LDIF files?


What is the UnboundID LDAP SDK for Java?

The UnboundID LDAP SDK for Java is a fast, powerful, user-friendly, and completely free Java API for communicating with LDAP directory servers. It is an alternative to other APIs like JNDI, the Netscape Directory SDK for Java, and JLDAP. If you need to perform LDAP communication (or perform other directory-related processing like reading and writing LDIF files), then this is the API that you should be using.


What advantages does the UnboundID LDAP SDK have over other LDAP APIs?

The UnboundID LDAP SDK for Java provides a number of advantages over other Java-based LDAP APIs. See this document for a detailed overview of the advantages that our LDAP SDK provides over the alternatives, including a single-page comparison that summarizes many of the benefits.


How can I get the LDAP SDK?

The UnboundID LDAP SDK for Java is available for download at https://github.com/pingidentity/ldapsdk.


Where can I find the documentation for the LDAP SDK?

The LDAP SDK documentation (including this FAQ) is included with the LDAP SDK in the "docs" directory. The documentation for the latest release is also available online at https://docs.ldap.com/ldap-sdk/docs/.


Does the LDAP SDK work with any LDAP directory server?

Yes. The UnboundID LDAP SDK for Java supports the standard LDAP protocol, and will work with any directory server that supports LDAPv3. Note that LDAP is an extensible protocol and there are a number of optional features. Not all directory servers support all of the features offered by the LDAP SDK, and some directories may provide controls, extended operations, or SASL mechanisms not explicitly supported by the LDAP SDK (although the LDAP SDK is also extensible and it is possible to add support for custom controls, extended operations, and SASL mechanisms that it doesn't provide out of the box).


What LDAP specifications does the LDAP SDK support?

The LDAP SDK provides full support for the core LDAPv3 protocol as described in RFC 2251 and updated in RFC 4511. It also supports a number of controls, extended operations, and other capabilities described in a number of other RFCs and IETF drafts. See this page for information about some of the specifications supported by the LDAP SDK.


Does the LDAP SDK support LDAPv2?

No, it does not. LDAPv2 is an older version of the protocol with a much more limited feature set than LDAPv3 and using a somewhat arcane encoding. It was declared "historic" by RFC 3494 in 2003 and shouldn't be used for new development.


Is the LDAP SDK free to use?

Yes. The UnboundID LDAP SDK is completely free to use and redistribute by itself or in a larger work under the terms of the Apache License, Version 2.0, the GPLv2, the LGPLv2.1, or the UnboundID LDAP SDK Free Use License.


Can I redistribute the LDAP SDK with my application? What do I need to include?

Yes. You can redistribute the UnboundID LDAP SDK for Java with your application. The only requirements are that you include the appropriate license file (one or more of the Apache License, the GPLv2, the LGPLv2.1, or the UnboundID LDAP SDK Free Use License, depending on which you have decided to use) along with the unboundid-ldapsdk.jar file.


What license does the LDAP SDK use?

The UnboundID LDAP SDK for Java is available under the terms of the OSI-approved, open source, and very permissive Apache License, Verison 2.0. For legacy purposes, it is also available under the terms of the GNU General Public License version 2 (GPLv2), the GNU Lesser General Public License version 2.1 (LGPLv2.1), and the UnboundID LDAP SDK Free Use License.


Why is the LDAP SDK available under multiple licenses? Which should I choose for my application?

We want to make it as easy and painless as possible to use the UnboundID LDAP SDK, so we have chosen licenses that should cover as broad a range of possible use cases as possible.

As of the 5.0.0 release, the LDAP SDK is available under the terms of the Apache License, Version 2.0. This is a very permissive OSI-approved open source license that should be suitable for just about any use case. We strongly recommend that all new users of the LDAP SDK choose this license.

Prior to the 5.0.0 release, the LDAP SDK was available under a couple of other open source licenses, including GPLv2 and LGPLv2.1. The GPLv2 license may be a good choice if you're using the LDAP SDK in an application that is itself licensed under the terms of the GPLv2 or a compatible license, but compatibility issues mean that it's not a very good choice for software under other licenses. The LGPLv2.1 is much more permissive than the GPLv2, but not quite as permissive as the Apache License.

The LDAP SDK is also available under the terms of the UnboundID LDAP SDK Free Use License. This is not an open source license, but it was designed to be compatible with a very broad range of applications (as long as you don't need to alter the LDAP SDK itself). However, given that this is a non-standard license, and given that the Apache License should be much more friendly for just about all desired use cases, we recommend using the Apache License over the UnboundID LDAP SDK Free Use License unless you're already using the LDAP SDK under those terms.

If you have licensed Ping Identity server products that include the LDAP SDK, then you may also use the LDAP SDK under the terms of that license agreement.


Is the LDAP SDK open source?

Yes. The LDAP SDK is available under the Apache License, Version 2.0, the GPLv2 and the LGPLv2.1, which are OSI-approved open source licenses. The full source for the LDAP SDK is available in the src.zip file which is included in the SDK download. It's also available on GitHub and on SourceForge.

The LDAP SDK is also available under the terms of the UnboundID LDAP SDK Free Use License. This is not an open source license, but is free to use, and may be compatible with some open source licenses.


Can the LDAP SDK be used in closed source or proprietary applications?

Yes. The LDAP SDK may be used in closed source or proprietary applications under the terms of the Apache License, Version 2.0, the LGPLv2.1, or the UnboundID LDAP SDK Free Use License. The GPLv2 license is not compatible for use with non-open-source applications.


Can the LDAP SDK be used in applications which are intended only for private use and will not be redistributed?

Yes. There are no restrictions on the use of the LDAP SDK in an application that is for internal use only and will not be redistributed outside of your organization. If you do redistribute the LDAP SDK itself or an application that uses the LDAP SDK, then you need to comply with the terms of the license that you have selected.


How can I get help, ask questions, report bugs, or provide feedback?

If you have questions, comments, problem reports, or any other feedback regarding the LDAP SDK, then you may provide it using one of the following options:


How can I keep up to date with new releases and the latest news about the LDAP SDK?

You can join the ldap-sdk-announce@lists.sourceforge.net mailing list, which will be used to provide notification of new releases and significant updates.


How can I debug problems in which the LDAP SDK isn't behaving as I expected?

The LDAP SDK provides access to debugging information using the standard Java logging framework. It can be enabled either programmatically or by setting Java properties. See the Debugging SDK Operations page for information about accessing enabling and accessing debugging capabilities.


Is the LDAP SDK suitable for production use?

The current version of the LDAP SDK is very stable and is suitable for use in production applications. We have developed an extensive test suite specifically for the LDAP SDK, and it also undergoes significant testing as it is used in our other products.


Is backward compatibility maintained between releases?

Whenever possible, we will avoid making incompatible changes in the LDAP SDK. In fact, we have unit tests in place which compare the current API against that of previous releases to ensure that no incompatibilities have been introduced. However, if there is sufficient justification, we reserve the right to break backward compatibility under the following conditions:

In the event that we do make such an incompatible change, it will be documented in the release notes for the new version.


Is the LDAP SDK threadsafe?

The LDAP SDK has been designed to be highly concurrent and scalable. As much of the LDAP SDK has been made threadsafe as is possible to do without adversely impacting performance or flexibility. Connections can be used to process multiple requests at the same time as long as none of them does something that will impact the state of that connection (e.g., tries to close or re-establish the connection, tries to perform a bind, or tries to initiate StartTLS negotiation).

The com.unboundid.util.ThreadSafety annotation type may be used to determine whether a given class or interface is threadsafe. All public classes and interfaces in the LDAP SDK should be marked with this annotation type to indicate whether instances may be safely accessed via multiple threads at the same time. This annotation type appears in the generated javadoc documentation, and for special cases in which a class may be partially threadsafe (like the LDAPConnection caveats mentioned above) the class-level documentation provides additional information about how such objects may be used concurrently.


Is the LDAP SDK extensible?

The LDAP SDK does provide various forms of extensibility. In particular, it contains a number of non-final classes that may be extended to provide additional functionality. It is possible to define custom controls, extended requests and results, SASL mechanisms, matching rules, server sets, and command-line tools by extending classes provided by the LDAP SDK.

Similarly, the LDAP SDK provides a number of interfaces that may be implemented by third-party code for various purposes, including notification of certain types of events or messages received from the server, establishing connections for following referrals, and transforming entries read from LDIF files.

However, the LDAP SDK also includes a number of interfaces and non-final classes that are intended to be extended only by code within the LDAP SDK itself and not by third-party code outside of the LDAP SDK. To help developers distinguish which classes and interfaces may be extended by external code and which are only allowed for classes in the LDAP SDK itself, all public interfaces and all non-final public classes have been updated to include an annotation which indicates whether new implementations may be provided in third-party code. If a class or interface contains the @Extensible annotation, then it is safe for third-party code to extend. Conversely, if a class or interface contains the @NotExtensible annotation then it is not intended to be implemented by code outside of the LDAP SDK (although objects of that type may be used by third-party code). These annotations are visible in the generated Javadoc documentation.


How can I determine the version number for the LDAP SDK build that I have?

There are a number of ways to determine the version of the LDAP SDK that you are using:


Where can I find examples that demonstrate how to use the LDAP SDK?

The UnboundID LDAP SDK for Java comes with many examples demonstrating its use. The following kinds of examples are available:


How do I create a connection to an LDAP directory server?

The com.unboundid.ldap.sdk.LDAPConnection class provides the main API for communicating with LDAP directory servers. To create a new LDAPConnection object, establish the connection, and authenticate to the directory server, you can use code like:

LDAPConnection connection = new LDAPConnection();
connection.connect("server.example.com", 389);
connection.bind("uid=john.doe,ou=People,dc=example,dc=com", "password');

You can also create the connection and establish it at the same time, like:

LDAPConnection connection = new LDAPConnection("server.example.com", 389);
connection.bind("uid=john.doe,ou=People,dc=example,dc=com", "password');

And you can also do all three in a single step:

LDAPConnection connection = new LDAPConnection("server.example.com", 389,
     "uid=john.doe,ou=People,dc=example,dc=com", "password");

How do I create secure connections?

The LDAP SDK supports the use of SSL and StartTLS for secure communication. SSL should be used to create connections that are always secure (and will generally use a different port from that used for LDAP communication, typically port 636). StartTLS may be used to add security to an existing insecure connection (and will communicate over the same port used for insecure LDAP communication, typically port 389). In both cases, the com.unboundid.util.ssl.SSLUtil class may be used to help configure the underlying security layer. The Javadoc documentation for the SSLUtil class provides a more thorough explanation of everything involved in creating connections, but the following example provides a quick demonstration of the process:

AggregateTrustManager trustManager = new AggregateTrustManager(false,
     JVMDefaultTrustManager.getInstance(),
     new TrustStoreTrustManager(trustStorePath, trustStorePIN,
          "PKCS12", true));
SSLUtil sslUtil = new SSLUtil(trustManager);

LDAPConnectionOptions connectionOptions = new LDAPConnectionOptions();
connectionOptions.setSSLSocketVerifier(
     new HostNameSSLSocketVerifier(true));

try (LDAPConnection connection = new LDAPConnection(
          sslUtil.createSSLSocketFactory(), connectionOptions,
          serverAddress, serverLDAPSPort))
{
  // Use the connection here.
  RootDSE rootDSE = connection.getRootDSE();
}

How do I perform searches?

There are two primary ways in which you can perform searches in a synchronous manner. For simple searches that are expected to match a small number of entries, you can allow the SDK to capture all of the entries in a list that it will make available in the SearchResult object that is returned. For example:

SearchResult searchResult = connection.search("dc=example,dc=com",
     SearchScope.SUB, "(uid=john.doe)");
System.out.println(searchResult.getEntryCount() + " entries returned.");
for (SearchResultEntry e : searchResult.getSearchEntries())
{
  System.out.println(e.toLDIFString());
  System.out.println();
}

For searches that are expected to match a large number of entries, or that may take a long time to complete and you want to ensure that entries are processed as quickly as they are returned, then you can implement the com.unboundid.ldap.sdk.SearchResultListener interface. This interface contains methods that will be called whenever a search result entry or reference is returned by the server for the search. The LDAPConnection.search method will still block until the search has completed. For example:

// The searchEntryReturned method of the provided searchListener will be
// invoked for each entry returned.  The searchReferenceReturned method of the
// searchListener will be invoked for each reference returned.  The call to
// the LDAPConnection.search method will not return until the search has
// completed, and the entries will not be available in the result, although the
// number of entries returned will still be included.
SearchResult searchResult = connection.search(searchListener,
     "dc=example,dc=com", SearchScope.SUB, "(givenName=John)");
System.out.println(searchResult.getEntryCount() + " entries returned.");

How do I modify entries?

The com.unboundid.ldap.sdk.Modification class may be used to describe the change or set of changes that should be made to a single attribute. A modify operation may be processed using one or more modifications, like:

Modification modification = new Modification(ModificationType.REPLACE,
     "description", "This is the new description for the user");
LDAPResult result = connection.modify(
     "uid=john.doe,ou=People,dc=example,dc=com", modification);

As a convenience, it is also possible to process modifications using the LDIF representation, with a separate value per line of the LDIF. For example:

LDAPResult result = connection.modify(
     "dn: uid=john.doe,ou=People,dc=example,dc=com",
     "changetype: modify",
     "replace: description",
     "description: This is the new description for the user");

How do I add new entries?

Entries can be added using a distinguished name and collection of attributes, like:

Attribute[] attributes =
{
  new Attribute("objectClass", "top", "person", "organizationalPerson",
       "inetOrgPerson"),
  new Attribute("uid", "john.doe"),
  new Attribute("givenName", "John"),
  new Attribute("sn", "Doe"),
  new Attribute("cn", "John Doe")
};
LDAPResult result = connection.add("uid=john.doe,ou=People,dc=example,dc=com",
     attributes);

As with the modify operation, add operations can be processed using the LDIF representation of the entry to add. For example:

LDAPResult result = connection.add(
     "dn: uid=john.doe,ou=People,dc=example,dc=com",
     "objectClass: top",
     "objectClass: person",
     "objectClass: organizationalPerson",
     "objectClass: inetOrgPerson",
     "uid: john.doe",
     "givenName: John",
     "sn: Doe",
     "cn: John Doe");

How do I use connection pools?

The UnboundID LDAP SDK for Java provides support for connection pools that can be used to maintain multiple connections to a directory server, or even multiple connections spread across multiple directory servers. The easiest way to create a connection pool is to provide an established (and optionally authenticated) connection to use as the template for creating new connections and the initial and maximum number of connections that should be maintained in the pool. For example:

LDAPConnection connection = new LDAPConnection("server.example.com", 389,
     "uid=john.doe,ou=People,dc=example,dc=com", "password");
LDAPConnectionPool pool = new LDAPConnectionPool(connection, 1, 10);

As with traditional connection pool implementations, it is possible to check out a connection, do something with it, and return it back to the pool, like:

LDAPConnection connection = pool.getConnection();
try
{
  SearchResult searchResult = connection.search("dc=example,dc=com",
       SearchScope.SUB, "(objectClass=*)");
  // Do something with the result.
  pool.releaseConnection(connection);
}
catch (LDAPSearchException lse)
{
  // The search failed.  See if the connection is still valid and either
  // release it back to the pool or notify the pool that it is no longer valid
  // so that it will create a new one in its place.
  if (ResultCode.isConnectionUsable(lse.getResultCode()))
  {
    pool.releaseConnection(connection);
  }
  else
  {
    pool.releaseDefunctConnection(connection);
  }
}

However, it is also possible to perform operations in the context of the connection pool without the need to explicitly check out the connection and perform all of the appropriate error handling. The LDAPConnectionPool class implements the same interface (LDAPInterface) as the LDAPConnection class, so it is possible to perform operations against a pool in much the same way as with a single connection. For example, the following is the logical equivalent to the above search:

SearchResult searchResult = pool.search("dc=example,dc=com", SearchScope.SUB,
     "(objectClass=*)");
// Do something with the result.

How do I process asynchronous operations?

The LDAP SDK provides relatively simple interfaces that may be used to process add, compare, delete, modify, modify DN, and search operations in an asynchronous manner. In this case, the LDAP SDK will return control to the caller immediately after sending the request to the server without waiting for the response. This allows the client to perform other processing in the meantime, and it will be notified when the response message(s) arrive for that operation. This page describes the process for performing asynchronous operations in the LDAP SDK.


How do I read and write LDIF files?

The com.unboundid.ldif package provides classes that may be used to read and write entries and change records using the LDAP Data Interchange Format (LDIF) syntax. The LDIFReader class can be used to read entries and change records, and the LDIFWriter class can be used to write them. The following code provides a simple example demonstrating the process that could be used to read entries from one file and write them to another:

LDIFReader ldifReader = new LDIFReader("/path/to/source.ldif");
LDIFWriter ldifWriter = new LDIFWriter("/path/to/target.ldif");
while (true)
{
  Entry entry = ldifReader.readEntry();
  if (entry == null)
  {
    // There are no more entries to be read.
    break;
  }
  ldifWriter.writeEntry(entry);
}
ldifReader.close();
ldifWriter.close();