# Adding Missing Overloaded API 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.

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:

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();
       }
    }

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

## Implementing Other Custom Context Methods

In the same manner as for custom `search` methods, you can actually execute any method in `DirContext` by using a `ContextExecutor`.

    public interface ContextExecutor {
       public Object executeWithContext(DirContext ctx) throws NamingException;
    }

When implementing a custom `ContextExecutor`, you can choose between using the `executeReadOnly()` or the `executeReadWrite()` method. Let's say that we want to call this method:

    Object lookupLink(Name name)

It's available in `DirContext`, but there is no matching method in `LdapTemplate`. It's a lookup method, so it should be read-only. We can implement it like this:

A custom DirContext method using ContextExecutor

    package com.example.dao;

    public class PersonDaoImpl implements PersonDao {
       ...
       public Object lookupLink(final Name name) {
          ContextExecutor executor = new ContextExecutor() {
             public Object executeWithContext(DirContext ctx) {
                return ctx.lookupLink(name);
             }
          };

          return ldapTemplate.executeReadOnly(executor);
       }
    }

In the same manner you can execute a read-write operation using the `executeReadWrite()` method.