[[adding-missing-overloaded-api-methods]]
= Adding Missing Overloaded API Methods

This section covers how to add your own overloaded API methods to implement new functionality.

[[implementing-custom-search-methods]]
== Implementing Custom Search Methods

`LdapTemplate` contains several overloaded versions of the most common operations in `DirContext`. However, 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.

Suppose you want to call the following `DirContext` method:

====
[source,java]
[subs="verbatim,quotes"]
----
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, as follows:

====
[source,java]
[subs="verbatim,quotes"]
----
public interface SearchExecutor {
   public NamingEnumeration executeSearch(DirContext ctx) throws NamingException;
}
----
====

In your custom executor, you have access to a `DirContext` object, which you can use to call the method you want. You can 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 collects the mapped results in an internal list. In order to actually perform the search, you need to call the `search` method in `LdapTemplate` that takes an executor and a handler as arguments. Finally, you need to return whatever your handler has collected. The following example shows how to do all of that:

.A custom search method using `SearchExecutor` and `AttributesMapper`
====
[source,java]
[subs="verbatim,quotes"]
----
package com.example.repo;

public class PersonRepoImpl implements PersonRepo {
   ...
   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`, the following example shows what it would look like:

.A custom search method using `SearchExecutor` and `ContextMapper`
====
[source,java]
[subs="verbatim,quotes"]
----
package com.example.repo;

public class PersonRepoImpl implements PersonRepo {
   ...
   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 you use the `ContextMapperCallbackHandler`, you must make sure that you have called `setReturningObjFlag(true)` on your `SearchControls` instance.

[[implementing-other-custom-context-methods]]
== Implementing Other Custom Context Methods

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

====
[source,java]
[subs="verbatim,quotes"]
----
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. Suppose you want to call the following method:

====
[source,java]
[subs="verbatim,quotes"]
----
Object lookupLink(Name name)
----
====

The method is available in `DirContext`, but there is no matching method in `LdapTemplate`. It is a lookup method, so it should be read-only. We can implement it as follows:

.A custom `DirContext` method using `ContextExecutor`
====
[source,java]
[subs="verbatim,quotes"]
----
package com.example.repo;

public class PersonRepoImpl implements PersonRepo {
   ...
   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 perform a read-write operation by using the `executeReadWrite()` method.


