mirror of https://github.com/OpenIdentityPlatform/OpenDJ.git

Mark Craig
22.39.2014 fb92e5b8094578acedae48a662612cc73df9d652
CR-4930 OPENDJ-1538 Update dev guide for switch from Futures to Promises
1 files deleted
1 files added
8 files modified
480 ■■■■ changed files
opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/Proxy.java 3 ●●●● patch | view | raw | blame | history
opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/SearchAsync.java 102 ●●●●● patch | view | raw | blame | history
src/main/docbkx/dev-guide/chap-extended-ops.xml 22 ●●●● patch | view | raw | blame | history
src/main/docbkx/dev-guide/chap-get-sdk.xml 61 ●●●● patch | view | raw | blame | history
src/main/docbkx/dev-guide/chap-simple-proxy.xml 27 ●●●●● patch | view | raw | blame | history
src/main/docbkx/dev-guide/chap-using-the-sdk.xml 136 ●●●●● patch | view | raw | blame | history
src/main/docbkx/sdk-release-notes/chap-get-sdk.xml 8 ●●●● patch | view | raw | blame | history
src/main/docbkx/sdk-release-notes/chap-whats-new.xml 21 ●●●●● patch | view | raw | blame | history
src/main/docbkx/sdk-release-notes/resources/maven-xml.txt 33 ●●●●● patch | view | raw | blame | history
src/main/docbkx/shared/programlisting-get-sdk.xml 67 ●●●●● patch | view | raw | blame | history
opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/Proxy.java
@@ -122,7 +122,8 @@
        final RequestHandlerFactory<LDAPClientContext, RequestContext> proxyFactory =
                new RequestHandlerFactory<LDAPClientContext, RequestContext>() {
                    @Override
                    public ProxyBackend handleAccept(LDAPClientContext clientContext) throws LdapException {
                    public ProxyBackend handleAccept(LDAPClientContext clientContext)
                            throws LdapException {
                        return new ProxyBackend(factory, bindFactory);
                    }
                };
opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/SearchAsync.java
@@ -71,21 +71,26 @@
                    WRITER.writeEntry(entry);
                    ++entryCount;
                } else { // Cancel the search.
                    CancelExtendedRequest request = Requests.newCancelExtendedRequest(requestID);
                    connection.extendedRequestAsync(request).onSuccess(new SuccessHandler<ExtendedResult>() {
                        @Override
                        public void handleResult(ExtendedResult result) {
                            System.err.println("Cancel request succeeded");
                            CANCEL_LATCH.countDown();
                        }
                    }).onFailure(new FailureHandler<LdapException>() {
                        @Override
                        public void handleError(LdapException error) {
                            System.err.println("Cancel request failed with result code: "
                                    + error.getResult().getResultCode().intValue());
                            CANCEL_LATCH.countDown();
                        }
                    });
                    CancelExtendedRequest request =
                            Requests.newCancelExtendedRequest(requestID);
                    connection.extendedRequestAsync(request)
                            .onSuccess(new SuccessHandler<ExtendedResult>() {
                                @Override
                                public void handleResult(ExtendedResult result) {
                                    System.err.println("Cancel request succeeded");
                                    CANCEL_LATCH.countDown();
                                }
                            })
                            .onFailure(new FailureHandler<LdapException>() {
                                @Override
                                public void handleError(LdapException error) {
                                    System.err.println("Cancel request failed: "
                                            + error.getResult().getResultCode().intValue()
                                            + " "
                                            + error.getResult().getDiagnosticMessage());
                                    CANCEL_LATCH.countDown();
                                }
                            });
                    return false;
                }
            } catch (final IOException e) {
@@ -112,7 +117,6 @@
        }
    }
    // --- JCite search result handler ---
    // --- JCite decl1 ---
