[Date Prev][Date Next] [Chronological] [Thread] [Top]

OpenLdap problem with Paging and Sun JNDI booster pack



Hello there,

You may remember a week or so ago I emailed you all a problem I was having
with using OpenLdap in connection with the Sun LDAP/JNDI Booster Pack 1.0.
I've worked a bit more on it since then and have found what I believe to be
a bug either with the booster pack or with OpenLdap itself.

Firstly I was unaware that the problems I were having were actually 2
separate problems until I managed to find out what was causing one of them
and write a work-around for it. Here they are anyway:

Problem 1) Failure to obtain a cookie from the LDAP server through the
context.getResponseControls() method. This meant that you cannot access any
pages of results subsequent to the first page.

Problem 2) Random failure of the LDAP server when retrieving pages after the
first page.

I managed to figure out what was causing the first problem. When you run a
search on LDAP through  JNDI the result that you get back is an object
called a NamingEnumeration. You then iterate through the NamingEnumeration
and do something with the results. After you have finished doing something
with the results then you call the method context.getResponseControls();
this method is supposed to get an array of Control objects, one of which
will be an instance of PagedResultsRepsonseControl. You then call a method
on PagedResultsResponseControl to obtain a server generated cookie and then
use the cookie to get the next Page in the sequence.
However, I found that if you do not iterate through the NamingEnumeration
then when you call context.getResponseControls all you get is a null object
reference instead of an array Control objects. Not wanting to iterate
through a NamingEnumeration is a perfectly reasonable thing to want do if
(as in my case) for some reason you don't want look at Page 1 -> x and only
wanted to examine the NamingEnumeration for page x+1. If this is expected
behaviour then it is not documented anywhere in the API and should be.
I'll illustrate the problem with some example code that fails.

//get the InitialLdapContext here etc..
do
{
	naming = ctx.search(searchBase, filter, controls);
	//Unless you iterate though the
	//NamingEnumeration no cookie is obtainable
	//when you call ctx.getResponseControls()
	if(page == desiredPage)
	{
		int subcounter = 0;
		while(naming.hasMoreElements())
		{
			subcounter++;
			SearchResult si = (SearchResult)naming.nextElement();
			count++;
			System.out.println(si.getName());
		}
		System.out.println(ldapSearchFilter + " returned " + subcounter );
	}
	else
	{
		System.out.println(ldapSearchFilter + " did not return any entries.");
	}

	// check if the response controls are null
	Control[] response = ctx.getResponseControls();
	if(response != null)
	{
		b =((PagedResultsResponseControl)response[0]).getCookie();
	}
	else
	{
		b = null;
	}
	if(b != null)
	{
		//create new PagedResultsControl
		prc = new PagedResultsControl(pageSize, b, Control.CRITICAL);
		ctx.setRequestControls(new Control[] {prc});
	}
}while(b != null)
//rest of code..

All you need to do to fix the problem is to iterate though every
NamingEnumeration you get back from the server, even if you do nothing with
the results.

The second problem is one I've been unable to solve. When getting several
pages of results from the server I got OperationNotSupportedExceptions
thrown at random intervals wrapped around the following OpenLdap error
message:

[LDAP: error code 53 - paged results cookie is invalid or old]

Sometimes the error code is error code 2, but the wrapped error message
remains the same. Running the same test several hundred times didn't give
any clue as to what was happening, sometimes the exception was thrown when
getting the second page of results, sometimes all the pages were
successfully retrieved. The only thing that was consistently retrieved from
the server was the first page of results. Anything after that was just luck.
After putting the error message into Google I got the following bit of C
code from OpenLdap:

http://www.opensource.apple.com/darwinsource/10.3/OpenLDAP-37/OpenLDAP/serve
rs/slapd/controls.c

I don't know enough about OpenLdap and C to figure out what's going on here,
but if someone else does, then please send me an email as I could really do
with sorting out paging in the code I've written sooner rather than later.

Regards

Jon Poulton