Repository: curator
Updated Branches:
  refs/heads/CURATOR-397 8237fde0a -> 1dab81b5a


adding docs


Project: http://git-wip-us.apache.org/repos/asf/curator/repo
Commit: http://git-wip-us.apache.org/repos/asf/curator/commit/1dab81b5
Tree: http://git-wip-us.apache.org/repos/asf/curator/tree/1dab81b5
Diff: http://git-wip-us.apache.org/repos/asf/curator/diff/1dab81b5

Branch: refs/heads/CURATOR-397
Commit: 1dab81b5afedc4a0669312b386936baf7715c080
Parents: 8237fde
Author: randgalt <randg...@apache.org>
Authored: Sat Apr 8 15:03:49 2017 -0500
Committer: randgalt <randg...@apache.org>
Committed: Sat Apr 8 15:03:49 2017 -0500

----------------------------------------------------------------------
 .../x/async/modeled/JacksonModelSerializer.java |   6 +
 .../x/async/modeled/ModelSerializer.java        |  16 ++
 .../modeled/ModeledAsyncCuratorFramework.java   |  19 ++
 .../apache/curator/x/async/modeled/ZPath.java   |  55 +++++
 .../src/site/confluence/async.confluence        | 212 +++++++++++++++++++
 .../src/site/confluence/index.confluence        | 210 ++----------------
 .../src/site/confluence/modeled.confluence      | 103 +++++++++
 curator-x-async/src/site/site.xml               |   2 +-
 src/site/site.xml                               |   3 +-
 9 files changed, 430 insertions(+), 196 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/curator/blob/1dab81b5/curator-x-async/src/main/java/org/apache/curator/x/async/modeled/JacksonModelSerializer.java
----------------------------------------------------------------------
diff --git 
a/curator-x-async/src/main/java/org/apache/curator/x/async/modeled/JacksonModelSerializer.java
 
b/curator-x-async/src/main/java/org/apache/curator/x/async/modeled/JacksonModelSerializer.java
index 5fb6e07..90b120a 100644
--- 
a/curator-x-async/src/main/java/org/apache/curator/x/async/modeled/JacksonModelSerializer.java
+++ 
b/curator-x-async/src/main/java/org/apache/curator/x/async/modeled/JacksonModelSerializer.java
@@ -28,6 +28,12 @@ import com.fasterxml.jackson.databind.ObjectWriter;
 import java.io.IOException;
 import java.util.Arrays;
 