@@ -176,37 +180,47 @@
            return;
        }
        // --- Using Promises ---
        // Initiate the asynchronous connect, bind, and search.
        final LDAPConnectionFactory factory = new LDAPConnectionFactory(hostName, port);
        factory.getConnectionAsync().thenAsync(new AsyncFunction<Connection, BindResult, LdapException>() {
            @Override
            public Promise<BindResult, LdapException> apply(Connection connection) throws LdapException {
                SearchAsync.connection = connection;
                return connection.bindAsync(Requests.newSimpleBindRequest(userName, password.toCharArray()));
            }
        }).thenAsync(new AsyncFunction<BindResult, Result, LdapException>() {
            @Override
            public Promise<Result, LdapException> apply(BindResult result) throws LdapException {
                LdapPromise<Result> promise = connection.searchAsync(
                        Requests.newSearchRequest(baseDN, scope, filter, attributes), new SearchResultHandlerImpl());
                requestID = promise.getRequestID();
                return promise;
            }
        }).onSuccess(new SuccessHandler<Result>() {
            @Override
            public void handleResult(Result result) {
                resultCode = result.getResultCode().intValue();
                COMPLETION_LATCH.countDown();
            }
        }).onFailure(new FailureHandler<LdapException>() {
            @Override
            public void handleError(LdapException error) {
                System.err.println(error.getMessage());
                resultCode = error.getResult().getResultCode().intValue();
                COMPLETION_LATCH.countDown();
            }
        });
        factory.getConnectionAsync()
                .thenAsync(new AsyncFunction<Connection, BindResult, LdapException>() {
                    @Override
                    public Promise<BindResult, LdapException> apply(Connection connection)
                            throws LdapException {
                        SearchAsync.connection = connection;
                        return connection.bindAsync(Requests
                                .newSimpleBindRequest(userName, password.toCharArray()));
                    }
                })
                .thenAsync(new AsyncFunction<BindResult, Result, LdapException>() {
                    @Override
                    public Promise<Result, LdapException> apply(BindResult result)
                            throws LdapException {
                        LdapPromise<Result> promise = connection.searchAsync(
                                Requests.newSearchRequest(baseDN, scope, filter, attributes),
                                new SearchResultHandlerImpl());
                        requestID = promise.getRequestID();
                        return promise;
                    }
                })
                .onSuccess(new SuccessHandler<Result>() {
                    @Override
                    public void handleResult(Result result) {
                        resultCode = result.getResultCode().intValue();
                        COMPLETION_LATCH.countDown();
                    }
                })
                .onFailure(new FailureHandler<LdapException>() {
                    @Override
                    public void handleError(LdapException error) {
                        System.err.println(error.getMessage());
                        resultCode = error.getResult().getResultCode().intValue();
                        COMPLETION_LATCH.countDown();
                    }
                });
        // --- Using Promises ---
        // Await completion.
        try {
src/main/docbkx/dev-guide/chap-extended-ops.xml
@@ -117,9 +117,17 @@
  already finished processing the original request before it receives your
  Cancel request.</para>
  <para>You can add a Cancel extended request for example to stop handling
  entries returned from a search if the directory server returns more entries
  than you want.</para>
  <para>
   You can add a Cancel extended request for example
   to stop handling entries returned from a search
   if the directory server returns more entries than you want.
   In the following example, the search result handler implementation
   is passed to a <literal>searchAsync()</literal> method on the connection.
   When the entry count reaches 10, the example requests
   that the directory server cancel the search.
   Notice that the extended request is also asynchronous,
   handled using promises to deal with both success and also error conditions.
  </para>
  <programlisting language="java"
  >[jcp:org.forgerock.opendj.examples.SearchAsync:--- JCite decl1 ---]</programlisting>
@@ -130,14 +138,6 @@
  <programlisting language="java"
  >[jcp:org.forgerock.opendj.examples.SearchAsync:--- JCite search result handler ---]</programlisting>
  <!-- FixMe workaround pending OPENDJ-1538: Update dev guide for change from Futures to Promises
  <programlisting language="java"
  >jcp:org.forgerock.opendj.examples.SearchAsync:- - - JCite cancel result handler - - -]</programlisting>
  -->
  <programlisting>
   Coming soon... pending OPENDJ-1538: Update dev guide for change from Futures to Promises
  </programlisting>
  <para>OpenDJ directory server supports the cancel operation. If OpenDJ
  directory server manages to return all entries in
  <filename>Example.ldif</filename> before it receives the Cancel extended
