This class provides an implementation of an LDAP connection pool, which is a
structure that can hold multiple connections established to a given server
that can be reused for multiple operations rather than creating and
destroying connections for each operation. This connection pool
implementation provides traditional methods for checking out and releasing
connections, but it also provides wrapper methods that make it easy to
perform operations using pooled connections without the need to explicitly
check out or release the connections.
Note that both the
LDAPConnectionPool class and the
LDAPConnection class implement the
LDAPInterface interface.
This is a common interface that defines a number of common methods for
processing LDAP requests. This means that in many cases, an application can
use an object of type
LDAPInterface rather than
LDAPConnection, which makes it possible to work with either a single
standalone connection or with a connection pool.
Creating a Connection Pool
An LDAP connection pool can be created from either a single
LDAPConnection (for which an appropriate number of copies will be
created to fill out the pool) or using a
ServerSet to create
connections that may span multiple servers. For example:
// Create a new LDAP connection pool with ten connections established and
// authenticated to the same server:
LDAPConnection connection = new LDAPConnection(address, port);
BindResult bindResult = connection.bind(bindDN, password);
LDAPConnectionPool connectionPool = new LDAPConnectionPool(connection, 10);
// Create a new LDAP connection pool with 10 connections spanning multiple
// servers using a server set.
RoundRobinServerSet serverSet = new RoundRobinServerSet(addresses, ports);
SimpleBindRequest bindRequest = new SimpleBindRequest(bindDN, password);
LDAPConnectionPool connectionPool =
new LDAPConnectionPool(serverSet, bindRequest, 10);
Note that in some cases, such as when using StartTLS, it may be necessary to
perform some additional processing when a new connection is created for use
in the connection pool. In this case, a
PostConnectProcessor should
be provided to accomplish this. See the documentation for the
StartTLSPostConnectProcessor class for an example that demonstrates
its use for creating a connection pool with connections secured using
StartTLS.
Processing Operations with a Connection Pool
If a single operation is to be processed using a connection from the
connection pool, then it can be used without the need to check out or release
a connection or perform any validity checking on the connection. This can
be accomplished via the
LDAPInterface interface that allows a
connection pool to be treated like a single connection. For example, to
perform a search using a pooled connection:
SearchResult searchResult =
connectionPool.search("dc=example,dc=com", SearchScope.SUB,
"(uid=john.doe)");
If an application needs to process multiple operations using a single
connection, then it may be beneficial to obtain a connection from the pool
to use for processing those operations and then return it back to the pool
when it is no longer needed. This can be done using the
getConnection and
releaseConnection methods. If during
processing it is determined that the connection is no longer valid, then the
connection should be released back to the pool using the
releaseDefunctConnection method, which will ensure that the
connection is closed and a new connection will be established to take its
place in the pool.
Note that it is also possible to process multiple operations on a single
connection using the
processRequests method. This may be useful if
a fixed set of operations should be processed over the same connection and
none of the subsequent requests depend upon the results of the earlier
operations.
Connection pools should generally not be used when performing operations that
may change the state of the underlying connections. This is particularly
true for bind operations and the StartTLS extended operation, but it may
apply to other types of operations as well.
Performing a bind operation using a connection from the pool will invalidate
any previous authentication on that connection, and if that connection is
released back to the pool without first being re-authenticated as the
original user, then subsequent operation attempts may fail or be processed in
an incorrect manner. Bind operations should only be performed in a
connection pool if the pool is to be used exclusively for processing binds,
if the bind request is specially crafted so that it will not change the
identity of the associated connection (e.g., by including the retain identity
request control in the bind request if using the Commercial Edition of the
LDAP SDK with a Ping Identity, UnboundID, or Alcatel-Lucent 8661 Directory
Server), or if the code using the connection pool makes sure to
re-authenticate the connection as the appropriate user whenever its identity
has been changed.
The StartTLS extended operation should never be invoked on a connection which
is part of a connection pool. It is acceptable for the pool to maintain
connections which have been configured with StartTLS security prior to being
added to the pool (via the use of the
StartTLSPostConnectProcessor).
Pool Connection Management
When creating a connection pool, you may specify an initial number of
connections and a maximum number of connections. The initial number of
connections is the number of connections that should be immediately
established and available for use when the pool is created. The maximum
number of connections is the largest number of unused connections that may
be available in the pool at any time.
Whenever a connection is needed, whether by an attempt to check out a
connection or to use one of the pool's methods to process an operation, the
pool will first check to see if there is a connection that has already been
established but is not currently in use, and if so then that connection will
be used. If there aren't any unused connections that are already
established, then the pool will determine if it has yet created the maximum
number of connections, and if not then it will immediately create a new
connection and use it. If the pool has already created the maximum number
of connections, then the pool may wait for a period of time (as indicated by
the
getMaxWaitTimeMillis() method, which has a default value of zero
to indicate that it should not wait at all) for an in-use connection to be
released back to the pool. If no connection is available after the specified
wait time (or there should not be any wait time), then the pool may
automatically create a new connection to use if
getCreateIfNecessary() returns
true (which is the default).
If it is able to successfully create a connection, then it will be used. If
it cannot create a connection, or if
getCreateIfNecessary() returns
false, then an
LDAPException will be thrown.
Note that the maximum number of connections specified when creating a pool
refers to the maximum number of connections that should be available for use
at any given time. If
getCreateIfNecessary() returns
true,
then there may temporarily be more active connections than the configured
maximum number of connections. This can be useful during periods of heavy
activity, because the pool will keep those connections established until the
number of unused connections exceeds the configured maximum. If you wish to
enforce a hard limit on the maximum number of connections so that there
cannot be more than the configured maximum in use at any time, then use the
setCreateIfNecessary(boolean) method to indicate that the pool
should not automatically create connections when one is needed but none are
available, and you may also want to use the
setMaxWaitTimeMillis(long) method to specify a maximum wait time to
allow the pool to wait for a connection to become available rather than
throwing an exception if no connections are immediately available.