145 lines
4.9 KiB
Plaintext
145 lines
4.9 KiB
Plaintext
[[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.
|
|
|
|
|