Content Synchronization (Sync Repl)

Request that the server send the client updates in order for the client to stay in sync with the server. See RFC 4533.

Note that these examples use the DefaultCookieManager which stores cookie data in memory. Most implementers will want to provider a custom implementation to persist cookie data. The interface for CookieManager looks like:

public interface CookieManager
{
  byte[] readCookie(); // invoked when the operation begins

  void writeCookie(byte[] cookie); // invoked whenever a cookie is seen in a control or message
}

Refresh Only

Creates a SyncReplClient to use for a content synchronization without an existing cookie. By setting the persist property to false we expect the server will send the client all content followed by a response. Which means we do not expect to block indefinitely.

Connection conn = DefaultConnectionFactory.getConnection("ldap://directory.ldaptive.org");
try {
  conn.open();
  SyncReplClient client = new SyncReplClient(conn, false); // false indicates do not persist
  SearchRequest request = SearchRequest.newObjectScopeSearchRequest("dc=ldaptive,dc=org");
  BlockingQueue<SyncReplItem> results = client.execute(request, new DefaultCookieManager());
  while (true) {
    SyncReplItem item = results.take(); // blocks until result is received
    if (item.isEntry()) {
      SyncStateControl ssc = item.getEntry().getSyncStateControl();
      LdapEntry entry = item.getEntry().getSearchEntry();
      // process this entry with the sync state control data
    } else if (item.isMessage()) {
      SyncInfoMessage sim = item.getMessage();
      // process this info message
    } else if (item.isResponse()) {
      SyncDoneControl sdc = item.getResponse().getSyncDoneControl();
      // synchronization complete
      break;
    } else if (item.isAsyncRequest()) {
      // request has begun
      AsyncRequest ar = item.getAsyncRequest();
    } else if (item.isException()) {
      // an error has occurred, try again
      while (true) {
        try {
          conn.reopen();
          break;
        } catch (LdapException e) {
          System.err.println(
            "Failed to reopen connection: " + e.getMessage());
          try {
            Thread.sleep(5000);
          } catch (InterruptedException ie) {}
        }
      }
      results = client.execute(request, new DefaultCookieManager());
    }
  }
} finally {
  conn.close();
}

Refresh and Persist

Creates a SyncReplClient to use for a content synchronization without an existing cookie. By setting the persist property to true we expect the server will continue sending us content updates until the operation is cancelled.

Connection conn = DefaultConnectionFactory.getConnection("ldap://directory.ldaptive.org");
try {
  conn.open();
  SyncReplClient client = new SyncReplClient(conn, true); // true indicates persist
  SearchRequest request = SearchRequest.newObjectScopeSearchRequest("dc=ldaptive,dc=org");
  BlockingQueue<SyncReplItem> results = client.execute(request, new DefaultCookieManager());
  while (true) {
    SyncReplItem item = results.take(); // blocks until result is received
    if (item.isEntry()) {
      SyncStateControl ssc = item.getEntry().getSyncStateControl();
      LdapEntry entry = item.getEntry().getSearchEntry();
      // process this entry with the sync state control data
      if (entry.size() > 0) { // arbitrary condition
        // stop receiving updates
        client.cancel(item.getEntry().getSearchEntry().getMessageId());
      }
    } else if (item.isMessage()) {
      SyncInfoMessage sim = item.getMessage();
      // process this info message
    } else if (item.isResponse()) {
      SyncDoneControl sdc = item.getResponse().getSyncDoneControl();
      // synchronization complete
      break;
    } else if (item.isAsyncRequest()) {
      // request has begun
      AsyncRequest ar = item.getAsyncRequest();
    } else if (item.isException()) {
      // an error occurred, try again
      while (true) {
        try {
          conn.reopen();
          break;
        } catch (LdapException e) {
          System.err.println(
            "Failed to reopen connection: " + e.getMessage());
          try {
            Thread.sleep(5000);
          } catch (InterruptedException ie) {}
        }
      }
      results = client.execute(request, new DefaultCookieManager());
    }
  }
} finally {
  conn.close();
}

Provider Support

JNDI JLDAP Apache LDAP UnboundID OpenDJ
Functionality exists in the provider API and has been confirmed
Functionality does not exist in the provider API
Functionality exists in the provider API, but did not work in our test environment
? Functionality exists in the provider API, but has not been integrated into the ldaptive provider