src/main/docbkx/dev-guide/chap-get-sdk.xml
@@ -28,7 +28,8 @@
 xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
 xsi:schemaLocation='http://docbook.org/ns/docbook
                     http://docbook.org/xml/5.0/xsd/docbook.xsd'
 xmlns:xlink='http://www.w3.org/1999/xlink'>
 xmlns:xlink='http://www.w3.org/1999/xlink'
 xmlns:xinclude='http://www.w3.org/2001/XInclude'>
 <title>Getting OpenDJ LDAP SDK</title>
 <para>This chapter introduces OpenDJ LDAP SDK, demonstrating how to get the
@@ -96,43 +97,12 @@
   <para>Let that expensive computer you bought do the work.</para>
   <step>
    <para>Include the ForgeRock repository in your list, and include the SDK
    as a dependency.</para>
    <para>
     Include the ForgeRock repository in your list,
     and include SDK and SLF4J dependencies.
    </para>
    <programlisting language="xml">&lt;repositories&gt;
  &lt;repository&gt;
    &lt;id&gt;forgerock-staging-repository&lt;/id&gt;
    &lt;name&gt;ForgeRock Release Repository&lt;/name&gt;
    &lt;url&gt;${mavenRepoReleases}&lt;/url&gt;
    &lt;snapshots&gt;
      &lt;enabled&gt;false&lt;/enabled&gt;
    &lt;/snapshots&gt;
  &lt;/repository&gt;
  &lt;repository&gt;
    &lt;id&gt;forgerock-snapshots-repository&lt;/id&gt;
    &lt;name&gt;ForgeRock Snapshot Repository&lt;/name&gt;
    &lt;url&gt;${mavenRepoSnapshots}&lt;/url&gt;
    &lt;releases&gt;
      &lt;enabled&gt;false&lt;/enabled&gt;
    &lt;/releases&gt;
  &lt;/repository&gt;
&lt;/repositories&gt;
...
&lt;dependencies&gt;
  &lt;dependency&gt;
    &lt;groupId&gt;${project.groupId}&lt;/groupId&gt;
    &lt;artifactId&gt;opendj-core&lt;/artifactId&gt;
    &lt;version&gt;<?eval ${docTargetVersion}?>&lt;/version&gt;
  &lt;/dependency&gt;
  &lt;dependency&gt;
    &lt;groupId&gt;${project.groupId}&lt;/groupId&gt;
    &lt;artifactId&gt;opendj-grizzly&lt;/artifactId&gt;
    &lt;version&gt;<?eval ${docTargetVersion}?>&lt;/version&gt;
  &lt;/dependency&gt;
&lt;/dependencies&gt;
    </programlisting>
    <xinclude:include href="../shared/programlisting-get-sdk.xml" />
   </step>
  </procedure>
@@ -195,23 +165,6 @@
    <screen>
$ <userinput>cd opendj/</userinput>
$ <userinput>mvn install</userinput>
<computeroutput>[INFO] Scanning for projects...
[INFO] ------------------------------------------------------------------------
[INFO] Reactor Build Order:
[INFO]
[INFO] OpenDJ Directory Services Project
[INFO] OpenDJ Core APIs
[INFO] OpenDJ Grizzly Transport Provider
[INFO] OpenDJ SDK
[INFO] OpenDJ SDK Toolkit
       ...
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 2:51.315s
[INFO] Finished at: Wed Apr 10 14:28:36 CEST 2013
[INFO] Final Memory: 37M/382M
[INFO] ------------------------------------------------------------------------</computeroutput>
    </screen>
   </step>
   <step>
