Chapter 4. Adding Missing Overloaded API Methods

Table of Contents

Implementing Custom Search Methods
Implementing Other Custom Context Methods

Implementing Custom Search Methods

While LdapTemplate contains several overloaded versions of the most common operations in DirContext, we have not provided an alternative for each and every method signature, mostly because there are so many of them. We have, however, provided a means to call whichever DirContext method you want and still get the benefits that LdapTemplate provides.

Let's say that you want to call the following DirContext method:

NamingEnumeration search(Name name, String filterExpr, Object[] filterArgs, SearchControls ctls)

There is no corresponding overloaded method in LdapTemplate. The way to solve this is to use a custom SearchExecutor implementation:

public interface SearchExecutor {
   public NamingEnumeration executeSearch(DirContext ctx) throws NamingException;
}

In your custom executor, you have access to a DirContext object, which you use to call the method you want. You then provide a handler that is responsible for mapping attributes and collecting the results. You can for example use one of the available implementations of CollectingNameClassPairCallbackHandler, which will collect the mapped results in an internal list. In order to actually execute the search, you call the search method in LdapTemplate that takes an executor and a handler as arguments. Finally, you return whatever your handler has collected.

Example 4.1. A custom search method using SearchExecutor and AttributesMapper

package com.example.dao;

public class PersonDaoImpl implements PersonDao {
   ...
   public List search(final Name base, final String filter, final String[] params,
         final SearchControls ctls) {
      SearchExecutor executor = new SearchExecutor() {
         public NamingEnumeration executeSearch(DirContext ctx) {
            return ctx.search(base, filter, params, ctls);
         }
      };

      CollectingNameClassPairCallbackHandler handler =
         new AttributesMapperCallbackHandler(new PersonAttributesMapper());

      ldapTemplate.search(executor, handler);
      return handler.getList();
   }
}

If you prefer the ContextMapper to the AttributesMapper, this is what it would look like:

Example 4.2. A custom search method using SearchExecutor and ContextMapper

package com.example.dao;

public class PersonDaoImpl implements PersonDao {
   ...
   public List search(final Name base, final String filter, final String[] params,
         final SearchControls ctls) {
      SearchExecutor executor = new SearchExecutor() {
         public NamingEnumeration executeSearch(DirContext ctx) {
            return ctx.search(base, filter, params, ctls);
         }
      };

      CollectingNameClassPairCallbackHandler handler =
         new ContextMapperCallbackHandler(new PersonContextMapper());

      ldapTemplate.search(executor, handler);
      return handler.getList();
   }
}

Note

When using the ContextMapperCallbackHandler you must make sure that you have called setReturningObjFlag(true) on your SearchControls instance.