278 lines
13 KiB
Plaintext
278 lines
13 KiB
Plaintext
<!--
|
|
|
|
Copyright 2000-2007 Sun Microsystems, Inc. All Rights Reserved.
|
|
Portions copyright 1999 Netscape Communications Corporation. All
|
|
Rights Reserved.
|
|
|
|
The contents of this document are subject to the terms of the
|
|
Creative Commons Attribution-ShareAlike 2.5 license or any later
|
|
version (the "License"). You may not use this document except in
|
|
compliance with the License.
|
|
|
|
See the License for the specific language governing
|
|
permissions and limitations under the License. You can obtain
|
|
a copy of the License at
|
|
http://creativecommons.org/licenses/by-sa/2.5/legalcode.
|
|
|
|
-->
|
|
<chapter id="asynchronous"><title>Writing Asynchronous Clients With &DirectorySDKForJava;</title>
|
|
<highlights>
|
|
<para>This chapter shows how to use the asynchronous interface to LDAP in
|
|
Java applications.</para>
|
|
<itemizedlist>
|
|
<para>This chapter covers the following topics:</para>
|
|
<listitem><para><olink targetptr="async-vs-sync">Synchronous and Asynchronous Connections With Directory SDK for Java</olink></para></listitem>
|
|
<listitem><para><olink targetptr="async-using">Common Uses for the Asynchronous Interface With Directory SDK for Java</olink></para></listitem>
|
|
<listitem><para><olink targetptr="async-new">Classes in the Asynchronous Interface for Directory SDK for Java</olink></para></listitem>
|
|
<listitem><para><olink targetptr="async-search">Performing Asynchronous Searches With Directory SDK for Java</olink></para>
|
|
</listitem>
|
|
<listitem><para><olink targetptr="async-further">Further Reading About the Asynchronous Interface for Directory SDK for Java</olink></para></listitem>
|
|
</itemizedlist>
|
|
</highlights>
|
|
<sect1 id="async-vs-sync"><title>Synchronous and Asynchronous Connections
|
|
With Directory SDK for Java</title>
|
|
<indexterm>
|
|
<primary>asynchronous interface</primary>
|
|
<secondary>explained</secondary>
|
|
</indexterm><indexterm>
|
|
<primary>synchronous interface</primary>
|
|
<secondary>explained</secondary>
|
|
</indexterm>
|
|
<para>Most operations with &DirectorySDKForJava; are performed synchronously.
|
|
A connection is established, a request is sent, the results are returned.
|
|
Then the application resumes. Though the &DirectorySDKForJava; can deliver
|
|
one search result at a time, other operations block until completion when
|
|
accessing an LDAP server.</para>
|
|
<para>Sometimes, initiating a new request while another request executes can
|
|
be useful. An additional interface is provided to access the built-in support
|
|
in &DirectorySDKForJava; for these asynchronous requests. By returning
|
|
control to an application before obtaining a response, the asynchronous interface
|
|
allows you to perform complex operations requiring access to low-level LDAP
|
|
mechanisms.</para>
|
|
<para><classname>LDAPConnection</classname> methods support both asynchronous
|
|
requests and synchronous requests. Synchronous methods wait for response messages
|
|
from a server and then process the responses for you. Asynchronous methods
|
|
require that you check for the messages. You then perform the processing in
|
|
your code. This mechanism allows you to make additional LDAP requests while
|
|
waiting for results to return.</para></sect1>
|
|
<sect1 id="async-using"><title>Common Uses for the Asynchronous Interface
|
|
With Directory SDK for Java</title>
|
|
<indexterm>
|
|
<primary>asynchronous interface</primary>
|
|
<secondary>common uses</secondary>
|
|
</indexterm>
|
|
<para>Since using the asynchronous interface involves managing more complex
|
|
code in an application, use the asynchronous methods only when required. The
|
|
most common use is for merging the results of searches that involve multiple
|
|
servers or that are executed simultaneously on different subtrees. This method
|
|
is sometimes referred to as <firstterm>multiplexing</firstterm>.</para>
|
|
<para>A search that multiplexes servers can make a request to an array of
|
|
hosts. A search that multiplexes query statements can make different requests
|
|
to different subtrees of a server. If you combine these search methods, you
|
|
can perform complex searches across a number of servers without having to
|
|
wait for individual responses.</para>
|
|
<para>The following example illustrates a practical use of multiplexed searches
|
|
and the asynchronous interface.</para>
|
|
<para>Suppose event notification must be implemented as a generic service
|
|
with LDAP persistent search. Synchronous methods require a new thread for
|
|
every request to the service. This solution is not scalable and can exhaust
|
|
system resources very quickly.</para>
|
|
<para>After the search is rewritten using the asynchronous interface, performance
|
|
improves dramatically. Since asynchronous searches do not block until completion,
|
|
the persistent search results can be multiplexed into one queue and then processed
|
|
on a single thread.</para></sect1>
|
|
<sect1 id="async-new"><title>Classes in the Asynchronous Interface for Directory
|
|
SDK for Java</title>
|
|
<indexterm>
|
|
<primary>asynchronous interface</primary>
|
|
<secondary>classes</secondary>
|
|
</indexterm>
|
|
<para>&DirectorySDKForJava; handles asynchronous communication through
|
|
the <classname>LDAPAsynchronousConnection</classname> interface and its dependent
|
|
classes. These files collectively form the asynchronous extensions to the
|
|
LDAP API.</para>
|
|
<para><classname>LDAPAsynchronousConnection</classname> defines methods for
|
|
authenticating to a server, as well as for searching, modifying, comparing,
|
|
and deleting entries in the directory.</para>
|
|
<para>When you call a method of <classname>LDAPAsynchronousConnection</classname>,
|
|
the method returns a listener object. This object acts as a message queue.
|
|
The object accepts search results and server-generated responses to LDAP requests.
|
|
The LDAP client has the responsibility to read and process these messages.</para>
|
|
<itemizedlist>
|
|
<para><classname>LDAPAsynchronousConnection</classname> incorporates the following
|
|
classes for handling asynchronous client-server interactions:</para>
|
|
<listitem><para><classname>LDAPMessage</classname>, which is the base class
|
|
for LDAP request and response messages.</para></listitem>
|
|
<listitem><para><classname>LDAPResponse</classname>, which extends <classname>LDAPMessage
|
|
</classname>, represents a message received from an LDAP server in response
|
|
to a request.</para></listitem>
|
|
<listitem><para><classname>LDAPExtendedResponse</classname>, which extends <classname>
|
|
LDAPResponse</classname>. This response is the response that an LDAP server
|
|
returns when handling an extended operation request.</para></listitem>
|
|
<listitem><para><classname>LDAPResponseListener</classname> queues <classname>LDAPResponse
|
|
</classname> messages.</para></listitem>
|
|
<listitem><para><classname>LDAPSearchResult</classname>, which extends <classname>
|
|
LDAPMessage</classname>. The response contains a single LDAP entry. The response
|
|
is one of the responses an LDAP server can return when handling a search request.
|
|
</para></listitem>
|
|
<listitem><para><classname>LDAPSearchResultReference</classname>, which extends <classname>
|
|
LDAPMessage</classname>. The response contains a referral. The response is
|
|
one of the responses that an LDAP server can return when handling a search
|
|
request.</para></listitem>
|
|
<listitem><para><classname>LDAPSearchListener</classname> queues search results
|
|
and references.</para></listitem>
|
|
</itemizedlist>
|
|
</sect1>
|
|
<sect1 id="async-search"><title>Performing Asynchronous Searches With Directory
|
|
SDK for Java</title>
|
|
<para>One of the most common uses of the asynchronous interface is for performing
|
|
multiplexed searches using more than one server or suffix.</para>
|
|
<task id="async-search-mult-servers"><title>To Search Across Multiple Servers</title>
|
|
<indexterm>
|
|
<primary>asynchronous interface</primary>
|
|
<secondary>search multiple servers</secondary>
|
|
</indexterm>
|
|
<tasksummary>
|
|
<para>To search on more than one server, perform the following steps.</para>
|
|
</tasksummary>
|
|
<procedure>
|
|
<step><para>Connect to all the servers.</para></step>
|
|
<step><para>Create a response listener for one search.</para></step>
|
|
<step><para>Share the response listener with all the other searches.</para>
|
|
</step>
|
|
<step><para>Obtain and process the results.</para></step>
|
|
<step><para>Disconnect from the servers.</para></step>
|
|
</procedure>
|
|
<example id="async-search-mult-servers-example">
|
|
<title>Searching Across Multiple Servers</title>
|
|
<para>This example demonstrates how to search on two servers at the same time.</para>
|
|
<programlisting>import netscape.ldap.*;
|
|
import java.util.*;
|
|
|
|
public class MultiplexServers {
|
|
public static void main(String[] args) {
|
|
try {
|
|
LDAPConnection[] ld = new LDAPConnection[2];
|
|
String[] hosts = {"server1", "server2"};
|
|
int[] ports = {389, 389};
|
|
String[] bases = {"dc=example,dc=com", "dc=example,dc=com"};
|
|
|
|
/* search for all entries with surname of Jensen */
|
|
String MY_FILTER = "(sn=Jensen)";
|
|
for (int i = 0; i < ld.length; i++) {
|
|
ld[i] = new LDAPConnection();
|
|
ld[i].connect(hosts[i], ports[i]);
|
|
}
|
|
/* Get a response listener for one search */
|
|
LDAPSearchListener l = ld[0].search(bases[0], ld[0].SCOPE_SUB,
|
|
MY_FILTER, null, false, (LDAPSearchListener)null);
|
|
/* Share the listener */
|
|
for (int i = 1; i < ld.length; i++) {
|
|
ld[i].search(bases[i], ld[i].SCOPE_SUB,
|
|
MY_FILTER, null, false, l);
|
|
}
|
|
|
|
/* Loop on results until finished */
|
|
LDAPMessage msg;
|
|
while ((msg = l.getResponse()) != null) {
|
|
if (msg instanceof LDAPSearchResultReference) {
|
|
; // Ignore referrals
|
|
} else if (msg instanceof LDAPSearchResult) {
|
|
LDAPEntry entry = ((LDAPSearchResult)msg).getEntry();
|
|
System.out.println("Found entry: " + entry.getDN());
|
|
} else if (msg instanceof LDAPResponse) {
|
|
int result = ((LDAPResponse)msg).getResultCode();
|
|
if (result != 0) {
|
|
System.out.println("Result code: " + result);
|
|
System.out.println("Error message: " +
|
|
((LDAPResponse)msg).getErrorMessage());
|
|
}
|
|
}
|
|
}
|
|
for (int i = 0; i < ld.length; i++) {
|
|
ld[i].disconnect();
|
|
}
|
|
} catch (LDAPException e) {
|
|
System.err.println(e.toString());
|
|
}
|
|
}
|
|
}</programlisting>
|
|
</example>
|
|
</task>
|
|
<task id="async-search-mult-suffixes"><title>To Search Across Multiple Suffixes
|
|
on a Single Server</title>
|
|
<indexterm>
|
|
<primary>asynchronous interface</primary>
|
|
<secondary>search multiple suffixes</secondary>
|
|
</indexterm>
|
|
<tasksummary>
|
|
<para>To search on more than one suffix, perform the following steps.</para>
|
|
</tasksummary>
|
|
<procedure>
|
|
<step><para>Connect to the server.</para></step>
|
|
<step><para>Create a response listener for one search.</para></step>
|
|
<step><para>Share (multiplex) the response listener with the other searches.</para>
|
|
</step>
|
|
<step><para>Obtain and process the results.</para></step>
|
|
<step><para>Disconnect from the server.</para></step>
|
|
</procedure>
|
|
<example id="async-search-mult-suffixes-example">
|
|
<title>Searching Across Multiple Suffixes</title>
|
|
<para>This example demonstrates how to search across two suffixes at the same
|
|
time.</para>
|
|
<programlisting>import netscape.ldap.*;
|
|
import java.util.*;
|
|
|
|
public class MultiplexSuffixes {
|
|
public static void main(String[] args) {
|
|
try {
|
|
UserArgs userArgs =
|
|
new UserArgs("MultipleSuffixes", args, false);
|
|
LDAPConnection ld = new LDAPConnection();
|
|
ld.connect(userArgs.getHost(), userArgs.getPort());
|
|
|
|
String[] bases = {"dc=example,dc=com",
|
|
"ou=groups,dc=example,dc=com"};
|
|
String MY_FILTER = "(objectclass=*)";
|
|
|
|
/* Get a response listener for one search */
|
|
LDAPSearchListener l = ld.search(bases[0], ld.SCOPE_ONE,
|
|
MY_FILTER, null, false, (LDAPSearchListener)null);
|
|
/* Share the listener */
|
|
for (int i = 1; i < bases.length; i++) {
|
|
ld.search(bases[i], ld.SCOPE_ONE,
|
|
MY_FILTER, null, false, l);
|
|
}
|
|
|
|
/* Loop on results until finished */
|
|
LDAPMessage msg;
|
|
while ((msg = l.getResponse()) != null) {
|
|
if (msg instanceof LDAPSearchResultReference) {
|
|
; // Ignore referrals
|
|
} else if (msg instanceof LDAPSearchResult) {
|
|
LDAPEntry entry = ((LDAPSearchResult)msg).getEntry();
|
|
System.out.println("Found entry: " + entry.getDN());
|
|
} else if (msg instanceof LDAPResponse) {
|
|
int result = ((LDAPResponse)msg).getResultCode();
|
|
if (result != 0) {
|
|
System.out.println("Result code: " + result);
|
|
System.out.println("Error message: " +
|
|
((LDAPResponse)msg).getErrorMessage());
|
|
}
|
|
}
|
|
}
|
|
ld.disconnect();
|
|
} catch (LDAPException e) {
|
|
System.err.println(e.toString());
|
|
}
|
|
}
|
|
}</programlisting>
|
|
</example>
|
|
</task>
|
|
</sect1>
|
|
<sect1 id="async-further"><title>Further Reading About the Asynchronous Interface
|
|
for Directory SDK for Java</title>
|
|
<para>The asynchronous interface is defined in an Internet Draft, <citetitle>The
|
|
Java LDAP Application Programming Interface</citetitle>.</para></sect1>
|
|
</chapter>
|