src/main/docbkx/dev-guide/chap-simple-proxy.xml
@@ -160,20 +160,27 @@
  <programlisting language="java"
  >[jcp:org.forgerock.opendj.examples.Proxy:--- JCite listener ---]</programlisting>
  <para>You get a <literal>ServerConnectionFactory</literal> to handle requests
  coming from clients. The <literal>ServerConnectionFactory</literal> takes a
  request handler that deals with the incoming client requests. The request
  handler implements handlers for all supported operations. The Proxy example
  implements a <literal>ProxyBackend</literal> to handle requests. The
  <literal>ProxyBackend</literal> sends the requests on to the backend
  directory servers and routes the results returned back to client
  applications.</para>
  <para>
   The connection handler is a <literal>ServerConnectionFactory</literal>
   to handle requests coming from clients.
   The factory takes a request handler implementation
   that deals with all supported incoming client requests.
   The Proxy example uses a <literal>ProxyBackend</literal> to handle requests.
   The <literal>ProxyBackend</literal> sends the requests on
   to the backend directory servers
   and routes the results returned back to client applications.
  </para>
  <programlisting language="java"
  >[jcp:org.forgerock.opendj.examples.Proxy:--- JCite backend ---]</programlisting>
  <para>See the Proxy example code for details about the
  <literal>ProxyBackend</literal> implementation.</para>
  <para>
   For details about the <literal>ProxyBackend</literal> implementation, see
   <link
    xlink:href="http://opendj.forgerock.org/opendj-ldap-sdk-examples/xref/org/forgerock/opendj/examples/ProxyBackend.html"
    xlink:show="new"
   >ProxyBackend.java</link>.
  </para>
 </section>
 <section xml:id="dn-attr-rewriting">
src/main/docbkx/dev-guide/chap-using-the-sdk.xml
@@ -20,15 +20,15 @@
  !
  ! CCPL HEADER END
  !
  !      Copyright 2011-2013 ForgeRock AS
  !      Copyright 2011-2014 ForgeRock AS
  !    
-->
<chapter xml:id='chap-using-the-sdk'
 xmlns='http://docbook.org/ns/docbook' version='5.0' xml:lang='en'
 xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
 xsi:schemaLocation='http://docbook.org/ns/docbook http://docbook.org/xml/5.0/xsd/docbook.xsd'
 xmlns:xlink='http://www.w3.org/1999/xlink'
 xmlns:xinclude='http://www.w3.org/2001/XInclude'>
         xmlns='http://docbook.org/ns/docbook' version='5.0' xml:lang='en'
         xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
         xsi:schemaLocation='http://docbook.org/ns/docbook
                             http://docbook.org/xml/5.0/xsd/docbook.xsd'
         xmlns:xlink='http://www.w3.org/1999/xlink'>
 <title>Using the LDAP SDK</title>
 <para>As LDAP relies on a connection from the client to the directory server,
@@ -54,25 +54,8 @@
  the connection. When finished, your application closes the connection.</para>
  <programlisting language="java">
final LDAPConnectionFactory factory = new LDAPConnectionFactory(host, port);
Connection connection = null;
try {
    connection = factory.getConnection();
    // Perform operations on the connection, such as connection.bind(),
    // connection.search(), connection.modify(), etc.
    } catch (final ErrorResultException e) {
        System.err.println(e.getMessage());
        System.exit(e.getResult().getResultCode().intValue());
        return;
    } finally {
        if (connection != null) {
            connection.close();
        }
    }
</programlisting>
[jcp:org.forgerock.opendj.examples.Search:--- JCite ---]
  </programlisting>
  <para>For a complete example in context, see <link
  xlink:href="http://opendj.forgerock.org/opendj-ldap-sdk-examples/xref/org/forgerock/opendj/examples/Search.html"
@@ -80,52 +63,38 @@
  xlink:href="http://opendj.forgerock.org/opendj-ldap-sdk-examples/"
  xlink:show="new">OpenDJ LDAP SDK examples</link>.</para>
  <para>For asynchronous operations, your application passes a result handler
  to <literal>LDAPConnectionFactory.getConnectionAsync()</literal> that
  implements the <literal>ResultHandler&lt;Connection&gt;</literal>
  interface.</para>
  <para>
   For asynchronous operations,
   your application obtains a connection with
   <literal>LDAPConnectionFactory.getConnectionAsync()</literal>,
   and then uses promises to handle the bind, the subsequent operations,
   the results, and any errors in asynchronous fashion.
  </para>
  <programlisting language="java">
