Announcement Announcement Module
No announcement yet.
Paged search results Page Title Module
Move Remove Collapse
Conversation Detail Module
  • Filter
  • Time
  • Show
Clear All
new posts

  • Paged search results

    Dear community,

    Quite recently, we implemented support for generic pre- and postprocessing of the DirContext through the interface DirContextProcessor and a corresponding search method in LdapTemplate:

    public interface DirContextProcessor {
       public void preProcess(DirContext ctx) throws NamingException;
       public void postProcess(DirContext ctx) throws NamingException;
    public void search(SearchExecutor se, NameClassPairCallbackHandler handler,
       DirContextProcessor processor) throws DataAccessException;
    We then created a base class to simplify implementing custom DirContextProcessors that use request controls:

    public abstract class AbstractRequestControlDirContextProcessor
          implements DirContextProcessor {
       public void preProcess(DirContext ctx) throws NamingException {
       public abstract Control createRequestControl();
    Spring LDAP now provides support for paged results by leveraging this concept. It does so by providing two classes: PagedResultsRequestControl and PagedResultsCookie. The PagedResultsRequestControl class creates a standard PagedResultsControl with the requested page size and adds it to the LdapContext. After the search, it gets the corresponding PagedResultsResponseControl from the LdapContext and retrieves two pieces of information from it: the estimated total result size and a cookie. This cookie contains information that the server needs the next time it is called with a PagedResultsControl. The wrapper class PagedResultsCookie is provided for storing this cookie.

    The following example shows how to achieve paged search results:

    public class PagedSearchIntegrationTests extends
          AbstractDependencyInjectionSpringContextTests {
       private LdapTemplate tested;
       // LDAP contains 5 persons matching the filter. Page size is 3.
       // Expects two batches of 3 and 2 persons respectively.
       public void testPagedResult() {
          SearchExecutor searchExecutor = new SearchExecutor() {
             public NamingEnumeration executeSearch(DirContext ctx)
                   throws NamingException {
                SearchControls searchControls = new SearchControls();
                   "(&(objectclass=person)(cn=Some Person*))", searchControls);
          PersonAttributesMapper mapper = new PersonAttributesMapper();
          CollectingNameClassPairCallbackHandler callbackHandler =
          PagedResultsRequestControl requestControl;
          requestControl = new PagedResultsRequestControl(3);
, callbackHandler, requestControl);
          PagedResultsCookie cookie = requestControl.getCookie();
          assertNotNull("Cookie should not be null yet", cookie.getCookie());
          assertEquals(3, callbackHandler.getList().size());
          // Prepare for second and last search
          requestControl = new PagedResultsRequestControl(3, cookie);
, callbackHandler, requestControl);
          cookie = requestControl.getCookie();
          assertNull("Cookie should be null now", cookie.getCookie());
          assertEquals(5, callbackHandler.getList().size());
    This is all still in the Subversion trunk, but feel free to have a look at it. And if you end up developing support for a specific control, we could then discuss if it can be incorporated into the framework.

    We expect the next release to be out in October.


  • #2
    Syntax question


    Excuse me but I don't understand this syntax :

    PersonAttributesMapper mapper = new PersonAttributesMapper();
    CollectingNameClassPairCallbackHandler callbackHandler = AttributesMapperCallbackHandler(mapper);

    Thank you for your explanation.


    • #3
      The AttributesMapperCallbackHandler is an (non-static) inner class in LdapTemplate. Initialization of of a non-static inner class needs to be done with reference to an instance to the surrounding class, which is done using this syntax.

      As a side note, in the 1.2 version, the useful inner classes have been extracted to top-level classes, so you won't need to worry about this .