Skip to content

Commit bad7871

Browse files
rwinchjzheaux
authored andcommitted
Split files
Issue gh-869
1 parent 5950906 commit bad7871

17 files changed

+2900
-2900
lines changed
Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
[[adding-missing-overloaded-api-methods]]
2+
= Adding Missing Overloaded API Methods
3+
4+
This section covers how to add your own overloaded API methods to implement new functionality.
5+
6+
[[implementing-custom-search-methods]]
7+
== Implementing Custom Search Methods
8+
9+
`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.
10+
11+
Suppose you want to call the following `DirContext` method:
12+
13+
====
14+
[source,java]
15+
[subs="verbatim,quotes"]
16+
----
17+
NamingEnumeration search(Name name, String filterExpr, Object[] filterArgs, SearchControls ctls)
18+
----
19+
====
20+
21+
There is no corresponding overloaded method in `LdapTemplate`. The way to solve this is to use a custom `SearchExecutor` implementation, as follows:
22+
23+
====
24+
[source,java]
25+
[subs="verbatim,quotes"]
26+
----
27+
public interface SearchExecutor {
28+
public NamingEnumeration executeSearch(DirContext ctx) throws NamingException;
29+
}
30+
----
31+
====
32+
33+
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:
34+
35+
.A custom search method using `SearchExecutor` and `AttributesMapper`
36+
====
37+
[source,java]
38+
[subs="verbatim,quotes"]
39+
----
40+
package com.example.repo;
41+
42+
public class PersonRepoImpl implements PersonRepo {
43+
...
44+
public List search(final Name base, final String filter, final String[] params,
45+
final SearchControls ctls) {
46+
**SearchExecutor executor = new SearchExecutor() {
47+
public NamingEnumeration executeSearch(DirContext ctx) {
48+
return ctx.search(base, filter, params, ctls);
49+
}
50+
};**
51+
52+
CollectingNameClassPairCallbackHandler handler =
53+
new AttributesMapperCallbackHandler(new PersonAttributesMapper());
54+
55+
ldapTemplate.search(**executor**, handler);
56+
return handler.getList();
57+
}
58+
}
59+
----
60+
====
61+
62+
If you prefer the `ContextMapper` to the `AttributesMapper`, the following example shows what it would look like:
63+
64+
.A custom search method using `SearchExecutor` and `ContextMapper`
65+
====
66+
[source,java]
67+
[subs="verbatim,quotes"]
68+
----
69+
package com.example.repo;
70+
71+
public class PersonRepoImpl implements PersonRepo {
72+
...
73+
public List search(final Name base, final String filter, final String[] params,
74+
final SearchControls ctls) {
75+
SearchExecutor executor = new SearchExecutor() {
76+
public NamingEnumeration executeSearch(DirContext ctx) {
77+
return ctx.search(base, filter, params, ctls);
78+
}
79+
};
80+
81+
CollectingNameClassPairCallbackHandler handler =
82+
**new ContextMapperCallbackHandler(new PersonContextMapper()**);
83+
84+
ldapTemplate.search(executor, handler);
85+
return handler.getList();
86+
}
87+
}
88+
----
89+
====
90+
91+
NOTE: When you use the `ContextMapperCallbackHandler`, you must make sure that you have called `setReturningObjFlag(true)` on your `SearchControls` instance.
92+
93+
[[implementing-other-custom-context-methods]]
94+
== Implementing Other Custom Context Methods
95+
96+
In the same manner as for custom `search` methods, you can actually call any method in `DirContext` by using a `ContextExecutor`, as follows:
97+
98+
====
99+
[source,java]
100+
[subs="verbatim,quotes"]
101+
----
102+
public interface ContextExecutor {
103+
public Object executeWithContext(DirContext ctx) throws NamingException;
104+
}
105+
----
106+
====
107+
108+
When implementing a custom `ContextExecutor`, you can choose between using the `executeReadOnly()` or the `executeReadWrite()` method. Suppose you want to call the following method:
109+
110+
====
111+
[source,java]
112+
[subs="verbatim,quotes"]
113+
----
114+
Object lookupLink(Name name)
115+
----
116+
====
117+
118+
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:
119+
120+
.A custom `DirContext` method using `ContextExecutor`
121+
====
122+
[source,java]
123+
[subs="verbatim,quotes"]
124+
----
125+
package com.example.repo;
126+
127+
public class PersonRepoImpl implements PersonRepo {
128+
...
129+
public Object lookupLink(final Name name) {
130+
ContextExecutor executor = new ContextExecutor() {
131+
public Object executeWithContext(DirContext ctx) {
132+
return ctx.lookupLink(name);
133+
}
134+
};
135+
136+
return ldapTemplate.executeReadOnly(executor);
137+
}
138+
}
139+
----
140+
====
141+
142+
In the same manner, you can perform a read-write operation by using the `executeReadWrite()` method.
143+
144+

0 commit comments

Comments
 (0)