private static final class ConnectResultHandlerImpl
        implements ResultHandler&lt;Connection&gt; {
    @Override
    public void handleErrorResult(final ErrorResultException error) {
        ...
    }
[jcp:org.forgerock.opendj.examples.SearchAsync: --- Using Promises ---]
  </programlisting>
    @Override
    public void handleResult(final Connection connection) {
        // Connect succeeded: save connection and initiate bind.
        SearchAsync.connection = connection;
  <para>
   When the factory gets a connection,
   your application passes an <literal>AsyncFunction</literal>
   to apply to the connection to handle the bind
   by using the <literal>thenAsync()</literal> method in the fluent style.
   Your application uses <literal>thenAsync()</literal> again
   to pass another <literal>AsyncFunction</literal> to perform the operation.
   In the sample shown here, the second call to <literal>thenAsync()</literal>
   passes a function that performs a search, passing in a handler
   to deal with the search results returned by the directory server.
   The call to <literal>onSuccess()</literal> handles the final result,
   with the call to <literal>onFailure()</literal> dealing with exceptions.
  </para>
        final BindRequest request =
                Requests.newSimpleBindRequest(userName, password.toCharArray());
        connection.bindAsync(request, null, new BindResultHandlerImpl());
    }
}
// Main method initiates async operations by getting a connection...
final LDAPConnectionFactory factory = new LDAPConnectionFactory(hostName, port);
factory.getConnectionAsync(new ConnectResultHandlerImpl());
...
if (connection != null) {
    connection.close();
}
</programlisting>
  <para>When the connection result handler gets a connection, your application
  can pass result handlers for other operations using methods on the connection
  named <literal>*Async()</literal>. For most operations, your application
  implements <literal>ResultHandler</literal>. For searches, your application
  implements <literal>SearchResultHandler</literal>. The result handler is
  notified upon completion of the operation.</para>
  <para>Asynchronous methods are non-blocking, returning a
  <literal>FutureResult</literal> whose <literal>get()</literal> method lets
  you retrieve the result. Your application must coordinate concurrency when
  you use asynchronous operations.</para>
  <para>
   Asynchronous methods are non-blocking, returning a <literal>Promise</literal>,
   so that you can chain methods in the fluent style.
   Your application must coordinate concurrency
   when you use asynchronous operations.
  </para>
  <para>For a complete example in context, see <link
  xlink:href="http://opendj.forgerock.org/opendj-ldap-sdk-examples/xref/org/forgerock/opendj/examples/SearchAsync.html"
@@ -145,12 +114,14 @@
  other than success. The <literal>ResultCode</literal> class encapsulates the
  LDAP codes and additional client-side codes specific to the SDK.</para>
  <para>Your application deals with most non-success result codes when it
  catches one of the LDAP SDK exceptions corresponding to the operation you
  requested. <literal>ErrorResultException</literal> is a common way for the
  SDK to indicate a non-successful result. Your application can then take
  remedial action based on the result code, as in the following synchronous
  excerpt.</para>
  <para>
   Your application deals with most non-success result codes
   by catching <literal>LdapException</literal> objects
   or handling them when supplied to <literal>FailureHandler</literal> objects
   passed to <literal>onFailure()</literal> methods.
   Your application can then take remedial action based on the result code,
   as in the following synchronous example.
  </para>
  <programlisting language="java">
final LDAPConnectionFactory factory = new LDAPConnectionFactory(host, port);
@@ -162,7 +133,7 @@
    // Perform operations on the connection...
} catch (final ErrorResultException e) {
} catch (final LdapException e) {
    // Take remedial action based on the result code...
    // e.getResult().getResultCode() returns the code for you to interpret.
@@ -172,12 +143,19 @@
        connection.close();
    }
}
</programlisting>
  </programlisting>
  <para>Also notice the methods <literal>ResultCode.getName()</literal> that
  provides a short, human-readable version of the result code, and
  <literal>Result.getDiagnosticMessage()</literal> that can also help debug
  problems after the fact.</para>
  <para>
   Also notice the methods <literal>ResultCode.getName()</literal>
   that provides a short, human-readable version of the result code,
   and <literal>Result.getDiagnosticMessage()</literal>
   that can help to debug problems after the fact.
  </para>
  <para>
   When you have completely finished with a connection,
   then use the <literal>close()</literal> method on it.
  </para>
 </section>
 <!-- Pending https://bugster.forgerock.org/jira/browse/OPENDJ-178
