Files
spring-ldap/modules/ROOT/pages/adding-missing-overloaded-api-methods.adoc
2023-07-13 08:55:35 -06:00

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.