Concurrent Operations

Ldaptive provides some useful wrappers around LDAP operations to support threading and concurrency. This allows an application to execute an operation and then wait for the result as appropriate. By default a cached thread pool is used by the underlying ExecutorService.

Operation Workers

Searching is the most useful operation to perform concurrently. Multiple requests can be combined together and the client can wait until all operations have completed. All operations are executed on the same connection.

Connection conn = DefaultConnectionFactory.getConnection("ldap://directory.ldaptive.org");
try {
  conn.open();
  SearchRequest request1 = new SearchRequest("dc=ldaptive,dc=org","(givenName=daniel)");
  SearchRequest request2 = new SearchRequest("dc=ldaptive,dc=org","(sn=fisher)");
  SearchOperationWorker search = new SearchOperationWorker(new SearchOperation(conn));

  // to perform a single search
  Future<Response<SearchResult>> future = search.execute(request1);

  // to perform multiple searches
  Collection<Future<Response<SearchResult>>> futures = search.execute(request1, request2);

  // to perform multiple searches and wait
  Collection<Response<SearchResult>> responses = search.executeToCompletion(request1, request2);

  // cleanup the underlying executor service
  search.shutdown();
} finally {
  conn.close();
}

Implementations also exist for compare, bind, add, modify, modify DN, and delete operations.

Search Executors

Search Executors provide a useful abstraction for reusing search criteria and consequently it’s desirable to have some concurrency support built around them. Ldaptive provides two types of concurrent Search Executors.

ParallelSearchExecutor

Executes a list of search filters on the same connection. This allows multiple searches to execute in parallel while the client waits for all responses. A connection is retrieved from the factory and subsequently opened, then closed. If you need support for connection pooling see the ParallelPooledSearchExecutor.

ConnectionFactory cf = new DefaultConnectionFactory("ldap://directory.ldaptive.org");
ParallelSearchExecutor executor = new ParallelSearchExecutor();
SearchFilter sf1 = new SearchFilter("(givenName=daniel)");
SearchFilter sf2 = new SearchFilter("(sn=fisher)");

// iterates over the the search filters and executes each search on the same connection; null means return all attributes
Collection<Response<SearchResult>> responses = executor.search(
  cf, new SearchFilter[] {sf1, sf2}, (String[]) null);

// cleanup the underlying executor service
executor.shutdown();

AggregateSearchExecutor

Executes a list of search filters over a list of connection factories. This allows the same search to be run against multiple LDAPs with responses combined into a single collection. A connection is retrieved from each factory and subsequently opened, then closed. If you need support for connection pooling see the AggregatePooledSearchExecutor.

ConnectionFactory cf1 = new DefaultConnectionFactory("ldap://directory-1.ldaptive.org");
ConnectionFactory cf2 = new DefaultConnectionFactory("ldap://directory-2.ldaptive.org");
AggregateSearchExecutor executor = new AggregateSearchExecutor();
SearchFilter sf1 = new SearchFilter("(givenName=daniel)");
SearchFilter sf2 = new SearchFilter("(sn=fisher)");

// iterates over the connection factories and executes each search filter; null means return all attributes
Collection<Response<SearchResult>> responses = executor.search(
  new ConnectionFactory[] {cf1, cf2}, new SearchFilter[] {sf1, sf2}, (String[]) null);

// cleanup the underlying executor service
executor.shutdown();