src/main/docbkx/sdk-release-notes/chap-get-sdk.xml
@@ -40,12 +40,8 @@
 <para>
  To include OpenDJ LDAP SDK as a Maven dependency,
  include the ForgeRock repository in your list,
  and include the SDK as a dependency.
  and include the required dependencies.
 </para>
 <programlisting language="xml">
<xinclude:include href="resources/maven-xml.txt" parse="text">
 <xinclude:fallback>Failed to include Maven POM sections</xinclude:fallback>
</xinclude:include>
 </programlisting>
 <xinclude:include href="../shared/programlisting-get-sdk.xml" />
</chapter>
src/main/docbkx/sdk-release-notes/chap-whats-new.xml
@@ -34,6 +34,23 @@
  <para>
   This release provides the following new features and enhancements.
  </para>
  <para>TODO</para><!-- https://github.com/markcraig/release-notes-list-builder -->
  <itemizedlist>
   <listitem>
    <para>
     TODO
    </para>
   </listitem>
   <listitem>
    <para>
     The SDK now supports Promises rather than Futures,
     easing development of asynchronous client applications
     (<link
      xlink:href="https://bugster.forgerock.org/jira/browse/OPENDJ-1285"
      xlink:show="new"
     >OPENDJ-1285</link>).
    </para>
   </listitem>
  </itemizedlist>
</chapter>
src/main/docbkx/sdk-release-notes/resources/maven-xml.txt
File was deleted
src/main/docbkx/shared/programlisting-get-sdk.xml
New file
@@ -0,0 +1,67 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
  ! CCPL HEADER START
  !
  ! This work is licensed under the Creative Commons
  ! Attribution-NonCommercial-NoDerivs 3.0 Unported License.
  ! To view a copy of this license, visit
  ! http://creativecommons.org/licenses/by-nc-nd/3.0/
  ! or send a letter to Creative Commons, 444 Castro Street,
  ! Suite 900, Mountain View, California, 94041, USA.
  !
  ! See the License for the specific language governing permissions
  ! and limitations under the License.
  !
  ! If applicable, add the following below this CCPL HEADER, with the fields
  ! enclosed by brackets "[]" replaced with your own identifying information:
  !      Portions Copyright [yyyy] [name of copyright owner]
  !
  ! CCPL HEADER END
  !
  !      Copyright 2014 ForgeRock AS
  !
-->
<programlisting language="xml"
                xmlns='http://docbook.org/ns/docbook' version='5.0' xml:lang='en'
                xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
                xsi:schemaLocation='http://docbook.org/ns/docbook
                                    http://docbook.org/xml/5.0/xsd/docbook.xsd'>
<![CDATA[
<repositories>
  <repository>
    <id>forgerock-staging-repository</id>
    <name>ForgeRock Release Repository</name>
    <url>${mavenRepoReleases}</url>
    <snapshots>
      <enabled>false</enabled>
    </snapshots>
  </repository>
  <repository>
    <id>forgerock-snapshots-repository</id>
    <name>ForgeRock Snapshot Repository</name>
    <url>${mavenRepoSnapshots}</url>
    <releases>
      <enabled>false</enabled>
    </releases>
  </repository>
</repositories>
<dependencies>
  <dependency>
    <groupId>${project.groupId}</groupId>
    <artifactId>opendj-core</artifactId>
    <version>${project.version}</version>
  </dependency>
  <dependency>
    <groupId>${project.groupId}</groupId>
    <artifactId>opendj-grizzly</artifactId>
    <version>${project.version}</version>
  </dependency>
  <dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-simple</artifactId>
    <version>${slf4jVersion}</version>
  </dependency>
</dependencies>
]]>
</programlisting>