I am using the LDAP SDK from this site: https://www.unboundid.com/products/ldap-sdk/ . I would like to make a search operation which returns a lot of entries.
According to the FAQ's site, ( https://www.unboundid.com/products/ldap-sdk/docs/ldapsdk-faq.php#search ) I have to use a SearchResultListener implementation.
So here is what I did:
public class UpdateThread extends Thread implements SearchResultListener {
...
// create request
final SearchRequest request = new SearchRequest(this, instance.getBaseDN(),SearchScope.SUB, filter);
// Setting size limit of results.
request.setSizeLimit(2000);
...
// Get every result one by one.
@Override
public void searchEntryReturned(SearchResultEntry arg0) {
System.out.println("entry "+arg0.getDN());
}
The problem is that "searchEntryReturned" returns a maximum of 1000 results. Even if I set the size limit to "2000".
It is pretty simple to implement a paged LDAP query using standard java, by using the adding a PagedResultsControl
to the LdapContext
, without using a third party API as per Neil's answer above.
Hashtable<String, Object> env = new Hashtable<String, Object>(11);
env
.put(Context.INITIAL_CONTEXT_FACTORY,
"com.sun.jndi.ldap.LdapCtxFactory");
/* Specify host and port to use for directory service */
env.put(Context.PROVIDER_URL,
"ldap://localhost:389/ou=People,o=JNDITutorial");
try {
LdapContext ctx = new InitialLdapContext(env, null);
// Activate paged results
int pageSize = 5;
byte[] cookie = null;
ctx.setRequestControls(new Control[] { new PagedResultsControl(pageSize,
Control.NONCRITICAL) });
int total;
do {
/* perform the search */
NamingEnumeration results = ctx.search("", "(objectclass=*)",
new SearchControls());
/* for each entry print out name + all attrs and values */
while (results != null && results.hasMore()) {
SearchResult entry = (SearchResult) results.next();
System.out.println(entry.getName());
}
// Examine the paged results control response
Control[] controls = ctx.getResponseControls();
if (controls != null) {
for (int i = 0; i < controls.length; i++) {
if (controls[i] instanceof PagedResultsResponseControl) {
PagedResultsResponseControl prrc = (PagedResultsResponseControl) controls[i];
total = prrc.getResultSize();
if (total != 0) {
System.out.println("***************** END-OF-PAGE "
+ "(total : " + total + ") *****************\n");
} else {
System.out.println("***************** END-OF-PAGE "
+ "(total: unknown) ***************\n");
}
cookie = prrc.getCookie();
}
}
} else {
System.out.println("No controls were sent from the server");
}
// Re-activate paged results
ctx.setRequestControls(new Control[] { new PagedResultsControl(
pageSize, cookie, Control.CRITICAL) });
} while (cookie != null);
ctx.close();
Example copied from here.
Although it's almost certainly the case that the server is enforcing the size limit of 1000 entries, there are potentially ways to get around that by issuing the request in multiple parts.
If the server supports the use of the simple paged results control (as defined in RFC 2696 and supported in the LDAP SDK as per https://docs.ldap.com/ldap-sdk/docs/javadoc/com/unboundid/ldap/sdk/controls/SimplePagedResultsControl.html), then you can use it to iterate through the results in "pages" containing a specified number of entries.
Alternately, the virtual list view (VLV) request control (https://www.unboundid.com/products/ldap-sdk/docs/javadoc/index.html?com/unboundid/ldap/sdk/controls/VirtualListViewRequestControl.html) could be used, but I would probably only recommend that if the server doesn't support the simple paged results control because the VLV request control also requires that the results be sorted, and that likely either requires special configuration in the server or some pretty expensive processing in order to be able to service the request.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With