+/**
+ * Model serializer that uses Jackson for JSON serialization. 
<strong>IMPORTANT: </strong>
+ * the jackson dependency is specified as <code>provided</code> in the 
curator-x-async Maven POM
+ * file to avoid adding a new dependency to Curator. Therefore, if you wish to 
use the
+ * JacksonModelSerializer you must manually add the dependency to your build 
system.
+ */
 public class JacksonModelSerializer<T> implements ModelSerializer<T>
 {
     private static final ObjectMapper mapper = new ObjectMapper();

http://git-wip-us.apache.org/repos/asf/curator/blob/1dab81b5/curator-x-async/src/main/java/org/apache/curator/x/async/modeled/ModelSerializer.java
----------------------------------------------------------------------
diff --git 
a/curator-x-async/src/main/java/org/apache/curator/x/async/modeled/ModelSerializer.java
 
b/curator-x-async/src/main/java/org/apache/curator/x/async/modeled/ModelSerializer.java
index 64defdf..9828c26 100644
--- 
a/curator-x-async/src/main/java/org/apache/curator/x/async/modeled/ModelSerializer.java
+++ 
b/curator-x-async/src/main/java/org/apache/curator/x/async/modeled/ModelSerializer.java
@@ -18,9 +18,25 @@
  */
 package org.apache.curator.x.async.modeled;
 
+/**
+ * Serializing interface for models
+ */
 public interface ModelSerializer<T>
 {
+    /**
+     * Given a model return the serialized bytes
+     *
+     * @param model model
+     * @return bytes
+     */
     byte[] serialize(T model);
 
+    /**
+     * Given bytes serialized via {@link #serialize(Object)} return
+     * the model
+     *
+     * @param bytes serialized bytes
+     * @return model
+     */
     T deserialize(byte[] bytes);
 }

http://git-wip-us.apache.org/repos/asf/curator/blob/1dab81b5/curator-x-async/src/main/java/org/apache/curator/x/async/modeled/ModeledAsyncCuratorFramework.java
----------------------------------------------------------------------
diff --git 
a/curator-x-async/src/main/java/org/apache/curator/x/async/modeled/ModeledAsyncCuratorFramework.java
 
b/curator-x-async/src/main/java/org/apache/curator/x/async/modeled/ModeledAsyncCuratorFramework.java
index fdcc259..6acc77c 100644
--- 
a/curator-x-async/src/main/java/org/apache/curator/x/async/modeled/ModeledAsyncCuratorFramework.java
+++ 
b/curator-x-async/src/main/java/org/apache/curator/x/async/modeled/ModeledAsyncCuratorFramework.java
@@ -30,11 +30,30 @@ public interface ModeledAsyncCuratorFramework<T>
     ImmutableSet<CreateOption> defaultCreateOptions = 
ImmutableSet.of(CreateOption.createParentsAsContainers, 
CreateOption.setDataIfExists);
     ImmutableSet<DeleteOption> defaultDeleteOptions = 
ImmutableSet.of(DeleteOption.guaranteed);
 
+    /**
+     * Return a new ModeledAsyncCuratorFramework for the given path and 
serializer. The returned ModeledAsyncCuratorFramework
+     * is set to not watch ZNodes and uses {@link #defaultCreateOptions} and 
{@link #defaultDeleteOptions}.
+     *
+     * @param client Curator client
+     * @param path path to model
+     * @param serializer the model's serializer
+     * @return Modeled Curator instance
+     */
     static <T> ModeledAsyncCuratorFramework<T> wrap(CuratorFramework client, 
ZPath path, ModelSerializer<T> serializer)
     {
         return builder(client, path, serializer).build();
     }
 
+    /**
+     * Start a new ModeledAsyncCuratorFrameworkBuilder for the given path and 
serializer. The returned ModeledAsyncCuratorFrameworkBuilder
+     * is set to not watch ZNodes and uses {@link #defaultCreateOptions} and 
{@link #defaultDeleteOptions}, but you can change these
+     * with builder methods.
+     *
+     * @param client Curator client
+     * @param path path to model
+     * @param serializer the model's serializer
+     * @return builder
+     */
     static <T> ModeledAsyncCuratorFrameworkBuilder<T> builder(CuratorFramework 
client, ZPath path, ModelSerializer<T> serializer)
     {
         return new ModeledAsyncCuratorFrameworkBuilder<>(client, path, 
serializer)

http://git-wip-us.apache.org/repos/asf/curator/blob/1dab81b5/curator-x-async/src/main/java/org/apache/curator/x/async/modeled/ZPath.java
----------------------------------------------------------------------
diff --git 
a/curator-x-async/src/main/java/org/apache/curator/x/async/modeled/ZPath.java 
b/curator-x-async/src/main/java/org/apache/curator/x/async/modeled/ZPath.java
index 7e24341..05d012a 100644
--- 
a/curator-x-async/src/main/java/org/apache/curator/x/async/modeled/ZPath.java
+++ 
b/curator-x-async/src/main/java/org/apache/curator/x/async/modeled/ZPath.java
@@ -2,15 +2,36 @@ package org.apache.curator.x.async.modeled;
 
 import org.apache.curator.x.async.modeled.details.ZPathImpl;
 
+/**
+ * Abstracts a ZooKeeper ZNode path
+ */
 public interface ZPath
 {
+    /**
+     * The root path: "/"
+     */
     ZPath root = ZPathImpl.root;
 
+    /**
+     * Take a ZNode string path and return a ZPath
+     *
+     * @param fullPath the path to parse
+     * @return ZPath
+     * @throws IllegalArgumentException if the path is invalid
+     */
     static ZPath parse(String fullPath)
     {
         return ZPathImpl.parse(fullPath);
     }
 
+    /**
+     * Convert individual path names into a ZPath. E.g.
+     * <code>ZPath.from("my", "full", "path")</code>
+     *
+     * @param names path names
+     * @return ZPath
+     * @throws IllegalArgumentException if any of the names is invalid
+     */
     static ZPath from(String... names)
     {
         ZPath path = root;
@@ -21,15 +42,49 @@ public interface ZPath
         return path;
     }
 
+    /**
+     * Return a ZPath that represents a child ZNode of this ZPath. e.g.
+     * <code>ZPath.from("a", "b").at("c")</code> represents the path "/a/b/c"
+     *
+     * @param child child node name
+     * @return ZPath
+     */
     ZPath at(String child);
 
+    /**
+     * Return this ZPath's parent
+     *
+     * @return parent ZPath
+     * @throws java.util.NoSuchElementException if this is the root ZPath
+     */
     ZPath parent();
 
+    /**
+     * Return true/false if this is the root ZPath
+     *
+     * @return true false
+     */
     boolean isRoot();
 
+    /**
+     * The string full path that this ZPath represents
+     *
+     * @return full path
+     */
     String fullPath();
 
+    /**
+     * The string parent path of this ZPath
+     *
+     * @return parent path
+     * @throws java.util.NoSuchElementException if this is the root ZPath
+     */
     String parentPath();
 
+    /**
+     * The node name at this ZPath
+     *
+     * @return name
+     */
     String nodeName();
 }

http://git-wip-us.apache.org/repos/asf/curator/blob/1dab81b5/curator-x-async/src/site/confluence/async.confluence
----------------------------------------------------------------------
diff --git a/curator-x-async/src/site/confluence/async.confluence 
b/curator-x-async/src/site/confluence/async.confluence
new file mode 100644
index 0000000..619f5c8
--- /dev/null
+++ b/curator-x-async/src/site/confluence/async.confluence
@@ -0,0 +1,212 @@
+h1. Curator Async
+
+With this DSL you can do asynchronous tasks in a more natural, functional way 
using
+[Java 8 
lambdas|https://docs.oracle.com/javase/tutorial/java/javaOO/lambdaexpressions.html].
 For example:
+
+{code}
+// let "client" be a CuratorFramework instance
+AsyncCuratorFramework async = AsyncCuratorFramework.wrap(client);
+async.checkExists().forPath(somePath).thenAccept(stat -> 
mySuccessOperation(stat));
+{code}
+
+h2. Usage
+
+Note: To use Curator Async, you should be familiar with Java 8's lambdas, 
CompletedFuture and CompletionStage.
+
+Create a [[CuratorFramework|../curator\-framework/index.html]] instance in the 
normal way. You then wrap this instance using
+AsyncCuratorFramework. i.e.
+
+{code}
+// let "client" be a CuratorFramework instance
+AsyncCuratorFramework async = AsyncCuratorFramework.wrap(client);
+{code}
+
+AsyncCuratorFramework has most of the same builder methods that 
CuratorFramework does with some important
+differences:
+
+* AsyncCuratorFramework builders return {{AsyncStage}} instances
+* AsyncCuratorFramework builders have no checked exceptions
+* Many of the builder methods have been simplified/clarified
+* All builders invoke the asynchronous versions of ZooKeeper APIs
+* Watchers also use CompletionStages \- see below for details
+
+h4. AsyncStage
+
+AsyncStage instances extend Java 8's CompletionStage. CompletionStage objects 
can be "completed" with a success
+value or an exception. The parameterized type of the AsyncStage will
+be whatever the builder used would naturally return as a success value. E.g. 
the async getData() builder's AsyncStage is
+parameterized with "byte\[\]".
+
+h4. Watchers
+
+ZooKeeper watchers also get the CompletionStage treatment in Curator Async. To 
add a watcher, call
+watched() prior to starting the appropriate builders. E.g.
+
+{code}
+async.watched().getData().forPath(path) ...
+{code}
+
+Thus, a data watcher will be set on the specified path. You access the 
CompletionStage for the watcher
+by using the event() method of AsyncStage. Here is a complete example:
+
+{code}
+async.watched().getData().forPath(path).event().thenAccept(watchedEvent -> 
watchWasTriggered(watchedEvent));
+{code}
+
+ZooKeeper calls watchers when there is a connection loss. This can make using 
the CompletionStage
+somewhat complicated (see AsyncEventException below). If you are not 
interested in watcher connection
+problems, you can tell Curator Async to not send them by calling:
+
+{code}
+// only complete the CompletionStage when the watcher is successfully triggered
+// i.e. don't complete on connection issues
+async.with(WatchMode.successOnly).watched()...
+{code}
+
+h4. AsyncEventException
+
+When an async watcher fails the exception set in the CompletionStage will be 
of type {{AsyncEventException}}.
+This exception allows you to see the KeeperState that caused the trigger and 
allows you to reset the
+completion stage. Reset is needed because ZooKeeper temporarily triggers 
watchers when there is a connection
+event (unless {{WatchMode.successOnly}} is used). However, the watcher stays 
set for the original operation. Use {{AsyncEventException#reset}}
+to start a new completion stage that will wait on the next trigger of the 
watcher.
+
+E.g.
+
+{code}
+AsyncStage stage = ...
+stage.event().exceptionally(e -> {
+    AsyncEventException asyncEx = (AsyncEventException)e;
+
+    ... note a connection problem ...
+
+    asyncEx.reset().thenAccept(watchedEvent -> 
watchWasTriggered(watchedEvent));
+});
+{code}
+
+h4. AsyncResult
+
+As a convenience, you can use {{AsyncResult}} to combine ZooKeeper method 
value, the ZooKeeper result
+code and any exception in one object allowing you to not worry about 
exceptional completions. i.e. the {{CompletionStage}}
+returned by {{AsyncResult.of()}} always completes successfully with an 
AsyncResult object.
+
+AsyncResult has methods to get either the method result (a path, Stat, etc.), 
a KeeperException code
+or a general exception:
+
+{code}
+Optional<T> getValue();
+
+KeeperException.Code getCode();
+
+Optional<Throwable> getException();
+{code}
+
+Use AsyncResult by wrapping an {{AsyncStage}} value. i.e.
+
+{code}
+CompletionStage<AsyncResult<Stat>> resultStage = 
AsyncResult.of(async.checkExists().forPath(path));
+resultStage.thenAccept(result -> {
+    if ( result.getValue().isPresent() ) {
+        // ...
+    } else if ( result.getCode() == KeeperException.Code.NOAUTH ) {
+        // ...
+    }
+    // etc.
+});
+{code}
+
+h2. Examples
+
+h4. Create a sequential ZNode
+
+Create a sequential ZNode and, once successfully completed, set a watcher
+on the ZNode. Note: this code does not deal with errors. Should a connection
+problem occur or another exception occur, the completion lambda will never be 
called.
+
+{code}
+async.create().withMode(PERSISTENT_SEQUENTIAL).forPath(path).thenAccept(actualPath
 ->
+    async.watched().getData().forPath(actualPath).thenApply(() -> 
watchTriggered()));
+{code}
+
+----
+
+h4. AsyncStage canonical usage
+
+This is the canonical way to deal with AsyncStage. Use the handle() method 
which provides
+both the success value and the exception. The exception will be non\-null on 
error.
+
+{code}
+async.create().withOptions(EnumSet.of(doProtected)).forPath(path).handle((actualPath,
 exception) -> {
+    if ( exception != null )
+    {
+        // handle problem
+    }
+    else
+    {
+        // actualPath is the path created
+    }
+    return null;
+});
+{code}
+
+----
+
+h4. Simplified usage via AsyncResult
+
+{code}
+AsyncResult.of(async.create().withOptions(EnumSet.of(doProtected)).forPath(path)).thenAccept(result
 -> {
+    if ( result.getRawValue() != null )
+    {
+        // result.getRawValue() is the path created
+    }
+    else
+    {
+        // ...
+    }
+});
+{code}
+
+----
+
+h4. Using executors
+
+Your completion routines can operate in a separate thread if you provide an 
executor.
+
+{code}
+async.create().withOptions(EnumSet.of(createParentsIfNeeded)).forPath("/a/b/c")
+    .thenAcceptAsync(path -> handleCreate(path), executor);
+{code}
+
+----
+
+h4. Separate handlers
+
+This example shows specifying separate completion handlers for success and 
exception.
+
+{code}
+AsyncStage<byte[]> stage = async.getData().forPath("/my/path");
+stage.exceptionally(e -> {
+    if ( e instanceof KeeperException.NoNodeException )
+    {
+        // handle no node
+    }
+    else
+    {
+        // handle other
+    }
+    return null;
+});
+stage.thenAccept(data -> processData(data));
+{code}
+
+----
+
+h4. Synchronous usage
+
+CompletionStage provides a blocking method as well so that you can block to 
get the result
+of an operation. i.e. this makes it possible to use the async APIs in a 
synchronous way.
+
+{code}
+// NOTE: get() specifies a checked exception
+async.create().forPath("/foo").toCompletableFuture().get();
+{code}

http://git-wip-us.apache.org/repos/asf/curator/blob/1dab81b5/curator-x-async/src/site/confluence/index.confluence
----------------------------------------------------------------------
diff --git a/curator-x-async/src/site/confluence/index.confluence 
b/curator-x-async/src/site/confluence/index.confluence
index 34b6c36..3ea8b4c 100644
--- a/curator-x-async/src/site/confluence/index.confluence
+++ b/curator-x-async/src/site/confluence/index.confluence
@@ -4,7 +4,7 @@ h2. Packaging
 
 Curator Async is in its own package in Maven Central: curator\-x\-async
 
-h2. What Is a Curator Async?
+h2. What Is Curator Async?
 
 Curator Async is a 
[DSL|https://en.wikipedia.org/wiki/Domain-specific_language] that wraps existing
 {{CuratorFramework}} instances. This DSL is entirely asynchronous and uses
@@ -13,212 +13,34 @@ mechanism for chaining, composing, etc. Additionally, 
Curator's original DSL has
 and simplified, in particular for operations such as {{create()}}.
 
 With this DSL you can do asynchronous tasks in a more natural, functional way 
using
-[Java 8 
lambdas|https://docs.oracle.com/javase/tutorial/java/javaOO/lambdaexpressions.html].
 For example:
-
-{code}
-// let "client" be a CuratorFramework instance
-AsyncCuratorFramework async = AsyncCuratorFramework.wrap(client);
-async.checkExists().forPath(somePath).thenAccept(stat -> 
mySuccessOperation(stat));
-{code}
+[Java 8 
lambdas|https://docs.oracle.com/javase/tutorial/java/javaOO/lambdaexpressions.html].
 
-h2. Usage
+The Curator Async package also contains a strongly typed DSL that allows you 
to map a ZooKeeper path
+to a serializable class as opposed to raw byte arrays.
 
-Note: To use Curator Async, you should be familiar with Java 8's lambdas, 
CompletedFuture and CompletionStage.
+h2. [[Curator Async|async.html]]
 
-Create a [[CuratorFramework|../curator\-framework/index.html]] instance in the 
normal way. You then wrap this instance using
-AsyncCuratorFramework. i.e.
+With this DSL you can do asynchronous tasks in a more natural, functional way 
using
+[Java 8 
lambdas|https://docs.oracle.com/javase/tutorial/java/javaOO/lambdaexpressions.html].
 For example:
 
 {code}
 // let "client" be a CuratorFramework instance
 AsyncCuratorFramework async = AsyncCuratorFramework.wrap(client);
+async.checkExists().forPath(somePath).thenAccept(stat -> 
mySuccessOperation(stat));
 {code}
 
-AsyncCuratorFramework has most of the same builder methods that 
CuratorFramework does with some important
-differences:
-
-* AsyncCuratorFramework builders return {{AsyncStage}} instances
-* AsyncCuratorFramework builders have no checked exceptions
-* Many of the builder methods have been simplified/clarified
-* All builders invoke the asynchronous versions of ZooKeeper APIs
-* Watchers also use CompletionStages \- see below for details
-
-h4. AsyncStage
-
-AsyncStage instances extend Java 8's CompletionStage. CompletionStage objects 
can be "completed" with a success
-value or an exception. The parameterized type of the AsyncStage will
-be whatever the builder used would naturally return as a success value. E.g. 
the async getData() builder's AsyncStage is
-parameterized with "byte\[\]".
-
-h4. Watchers
-
-ZooKeeper watchers also get the CompletionStage treatment in Curator Async. To 
add a watcher, call
-watched() prior to starting the appropriate builders. E.g.
-
-{code}
-async.watched().getData().forPath(path) ...
-{code}
-
-Thus, a data watcher will be set on the specified path. You access the 
CompletionStage for the watcher
-by using the event() method of AsyncStage. Here is a complete example:
-
-{code}
-async.watched().getData().forPath(path).event().thenAccept(watchedEvent -> 
watchWasTriggered(watchedEvent));
-{code}
-
-ZooKeeper calls watchers when there is a connection loss. This can make using 
the CompletionStage
-somewhat complicated (see AsyncEventException below). If you are not 
interested in watcher connection
-problems, you can tell Curator Async to not send them by calling:
-
-{code}
-// only complete the CompletionStage when the watcher is successfully triggered
-// i.e. don't complete on connection issues
-async.with(WatchMode.successOnly).watched()...
-{code}
-
-h4. AsyncEventException
-
-When an async watcher fails the exception set in the CompletionStage will be 
of type {{AsyncEventException}}.
-This exception allows you to see the KeeperState that caused the trigger and 
allows you to reset the
-completion stage. Reset is needed because ZooKeeper temporarily triggers 
watchers when there is a connection
-event (unless {{WatchMode.successOnly}} is used). However, the watcher stays 
set for the original operation. Use {{AsyncEventException#reset}}
-to start a new completion stage that will wait on the next trigger of the 
watcher.
-
-E.g.
-
-{code}
-AsyncStage stage = ...
-stage.event().exceptionally(e -> {
-    AsyncEventException asyncEx = (AsyncEventException)e;
-
-    ... note a connection problem ...
-
-    asyncEx.reset().thenAccept(watchedEvent -> 
watchWasTriggered(watchedEvent));
-});
-{code}
-
-h4. AsyncResult
-
-As a convenience, you can use {{AsyncResult}} to combine ZooKeeper method 
value, the ZooKeeper result
-code and any exception in one object allowing you to not worry about 
exceptional completions. i.e. the {{CompletionStage}}
-returned by {{AsyncResult.of()}} always completes successfully with an 
AsyncResult object.
-
-AsyncResult has methods to get either the method result (a path, Stat, etc.), 
a KeeperException code
-or a general exception:
-
-{code}
-Optional<T> getValue();
-
-KeeperException.Code getCode();
-
-Optional<Throwable> getException();
-{code}
-
-Use AsyncResult by wrapping an {{AsyncStage}} value. i.e.
-
-{code}
-CompletionStage<AsyncResult<Stat>> resultStage = 
AsyncResult.of(async.checkExists().forPath(path));
-resultStage.thenAccept(result -> {
-    if ( result.getValue().isPresent() ) {
-        // ...
-    } else if ( result.getCode() == KeeperException.Code.NOAUTH ) {
-        // ...
-    }
-    // etc.
-});
-{code}
-
-h2. Examples
-
-h4. Create a sequential ZNode
-
-Create a sequential ZNode and, once successfully completed, set a watcher
-on the ZNode. Note: this code does not deal with errors. Should a connection
-problem occur or another exception occur, the completion lambda will never be 
called.
-
-{code}
-async.create().withMode(PERSISTENT_SEQUENTIAL).forPath(path).thenAccept(actualPath
 ->
-    async.watched().getData().forPath(actualPath).thenApply(() -> 
watchTriggered()));
-{code}
-
-----
-
-h4. AsyncStage canonical usage
-
-This is the canonical way to deal with AsyncStage. Use the handle() method 
which provides
-both the success value and the exception. The exception will be non\-null on 
error.
-
-{code}
-async.create().withOptions(EnumSet.of(doProtected)).forPath(path).handle((actualPath,
 exception) -> {
-    if ( exception != null )
-    {
-        // handle problem
-    }
-    else
-    {
-        // actualPath is the path created
-    }
-    return null;
-});
-{code}
-
-----
-
-h4. Simplified usage via AsyncResult
-
-{code}
-AsyncResult.of(async.create().withOptions(EnumSet.of(doProtected)).forPath(path)).thenAccept(result
 -> {
-    if ( result.getRawValue() != null )
-    {
-        // result.getRawValue() is the path created
-    }
-    else
-    {
-        // ...
-    }
-});
-{code}
-
-----
-
-h4. Using executors
-
-Your completion routines can operate in a separate thread if you provide an 
executor.
-
-{code}
-async.create().withOptions(EnumSet.of(createParentsIfNeeded)).forPath("/a/b/c")
-    .thenAcceptAsync(path -> handleCreate(path), executor);
-{code}
-
-----
+See [[Curator Async|async.html]] for details.
 
-h4. Separate handlers
+h2. [[Modeled Curator|modeled.html]]
 
-This example shows specifying separate completion handlers for success and 
exception.
+This is a strongly typed DSL that allows you to map a ZooKeeper path to a 
serializable class as
+opposed to raw byte arrays. For example:
 
 {code}
-AsyncStage<byte[]> stage = async.getData().forPath("/my/path");
-stage.exceptionally(e -> {
-    if ( e instanceof KeeperException.NoNodeException )
-    {
-        // handle no node
-    }
-    else
-    {
-        // handle other
-    }
-    return null;
-});
-stage.thenAccept(data -> processData(data));
+// let "client" be a CuratorFramework instance
+ModeledAsyncCuratorFramework<MyModel> modeled = 
ModeledAsyncCuratorFramework.wrap(client, path, serializer);
+modeled.create(new MyModel());
 {code}
 
-----
+See [[Modeled Curator|modeled.html]] for details.
 
-h4. Synchronous usage
-
-CompletionStage provides a blocking method as well so that you can block to 
get the result
-of an operation. i.e. this makes it possible to use the async APIs in a 
synchronous way.
-
-{code}
-// NOTE: get() specifies a checked exception
-async.create().forPath("/foo").toCompletableFuture().get();
-{code}

http://git-wip-us.apache.org/repos/asf/curator/blob/1dab81b5/curator-x-async/src/site/confluence/modeled.confluence
----------------------------------------------------------------------
diff --git a/curator-x-async/src/site/confluence/modeled.confluence 
b/curator-x-async/src/site/confluence/modeled.confluence
new file mode 100644
index 0000000..0506f8e
--- /dev/null
+++ b/curator-x-async/src/site/confluence/modeled.confluence
@@ -0,0 +1,103 @@
+h1. Modeled Curator
+
+This is a strongly typed DSL that allows you to map a ZooKeeper path to a 
serializable class as
+opposed to raw byte arrays. For example:
+
+{code}
+// let "client" be a CuratorFramework instance
+ModeledAsyncCuratorFramework<MyModel> modeled = 
ModeledAsyncCuratorFramework.wrap(client, path, serializer);
+modeled.create(new MyModel());
+{code}
+
+h2. Background and Usage
+
+Note: To use Modeled Curator, you should be familiar with Java 8's lambdas, 
CompletedFuture and CompletionStage.
+You should also be familiar with [[Curator Async|async.html]] as Modeled 
Curator is based on it.
+
+Modeled Curator maps a ZooKeeper path to a DSL that allows for strongly typed 
CRUD operations on that path
+and any children of the path. Bound into the DSL are all the various Curator 
options such as whether to
+watch nodes, compress data, use guaranteed delete, etc. You create an instance 
of this DSL once at startup
+so that it can be used without client code having to remember which serializer 
to use, which ACLs to
+set, etc.
+
+h4. Serialization
+
+{{ModelSerializer}} is the interface for serializing/deserializing model 
instances. For convenience
+a [[Jackson|https://github.com/FasterXML/jackson]] serializer is provided, 
{{JacksonModelSerializer}}.
+However, please note that the dependency on Jackson is marked as {{provided}} 
so as not to introduce
+a new dependency for using Curator. Therefore, if you wish to use the 
JacksonModelSerializer you must
+manually add the dependency to your build system.
+
+h4. Path Abstraction
+
+Instead of using raw string paths, Modeled Curator defines the {{ZPath}} 
interface that abstracts
+ZooKeeper paths.
+
+h4. Building
+
+You build a {{ModeledAsyncCuratorFramework}} instance using either the builder 
or helper wrapper. All
+options needed to use the ZPath are specified at build time:
+
+* whether and/or how to watch the ZNode
+* the ZNode {{CreateMode}}
+* any {{CreateOption}}s
+* any {{DeleteOption}}s
+* any ACLs
+* etc.
+
+These options are bound into the {{ModeledAsyncCuratorFramework}} instance and 
applied as needed.
+
+h2. Example
+
+For this example, assume this simple model:
+
+{code}
+public class Person {
+    private final String name;
+    private final int age;
+
+    public Person() {
+        this("", 0);
+    }
+
+    public Person(String name, int age) {
+        this.name = name;
+        this.age = age;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public int getAge() {
+        return age;
+    }
+}
+{code}
+
+We can now build a {{ModeledAsyncCuratorFramework}} that manages {{Person}} 
instances at a given path:
+
+{code}
+// let "client" be a CuratorFramework instance
+
+ZPath path = ZPath.parse(...);    // whatever path you need
+JacksonModelSerializer<Person> serializer = 
JacksonModelSerializer.build(Person.class);
+ModeledAsyncCuratorFramework<MyModel> modeled = 
ModeledAsyncCuratorFramework.wrap(client, path, serializer);
+
+...
+
+public void writePerson(String id, Person p) {
+    modeled.at(id).create(p);   // note this is an async operation
+}
+
+public void readPerson(String id, Consumer<Person> receiver) {
+    modeled.at(id).read().whenComplete((person, exception) -> {
+        if ( exception != null ) {
+            ...
+        } else {
+            receiver.accept(person);
+        }
+    });
+}
+
+{code}

http://git-wip-us.apache.org/repos/asf/curator/blob/1dab81b5/curator-x-async/src/site/site.xml
----------------------------------------------------------------------
diff --git a/curator-x-async/src/site/site.xml 
b/curator-x-async/src/site/site.xml
index 63fccaa..964353c 100644
--- a/curator-x-async/src/site/site.xml
+++ b/curator-x-async/src/site/site.xml
@@ -25,7 +25,7 @@
             <link rel="stylesheet" href="../css/site.css" />
             <script type="text/javascript">
                 $(function(){
-                $('a[title="Curator RPC Proxy"]').parent().addClass("active");
+                $('a[title="Curator Async"]').parent().addClass("active");
                 });
             </script>
         </head>

http://git-wip-us.apache.org/repos/asf/curator/blob/1dab81b5/src/site/site.xml
----------------------------------------------------------------------
diff --git a/src/site/site.xml b/src/site/site.xml
index 222ffde..9f87bd6 100644
--- a/src/site/site.xml
+++ b/src/site/site.xml
@@ -73,6 +73,7 @@
             <item name="Framework" href="curator-framework/index.html"/>
             <item name="Utilities" href="utilities.html"/>
             <item name="Client" href="curator-client/index.html"/>
+            <item name="Java 8/Async" href="curator-x-async/index.html"/>
             <item name="Schema Support" href="curator-framework/schema.html"/>
         </menu>
 
@@ -94,7 +95,7 @@
             <item name="Service Discovery" 
href="curator-x-discovery/index.html"/>
             <item name="Service Discovery Server" 
href="curator-x-discovery-server/index.html"/>
             <item name="Curator RPC Proxy" href="curator-x-rpc/index.html"/>
-            <item name="Curator Async" href="curator-x-async/index.html"/>
+            <item name="Curator Java 8/Async" 
href="curator-x-async/index.html"/>
         </menu>
 
         <menu name="Community" inherit="top">

Reply via email to