Files
spring-ldap/src/docbkx/executors.xml
2008-10-12 21:34:09 +00:00

148 lines
5.6 KiB
XML

<?xml version="1.0" encoding="UTF-8"?>
<chapter id="executors">
<title>Adding Missing Overloaded API Methods</title>
<sect1 id="executors-search">
<title>Implementing Custom Search Methods</title>
<para>While <literal>LdapTemplate</literal> contains several overloaded
versions of the most common operations in <literal>DirContext</literal>,
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 <literal>DirContext</literal> method you want
and still get the benefits that LdapTemplate provides.</para>
<para>Let's say that you want to call the following <literal>DirContext</literal>
method:</para>
<programlisting>NamingEnumeration search(Name name, String filterExpr, Object[] filterArgs, SearchControls ctls)</programlisting>
<para>There is no corresponding overloaded method in LdapTemplate. The way to solve
this is to use a custom <literal>SearchExecutor</literal> implementation:</para>
<informalexample>
<programlisting>public interface SearchExecutor {
public NamingEnumeration executeSearch(DirContext ctx) throws NamingException;
}</programlisting>
</informalexample>
<para>In your custom executor, you have access to a <literal>DirContext</literal>
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
<literal>CollectingNameClassPairCallbackHandler</literal>, which will collect
the mapped results in an internal list. In order to
actually execute the search, you call the <literal>search</literal>
method in LdapTemplate that takes an executor and a handler as arguments. Finally,
you return whatever your handler has collected.</para>
<example>
<title>A custom search method using SearchExecutor and
AttributesMapper</title>
<programlisting>package com.example.dao;
public class PersonDaoImpl implements PersonDao {
...
public List search(final Name base, final String filter, final String[] params,
final SearchControls ctls) {
<emphasis role="bold">SearchExecutor executor = new SearchExecutor() {
public NamingEnumeration executeSearch(DirContext ctx) {
return ctx.search(base, filter, params, ctls);
}
}</emphasis>;
CollectingNameClassPairCallbackHandler handler =
new AttributesMapperCallbackHandler(new PersonAttributesMapper());
ldapTemplate.search(<emphasis role="bold">executor</emphasis>, handler);
return handler.getList();
}
}</programlisting>
</example>
<para>If you prefer the <literal>ContextMapper</literal> to the
<literal>AttributesMapper</literal>, this is what it would look
like:</para>
<example>
<title>A custom search method using SearchExecutor and
ContextMapper</title>
<programlisting>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 =
<emphasis role="bold">new ContextMapperCallbackHandler(new PersonContextMapper())</emphasis>;
ldapTemplate.search(executor, handler);
return handler.getList();
}
}</programlisting>
</example>
<note>
<para>When using the
<literal>ContextMapperCallbackHandler</literal> you must
make sure that you have called
<literal>setReturningObjFlag(true)</literal> on your
<literal>SearchControls</literal> instance.</para>
</note>
</sect1>
<sect1 id="executors-others">
<title>Implementing Other Custom Context Methods</title>
<para>In the same manner as for custom <literal>search</literal> methods,
you can actually execute any method in <literal>DirContext</literal> by
using a <literal>ContextExecutor</literal>.</para>
<informalexample>
<programlisting>public interface ContextExecutor {
public Object executeWithContext(DirContext ctx) throws NamingException;
}</programlisting>
<para>When implementing a custom <literal>ContextExecutor</literal>, you
can choose between using the <literal>executeReadOnly()</literal> or the
<literal>executeReadWrite()</literal> method. Let's say that we want to
call this method:</para>
</informalexample>
<programlisting>Object lookupLink(Name name)</programlisting>
<para>It's available in <literal>DirContext</literal>, but there is no
matching method in <literal>LdapTemplate</literal>. It's a lookup method,
so it should be read-only. We can implement it like this:</para>
<example>
<title>A custom DirContext method using ContextExecutor</title>
<programlisting>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);
}
}</programlisting>
<para>In the same manner you can execute a read-write operation using
the <literal>executeReadWrite()</literal> method.</para>
</example>
</sect1>
</chapter>