You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@curator.apache.org by ra...@apache.org on 2014/02/18 10:48:42 UTC

[1/4] git commit: development continues

Repository: curator
Updated Branches:
  refs/heads/CURATOR-88 ce456d2df -> b4c76c79b


development continues


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

Branch: refs/heads/CURATOR-88
Commit: 4ab6476c090383dd8b411c21a56d497b226938ce
Parents: ce456d2
Author: randgalt <ra...@apache.org>
Authored: Mon Feb 17 13:28:19 2014 -0500
Committer: randgalt <ra...@apache.org>
Committed: Mon Feb 17 13:28:19 2014 -0500

----------------------------------------------------------------------
 .../curator/x/rest/CuratorRestContext.java      |  23 ++++
 .../curator/x/rest/api/ClientResource.java      |  96 ++++++++++++++---
 .../apache/curator/x/rest/api/Constants.java    |   1 +
 .../x/rest/api/RestBackgroundCallback.java      |   7 +-
 .../org/apache/curator/x/rest/api/Session.java  |   6 +-
 .../x/rest/dropwizard/CuratorApplication.java   |  52 +++++++++
 .../x/rest/dropwizard/CuratorConfiguration.java | 105 +++++++++++++++++++
 .../x/rest/dropwizard/CuratorHealthCheck.java   |  45 ++++++++
 .../x/rest/dropwizard/CuratorRestBundle.java    |  36 +++++--
 .../curator/x/rest/entities/LeaderSpec.java     |   3 +
 .../curator/x/rest/entities/PathAndId.java      |  60 +++++++++++
 .../entities/PersistentEphemeralNodeSpec.java   |   2 +
 curator-x-rest/src/main/resources/maven/pom.xml |  85 +++++++++++++++
 .../src/site/confluence/index.confluence        |   4 +-
 curator-x-rest/src/site/site.xml                |  38 +++----
 .../x/rest/dropwizard/DropwizardRunner.java     |  29 +----
 16 files changed, 514 insertions(+), 78 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/curator/blob/4ab6476c/curator-x-rest/src/main/java/org/apache/curator/x/rest/CuratorRestContext.java
----------------------------------------------------------------------
diff --git a/curator-x-rest/src/main/java/org/apache/curator/x/rest/CuratorRestContext.java b/curator-x-rest/src/main/java/org/apache/curator/x/rest/CuratorRestContext.java
index a07197e..68cb939 100644
--- a/curator-x-rest/src/main/java/org/apache/curator/x/rest/CuratorRestContext.java
+++ b/curator-x-rest/src/main/java/org/apache/curator/x/rest/CuratorRestContext.java
@@ -20,6 +20,8 @@ package org.apache.curator.x.rest;
 
 import com.google.common.base.Preconditions;
 import org.apache.curator.framework.CuratorFramework;
+import org.apache.curator.framework.state.ConnectionState;
+import org.apache.curator.framework.state.ConnectionStateListener;
 import org.apache.curator.utils.ThreadUtils;
 import org.apache.curator.x.rest.api.Session;
 import org.codehaus.jackson.map.ObjectMapper;
@@ -38,6 +40,19 @@ public class CuratorRestContext implements Closeable
     private final int sessionLengthMs;
     private final AtomicReference<State> state = new AtomicReference<State>(State.LATENT);
     private final ScheduledExecutorService executorService = ThreadUtils.newSingleThreadScheduledExecutor("CuratorRestContext");
+    private final AtomicReference<ConnectionState> connectionState = new AtomicReference<ConnectionState>();
+    private final ConnectionStateListener connectionStateListener = new ConnectionStateListener()
+    {
+        @Override
+        public void stateChanged(CuratorFramework client, ConnectionState newState)
+        {
+            if ( newState == ConnectionState.RECONNECTED )
+            {
+                newState = ConnectionState.CONNECTED;
+            }
+            connectionState.set(newState);
+        }
+    };
 
     private enum State
     {
@@ -58,6 +73,11 @@ public class CuratorRestContext implements Closeable
         return client;
     }
 
+    public ConnectionState getConnectionState()
+    {
+        return connectionState.get();
+    }
+
     public Session getSession()
     {
         Preconditions.checkState(state.get() == State.STARTED, "Not started");
@@ -77,6 +97,8 @@ public class CuratorRestContext implements Closeable
             }
         };
         executorService.scheduleAtFixedRate(runner, sessionLengthMs, sessionLengthMs, TimeUnit.MILLISECONDS);
+        client.getConnectionStateListenable().addListener(connectionStateListener);
+        connectionState.set(client.getZookeeperClient().isConnected() ? ConnectionState.CONNECTED : ConnectionState.SUSPENDED);
     }
 
     @Override
@@ -84,6 +106,7 @@ public class CuratorRestContext implements Closeable
     {
         if ( state.compareAndSet(State.STARTED, State.CLOSED) )
         {
+            client.getConnectionStateListenable().removeListener(connectionStateListener);
             executorService.shutdownNow();
             session.close();
         }

http://git-wip-us.apache.org/repos/asf/curator/blob/4ab6476c/curator-x-rest/src/main/java/org/apache/curator/x/rest/api/ClientResource.java
----------------------------------------------------------------------
diff --git a/curator-x-rest/src/main/java/org/apache/curator/x/rest/api/ClientResource.java b/curator-x-rest/src/main/java/org/apache/curator/x/rest/api/ClientResource.java
index 26708cf..2321fa0 100644
--- a/curator-x-rest/src/main/java/org/apache/curator/x/rest/api/ClientResource.java
+++ b/curator-x-rest/src/main/java/org/apache/curator/x/rest/api/ClientResource.java
@@ -19,6 +19,8 @@
 package org.apache.curator.x.rest.api;
 
 import com.google.common.base.Joiner;
+import com.google.common.collect.ImmutableList;
+import org.apache.curator.framework.CuratorFramework;
 import org.apache.curator.framework.api.*;
 import org.apache.curator.x.rest.CuratorRestContext;
 import org.apache.curator.x.rest.entities.CreateSpec;
@@ -26,15 +28,18 @@ import org.apache.curator.x.rest.entities.DeleteSpec;
 import org.apache.curator.x.rest.entities.ExistsSpec;
 import org.apache.curator.x.rest.entities.GetChildrenSpec;
 import org.apache.curator.x.rest.entities.GetDataSpec;
+import org.apache.curator.x.rest.entities.PathAndId;
 import org.apache.curator.x.rest.entities.SetDataSpec;
+import org.apache.zookeeper.CreateMode;
 import org.codehaus.jackson.node.ObjectNode;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 import javax.ws.rs.Consumes;
 import javax.ws.rs.DELETE;
 import javax.ws.rs.GET;
 import javax.ws.rs.POST;
 import javax.ws.rs.PUT;
 import javax.ws.rs.Path;
-import javax.ws.rs.PathParam;
 import javax.ws.rs.Produces;
 import javax.ws.rs.WebApplicationException;
 import javax.ws.rs.core.Context;
@@ -46,6 +51,7 @@ import java.util.List;
 @Path("/curator/v1/client")
 public class ClientResource
 {
+    private final Logger log = LoggerFactory.getLogger(getClass());
     private final CuratorRestContext context;
 
     public ClientResource(@Context CuratorRestContext context)
@@ -58,22 +64,25 @@ public class ClientResource
     @Path("/status")
     public Response getStatus() throws IOException
     {
-        ObjectNode node = context.getMapper().createObjectNode();
-        node.put("state", context.getClient().getState().name());
-        node.putPOJO("messages", context.getSession().drainMessages());
-
-        return Response.ok(context.getWriter().writeValueAsString(node)).build();
+        return getStatusWithTouch(ImmutableList.<String>of());
     }
 
-    @GET
-    @Path("/touch/{id}")
-    public Response touchThing(@PathParam("id") String id)
+    @POST
+    @Produces(MediaType.APPLICATION_JSON)
+    @Consumes(MediaType.APPLICATION_JSON)
+    @Path("/status")
+    public Response getStatusWithTouch(List<String> ids) throws IOException
     {
-        if ( !context.getSession().updateThingLastUse(id) )
+        ObjectNode node = context.getMapper().createObjectNode();
+        node.put("state", context.getConnectionState().name());
+        node.putPOJO("messages", context.getSession().drainMessages());
+
+        for ( String id : ids )
         {
-            return Response.status(Response.Status.NOT_FOUND).build();
+            context.getSession().updateThingLastUse(id);
         }
-        return Response.ok().build();
+
+        return Response.ok(context.getWriter().writeValueAsString(node)).build();
     }
 
     @POST
@@ -185,17 +194,47 @@ public class ClientResource
         }
         builder = castBuilder(builder, CreateModable.class).withMode(createSpec.getMode());
 
+        final String id = Constants.newId();
         if ( createSpec.isAsync() )
         {
-            BackgroundCallback backgroundCallback = new RestBackgroundCallback(context, Constants.CLIENT_CREATE_ASYNC, createSpec.getAsyncId());
+            BackgroundCallback backgroundCallback = new RestBackgroundCallback(context, Constants.CLIENT_CREATE_ASYNC, createSpec.getAsyncId())
+            {
+                @Override
+                public void processResult(CuratorFramework client, CuratorEvent event) throws Exception
+                {
+                    if ( event.getResultCode() == 0 )
+                    {
+                        checkEphemeralCreate(createSpec, id, event.getName());
+                    }
+                    super.processResult(client, event);
+                }
+
+                @Override
+                protected String getMessage(CuratorEvent event)
+                {
+                    if ( event.getResultCode() != 0 )
+                    {
+                        return Constants.ERROR;
+                    }
+                    return event.getName();
+                }
+
+                @Override
+                protected String getDetails(CuratorEvent event)
+                {
+                    if ( event.getResultCode() != 0 )
+                    {
+                        return super.getDetails(event);
+                    }
+                    return id;
+                }
+            };
             builder = castBuilder(builder, Backgroundable.class).inBackground(backgroundCallback);
         }
 
         String returnPath = String.valueOf(castBuilder(builder, PathAndBytesable.class).forPath(createSpec.getPath(), createSpec.getData().getBytes()));
-
-        ObjectNode node = context.getMapper().createObjectNode();
-        node.put("path", returnPath);
-        return Response.ok(context.getWriter().writeValueAsString(node)).build();
+        checkEphemeralCreate(createSpec, id, returnPath);
+        return Response.ok(new PathAndId(returnPath, id)).build();
     }
 
     @POST
@@ -275,4 +314,27 @@ public class ClientResource
         throw new WebApplicationException(Response.Status.BAD_REQUEST);
     }
 
+    private void checkEphemeralCreate(CreateSpec createSpec, String id, String ephemeralPath)
+    {
+        if ( (createSpec.getMode() == CreateMode.EPHEMERAL) || (createSpec.getMode() == CreateMode.EPHEMERAL_SEQUENTIAL) )
+        {
+            Closer<String> closer = new Closer<String>()
+            {
+                @Override
+                public void close(String path)
+                {
+                    log.warn("Ephemeral node has expired and is being deleted: " + path);
+                    try
+                    {
+                        context.getClient().delete().guaranteed().inBackground().forPath(path);
+                    }
+                    catch ( Exception e )
+                    {
+                        log.error("Could not delete expired ephemeral node: " + path);
+                    }
+                }
+            };
+            context.getSession().addThing(id, ephemeralPath, closer);
+        }
+    }
 }

http://git-wip-us.apache.org/repos/asf/curator/blob/4ab6476c/curator-x-rest/src/main/java/org/apache/curator/x/rest/api/Constants.java
----------------------------------------------------------------------
diff --git a/curator-x-rest/src/main/java/org/apache/curator/x/rest/api/Constants.java b/curator-x-rest/src/main/java/org/apache/curator/x/rest/api/Constants.java
index 5ee1982..a516322 100644
--- a/curator-x-rest/src/main/java/org/apache/curator/x/rest/api/Constants.java
+++ b/curator-x-rest/src/main/java/org/apache/curator/x/rest/api/Constants.java
@@ -34,6 +34,7 @@ class Constants
     static final String CLIENT_SET_DATA_ASYNC = "client-set-data-async";
     static final String CLIENT_EXISTS_ASYNC = "client-exists-async";
     static final String CLIENT_DELETE_ASYNC = "client-delete-async";
+    static final String ERROR = "error";
     static final String WATCH = "watch";
     static final String PATH_CACHE = "path-cache";
     static final String NODE_CACHE = "node-cache";

http://git-wip-us.apache.org/repos/asf/curator/blob/4ab6476c/curator-x-rest/src/main/java/org/apache/curator/x/rest/api/RestBackgroundCallback.java
----------------------------------------------------------------------
diff --git a/curator-x-rest/src/main/java/org/apache/curator/x/rest/api/RestBackgroundCallback.java b/curator-x-rest/src/main/java/org/apache/curator/x/rest/api/RestBackgroundCallback.java
index 482576b..a5e2284 100644
--- a/curator-x-rest/src/main/java/org/apache/curator/x/rest/api/RestBackgroundCallback.java
+++ b/curator-x-rest/src/main/java/org/apache/curator/x/rest/api/RestBackgroundCallback.java
@@ -40,7 +40,12 @@ class RestBackgroundCallback implements BackgroundCallback
     @Override
     public void processResult(CuratorFramework client, CuratorEvent event) throws Exception
     {
-        context.getSession().pushMessage(new StatusMessage(type, asyncId, getMessage(event), Integer.toString(event.getResultCode())));
+        context.getSession().pushMessage(new StatusMessage(type, asyncId, getMessage(event), getDetails(event)));
+    }
+
+    protected String getDetails(CuratorEvent event)
+    {
+        return Integer.toString(event.getResultCode());
     }
 
     protected String getMessage(CuratorEvent event)

http://git-wip-us.apache.org/repos/asf/curator/blob/4ab6476c/curator-x-rest/src/main/java/org/apache/curator/x/rest/api/Session.java
----------------------------------------------------------------------
diff --git a/curator-x-rest/src/main/java/org/apache/curator/x/rest/api/Session.java b/curator-x-rest/src/main/java/org/apache/curator/x/rest/api/Session.java
index 16478ce..36a2654 100644
--- a/curator-x-rest/src/main/java/org/apache/curator/x/rest/api/Session.java
+++ b/curator-x-rest/src/main/java/org/apache/curator/x/rest/api/Session.java
@@ -113,7 +113,11 @@ public class Session implements Closeable
 
     <T> String addThing(T thing, Closer<T> closer)
     {
-        String id = Constants.newId();
+        return addThing(Constants.newId(), thing, closer);
+    }
+
+    <T> String addThing(String id, T thing, Closer<T> closer)
+    {
         things.put(id, new Entry(thing, closer));
         return id;
     }

http://git-wip-us.apache.org/repos/asf/curator/blob/4ab6476c/curator-x-rest/src/main/java/org/apache/curator/x/rest/dropwizard/CuratorApplication.java
----------------------------------------------------------------------
diff --git a/curator-x-rest/src/main/java/org/apache/curator/x/rest/dropwizard/CuratorApplication.java b/curator-x-rest/src/main/java/org/apache/curator/x/rest/dropwizard/CuratorApplication.java
new file mode 100644
index 0000000..539097d
--- /dev/null
+++ b/curator-x-rest/src/main/java/org/apache/curator/x/rest/dropwizard/CuratorApplication.java
@@ -0,0 +1,52 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.curator.x.rest.dropwizard;
+
+import io.dropwizard.Application;
+import io.dropwizard.setup.Bootstrap;
+import io.dropwizard.setup.Environment;
+
+public class CuratorApplication
+{
+    public static void main(String[] args) throws Exception
+    {
+        Application application = new Application<CuratorConfiguration>()
+        {
+            @Override
+            public void initialize(Bootstrap<CuratorConfiguration> bootstrap)
+            {
+                bootstrap.addBundle(new CuratorRestBundle());
+            }
+
+            @Override
+            public void run(CuratorConfiguration configuration, Environment environment) throws Exception
+            {
+                // NOP
+            }
+        };
+
+        if ( args.length == 0 )
+        {
+            args = new String[]{"server"};
+        }
+
+        application.run(args);
+    }
+}

http://git-wip-us.apache.org/repos/asf/curator/blob/4ab6476c/curator-x-rest/src/main/java/org/apache/curator/x/rest/dropwizard/CuratorConfiguration.java
----------------------------------------------------------------------
diff --git a/curator-x-rest/src/main/java/org/apache/curator/x/rest/dropwizard/CuratorConfiguration.java b/curator-x-rest/src/main/java/org/apache/curator/x/rest/dropwizard/CuratorConfiguration.java
new file mode 100644
index 0000000..0ca30ac
--- /dev/null
+++ b/curator-x-rest/src/main/java/org/apache/curator/x/rest/dropwizard/CuratorConfiguration.java
@@ -0,0 +1,105 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.curator.x.rest.dropwizard;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import io.dropwizard.Configuration;
+import javax.validation.Valid;
+import javax.validation.constraints.Min;
+import javax.validation.constraints.NotNull;
+import java.util.concurrent.TimeUnit;
+
+public class CuratorConfiguration extends Configuration
+{
+    @Valid
+    @NotNull
+    @JsonProperty("connection-string")
+    private String zooKeeperConnectionString = "localhost:2181";
+
+    @Valid
+    @Min(1)
+    @JsonProperty("session-length-ms")
+    private int sessionLengthMs = (int)TimeUnit.MINUTES.toMillis(1);
+
+    @Valid
+    @Min(1)
+    @JsonProperty("connection-timeout-ms")
+    private int connectionTimeoutMs = (int)TimeUnit.SECONDS.toMillis(15);
+
+    @Valid
+    @Min(1)
+    @JsonProperty("retry-base-sleep-ms")
+    private int retryBaseSleepMs = 100;
+
+    @Valid
+    @Min(1)
+    @JsonProperty("retry-qty")
+    private int retryQty = 3;
+
+    public String getZooKeeperConnectionString()
+    {
+        return zooKeeperConnectionString;
+    }
+
+    public void setZooKeeperConnectionString(String zooKeeperConnectionString)
+    {
+        this.zooKeeperConnectionString = zooKeeperConnectionString;
+    }
+
+    public int getSessionLengthMs()
+    {
+        return sessionLengthMs;
+    }
+
+    public void setSessionLengthMs(int sessionLengthMs)
+    {
+        this.sessionLengthMs = sessionLengthMs;
+    }
+
+    public int getConnectionTimeoutMs()
+    {
+        return connectionTimeoutMs;
+    }
+
+    public void setConnectionTimeoutMs(int connectionTimeoutMs)
+    {
+        this.connectionTimeoutMs = connectionTimeoutMs;
+    }
+
+    public int getRetryBaseSleepMs()
+    {
+        return retryBaseSleepMs;
+    }
+
+    public void setRetryBaseSleepMs(int retryBaseSleepMs)
+    {
+        this.retryBaseSleepMs = retryBaseSleepMs;
+    }
+
+    public int getRetryQty()
+    {
+        return retryQty;
+    }
+
+    public void setRetryQty(int retryQty)
+    {
+        this.retryQty = retryQty;
+    }
+}

http://git-wip-us.apache.org/repos/asf/curator/blob/4ab6476c/curator-x-rest/src/main/java/org/apache/curator/x/rest/dropwizard/CuratorHealthCheck.java
----------------------------------------------------------------------
diff --git a/curator-x-rest/src/main/java/org/apache/curator/x/rest/dropwizard/CuratorHealthCheck.java b/curator-x-rest/src/main/java/org/apache/curator/x/rest/dropwizard/CuratorHealthCheck.java
new file mode 100644
index 0000000..594574d
--- /dev/null
+++ b/curator-x-rest/src/main/java/org/apache/curator/x/rest/dropwizard/CuratorHealthCheck.java
@@ -0,0 +1,45 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.curator.x.rest.dropwizard;
+
+import com.codahale.metrics.health.HealthCheck;
+import org.apache.curator.framework.state.ConnectionState;
+import org.apache.curator.x.rest.CuratorRestContext;
+
+public class CuratorHealthCheck extends HealthCheck
+{
+    private final CuratorRestContext context;
+
+    public CuratorHealthCheck(CuratorRestContext context)
+    {
+        this.context = context;
+    }
+
+    @Override
+    protected Result check() throws Exception
+    {
+        ConnectionState state = context.getConnectionState();
+        if ( state != ConnectionState.CONNECTED )
+        {
+            return Result.unhealthy(state.name());
+        }
+        return Result.healthy();
+    }
+}

http://git-wip-us.apache.org/repos/asf/curator/blob/4ab6476c/curator-x-rest/src/main/java/org/apache/curator/x/rest/dropwizard/CuratorRestBundle.java
----------------------------------------------------------------------
diff --git a/curator-x-rest/src/main/java/org/apache/curator/x/rest/dropwizard/CuratorRestBundle.java b/curator-x-rest/src/main/java/org/apache/curator/x/rest/dropwizard/CuratorRestBundle.java
index 250b285..2edc06f 100644
--- a/curator-x-rest/src/main/java/org/apache/curator/x/rest/dropwizard/CuratorRestBundle.java
+++ b/curator-x-rest/src/main/java/org/apache/curator/x/rest/dropwizard/CuratorRestBundle.java
@@ -20,25 +20,20 @@
 package org.apache.curator.x.rest.dropwizard;
 
 import com.sun.jersey.spi.inject.SingletonTypeInjectableProvider;
-import io.dropwizard.Bundle;
+import io.dropwizard.ConfiguredBundle;
 import io.dropwizard.setup.Bootstrap;
 import io.dropwizard.setup.Environment;
 import org.apache.curator.framework.CuratorFramework;
+import org.apache.curator.framework.CuratorFrameworkFactory;
+import org.apache.curator.retry.ExponentialBackoffRetry;
 import org.apache.curator.x.rest.CuratorRestClasses;
 import org.apache.curator.x.rest.CuratorRestContext;
 import org.eclipse.jetty.util.component.AbstractLifeCycle;
 import org.eclipse.jetty.util.component.LifeCycle;
 import javax.ws.rs.core.Context;
 
-public class CuratorRestBundle implements Bundle
+public class CuratorRestBundle implements ConfiguredBundle<CuratorConfiguration>
 {
-    private final CuratorRestContext context;
-
-    public CuratorRestBundle(CuratorFramework client, int sessionLengthMs)
-    {
-        this.context = new CuratorRestContext(client, sessionLengthMs);
-    }
-
     @Override
     public void initialize(Bootstrap<?> bootstrap)
     {
@@ -46,8 +41,10 @@ public class CuratorRestBundle implements Bundle
     }
 
     @Override
-    public void run(Environment environment)
+    public void run(CuratorConfiguration configuration, Environment environment) throws Exception
     {
+        final CuratorRestContext context = newCuratorRestContext(configuration);
+
         SingletonTypeInjectableProvider<Context, CuratorRestContext> injectable = new SingletonTypeInjectableProvider<Context, CuratorRestContext>(CuratorRestContext.class, context){};
         environment.jersey().register(injectable);
         for ( Class<?> clazz : CuratorRestClasses.getClasses() )
@@ -70,5 +67,24 @@ public class CuratorRestBundle implements Bundle
             }
         };
         environment.lifecycle().addLifeCycleListener(listener);
+
+        environment.healthChecks().register("Curator", new CuratorHealthCheck(context));
+    }
+
+    protected CuratorRestContext newCuratorRestContext(CuratorConfiguration configuration)
+    {
+        CuratorFramework client = newCuratorClient(configuration);
+        return new CuratorRestContext(client, configuration.getSessionLengthMs());
+    }
+
+    protected CuratorFramework newCuratorClient(CuratorConfiguration configuration)
+    {
+        ExponentialBackoffRetry retryPolicy = new ExponentialBackoffRetry(configuration.getRetryBaseSleepMs(), configuration.getRetryQty());
+        return CuratorFrameworkFactory.newClient
+        (
+            configuration.getZooKeeperConnectionString(),
+            configuration.getSessionLengthMs(),
+            configuration.getConnectionTimeoutMs(), retryPolicy
+        );
     }
 }

http://git-wip-us.apache.org/repos/asf/curator/blob/4ab6476c/curator-x-rest/src/main/java/org/apache/curator/x/rest/entities/LeaderSpec.java
----------------------------------------------------------------------
diff --git a/curator-x-rest/src/main/java/org/apache/curator/x/rest/entities/LeaderSpec.java b/curator-x-rest/src/main/java/org/apache/curator/x/rest/entities/LeaderSpec.java
index ad7fa90..fde9701 100644
--- a/curator-x-rest/src/main/java/org/apache/curator/x/rest/entities/LeaderSpec.java
+++ b/curator-x-rest/src/main/java/org/apache/curator/x/rest/entities/LeaderSpec.java
@@ -18,6 +18,9 @@
  */
 package org.apache.curator.x.rest.entities;
 
+import javax.xml.bind.annotation.XmlRootElement;
+
+@XmlRootElement
 public class LeaderSpec
 {
     private String path;

http://git-wip-us.apache.org/repos/asf/curator/blob/4ab6476c/curator-x-rest/src/main/java/org/apache/curator/x/rest/entities/PathAndId.java
----------------------------------------------------------------------
diff --git a/curator-x-rest/src/main/java/org/apache/curator/x/rest/entities/PathAndId.java b/curator-x-rest/src/main/java/org/apache/curator/x/rest/entities/PathAndId.java
new file mode 100644
index 0000000..ed27938
--- /dev/null
+++ b/curator-x-rest/src/main/java/org/apache/curator/x/rest/entities/PathAndId.java
@@ -0,0 +1,60 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.curator.x.rest.entities;
+
+import javax.xml.bind.annotation.XmlRootElement;
+
+@XmlRootElement
+public class PathAndId
+{
+    private String path;
+    private String id;
+
+    public PathAndId()
+    {
+        this("/", "");
+    }
+
+    public PathAndId(String path, String id)
+    {
+        this.path = path;
+        this.id = id;
+    }
+
+    public String getPath()
+    {
+        return path;
+    }
+
+    public void setPath(String path)
+    {
+        this.path = path;
+    }
+
+    public String getId()
+    {
+        return id;
+    }
+
+    public void setId(String id)
+    {
+        this.id = id;
+    }
+}

http://git-wip-us.apache.org/repos/asf/curator/blob/4ab6476c/curator-x-rest/src/main/java/org/apache/curator/x/rest/entities/PersistentEphemeralNodeSpec.java
----------------------------------------------------------------------
diff --git a/curator-x-rest/src/main/java/org/apache/curator/x/rest/entities/PersistentEphemeralNodeSpec.java b/curator-x-rest/src/main/java/org/apache/curator/x/rest/entities/PersistentEphemeralNodeSpec.java
index 691e77c..5f70112 100644
--- a/curator-x-rest/src/main/java/org/apache/curator/x/rest/entities/PersistentEphemeralNodeSpec.java
+++ b/curator-x-rest/src/main/java/org/apache/curator/x/rest/entities/PersistentEphemeralNodeSpec.java
@@ -19,7 +19,9 @@
 package org.apache.curator.x.rest.entities;
 
 import org.apache.curator.framework.recipes.nodes.PersistentEphemeralNode;
+import javax.xml.bind.annotation.XmlRootElement;
 
+@XmlRootElement
 public class PersistentEphemeralNodeSpec
 {
     private String path;

http://git-wip-us.apache.org/repos/asf/curator/blob/4ab6476c/curator-x-rest/src/main/resources/maven/pom.xml
----------------------------------------------------------------------
diff --git a/curator-x-rest/src/main/resources/maven/pom.xml b/curator-x-rest/src/main/resources/maven/pom.xml
new file mode 100644
index 0000000..9b2e707
--- /dev/null
+++ b/curator-x-rest/src/main/resources/maven/pom.xml
@@ -0,0 +1,85 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--~
+  ~ Licensed to the Apache Software Foundation (ASF) under one
+  ~ or more contributor license agreements.  See the NOTICE file
+  ~ distributed with this work for additional information
+  ~ regarding copyright ownership.  The ASF licenses this file
+  ~ to you under the Apache License, Version 2.0 (the
+  ~ "License"); you may not use this file except in compliance
+  ~ with the License.  You may obtain a copy of the License at
+  ~
+  ~   http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing,
+  ~ software distributed under the License is distributed on an
+  ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  ~ KIND, either express or implied.  See the License for the
+  ~ specific language governing permissions and limitations
+  ~ under the License.
+  -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <groupId>org.apache.curator</groupId>
+    <artifactId>curator-rest-application</artifactId>
+    <version>2.4.1-SNAPSHOT</version>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.curator</groupId>
+            <artifactId>curator-x-rest</artifactId>
+            <version>2.4.1-SNAPSHOT</version>
+            <exclusions>
+                <exclusion>
+                    <groupId>org.slf4j</groupId>
+                    <artifactId>slf4j-log4j12</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+
+        <dependency>
+            <groupId>io.dropwizard</groupId>
+            <artifactId>dropwizard-core</artifactId>
+            <version>0.7.0-rc1</version>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <artifactId>maven-shade-plugin</artifactId>
+                <version>2.2</version>
+                <configuration>
+                    <createDependencyReducedPom>false</createDependencyReducedPom>
+                    <filters>
+                        <filter>
+                            <artifact>*:*</artifact>
+                            <excludes>
+                                <exclude>META-INF/*.SF</exclude>
+                                <exclude>META-INF/*.DSA</exclude>
+                                <exclude>META-INF/*.RSA</exclude>
+                            </excludes>
+                        </filter>
+                    </filters>
+                </configuration>
+                <executions>
+                    <execution>
+                        <phase>package</phase>
+                        <goals>
+                            <goal>shade</goal>
+                        </goals>
+                        <configuration>
+                            <transformers>
+                                <transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/>
+                                <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
+                                    <mainClass>org.apache.curator.x.rest.dropwizard.CuratorApplication</mainClass>
+                                </transformer>
+                            </transformers>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+</project>

http://git-wip-us.apache.org/repos/asf/curator/blob/4ab6476c/curator-x-rest/src/site/confluence/index.confluence
----------------------------------------------------------------------
diff --git a/curator-x-rest/src/site/confluence/index.confluence b/curator-x-rest/src/site/confluence/index.confluence
index 5303b40..d81c9a8 100644
--- a/curator-x-rest/src/site/confluence/index.confluence
+++ b/curator-x-rest/src/site/confluence/index.confluence
@@ -1,8 +1,6 @@
 h1. Curator REST Proxy
 
-h2. Packaging
-Curator REST Proxy is in its own package in Maven Central: {{curator-x-rest}}
+NOTE: Curator REST Proxy is in its own package in Maven Central: {{curator-x-rest}}
 
-h2. Description
 The Curator REST module implements a proxy that bridges non-java environments with the Curator framework and recipes. *TBD*
 

http://git-wip-us.apache.org/repos/asf/curator/blob/4ab6476c/curator-x-rest/src/site/site.xml
----------------------------------------------------------------------
diff --git a/curator-x-rest/src/site/site.xml b/curator-x-rest/src/site/site.xml
index fe42cef..5f9c307 100644
--- a/curator-x-rest/src/site/site.xml
+++ b/curator-x-rest/src/site/site.xml
@@ -1,22 +1,24 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<!--~
-  ~ Licensed to the Apache Software Foundation (ASF) under one
-  ~ or more contributor license agreements.  See the NOTICE file
-  ~ distributed with this work for additional information
-  ~ regarding copyright ownership.  The ASF licenses this file
-  ~ to you under the Apache License, Version 2.0 (the
-  ~ "License"); you may not use this file except in compliance
-  ~ with the License.  You may obtain a copy of the License at
-  ~
-  ~   http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing,
-  ~ software distributed under the License is distributed on an
-  ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-  ~ KIND, either express or implied.  See the License for the
-  ~ specific language governing permissions and limitations
-  ~ under the License.
-  -->
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one
+    or more contributor license agreements.  See the NOTICE file
+    distributed with this work for additional information
+    regarding copyright ownership.  The ASF licenses this file
+    to you under the Apache License, Version 2.0 (the
+    "License"); you may not use this file except in compliance
+    with the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing,
+    software distributed under the License is distributed on an
+    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+    KIND, either express or implied.  See the License for the
+    specific language governing permissions and limitations
+    under the License.
+
+-->
 <project xmlns="http://maven.apache.org/DECORATION/1.1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/DECORATION/1.1.0 http://maven.apache.org/xsd/decoration-1.1.0.xsd" name="Discovery Service Server">
     <body>
         <head>

http://git-wip-us.apache.org/repos/asf/curator/blob/4ab6476c/curator-x-rest/src/test/java/org/apache/curator/x/rest/dropwizard/DropwizardRunner.java
----------------------------------------------------------------------
diff --git a/curator-x-rest/src/test/java/org/apache/curator/x/rest/dropwizard/DropwizardRunner.java b/curator-x-rest/src/test/java/org/apache/curator/x/rest/dropwizard/DropwizardRunner.java
index 44e2194..4d81ae9 100644
--- a/curator-x-rest/src/test/java/org/apache/curator/x/rest/dropwizard/DropwizardRunner.java
+++ b/curator-x-rest/src/test/java/org/apache/curator/x/rest/dropwizard/DropwizardRunner.java
@@ -19,37 +19,10 @@
 
 package org.apache.curator.x.rest.dropwizard;
 
-import io.dropwizard.Application;
-import io.dropwizard.Configuration;
-import io.dropwizard.setup.Bootstrap;
-import io.dropwizard.setup.Environment;
-import org.apache.curator.framework.CuratorFramework;
-import org.apache.curator.framework.CuratorFrameworkFactory;
-import org.apache.curator.retry.ExponentialBackoffRetry;
-
 public class DropwizardRunner
 {
     public static void main(String[] args) throws Exception
     {
-        Application<Configuration> application = new Application<Configuration>()
-        {
-            @Override
-            public void initialize(Bootstrap<Configuration> bootstrap)
-            {
-                CuratorFramework client = CuratorFrameworkFactory.newClient("localhost:2181", new ExponentialBackoffRetry(100, 3));
-                client.start();
-                bootstrap.addBundle(new CuratorRestBundle(client, 60000));
-            }
-
-            @Override
-            public void run(Configuration configuration, Environment environment) throws Exception
-            {
-            }
-        };
-        if ( args.length == 0 )
-        {
-            args = new String[]{"server"};
-        }
-        application.run(args);
+        CuratorApplication.main(args);
     }
 }


[4/4] git commit: doc continues

Posted by ra...@apache.org.
doc continues


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

Branch: refs/heads/CURATOR-88
Commit: b4c76c79bcc3f2e1ffcb0dcf32854255ffa9d126
Parents: 3267285
Author: randgalt <ra...@apache.org>
Authored: Tue Feb 18 10:48:30 2014 +0100
Committer: randgalt <ra...@apache.org>
Committed: Tue Feb 18 10:48:30 2014 +0100

----------------------------------------------------------------------
 .../curator/x/rest/api/ClientResource.java      |  40 +++++--
 .../apache/curator/x/rest/api/Constants.java    |   1 -
 .../curator/x/rest/api/LeaderResource.java      |  36 ++++++-
 .../x/rest/api/PathChildrenCacheResource.java   |   2 +-
 .../x/rest/api/RestBackgroundCallback.java      |   8 +-
 .../org/apache/curator/x/rest/api/Session.java  |   2 +-
 .../curator/x/rest/entities/LeaderSpec.java     |  14 +--
 .../x/rest/entities/ParticipantSpec.java        |  60 +++++++++++
 curator-x-rest/src/site/assets/client.png       | Bin 100105 -> 0 bytes
 .../src/site/confluence/apis.confluence         |  56 ++++++++++
 .../src/site/confluence/entities.confluence     |  86 +++++++++++++++
 .../src/site/confluence/index.confluence        | 108 ++-----------------
 .../src/site/confluence/status.confluence       |  75 +++++++++++++
 .../src/site/resources/images/client.png        | Bin 0 -> 100105 bytes
 14 files changed, 365 insertions(+), 123 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/curator/blob/b4c76c79/curator-x-rest/src/main/java/org/apache/curator/x/rest/api/ClientResource.java
----------------------------------------------------------------------
diff --git a/curator-x-rest/src/main/java/org/apache/curator/x/rest/api/ClientResource.java b/curator-x-rest/src/main/java/org/apache/curator/x/rest/api/ClientResource.java
index d866a21..49e3789 100644
--- a/curator-x-rest/src/main/java/org/apache/curator/x/rest/api/ClientResource.java
+++ b/curator-x-rest/src/main/java/org/apache/curator/x/rest/api/ClientResource.java
@@ -75,7 +75,7 @@ public class ClientResource
     public Response getStatusWithTouch(List<String> ids) throws IOException
     {
         ObjectNode node = context.getMapper().createObjectNode();
-        node.put("state", context.getConnectionState().name());
+        node.put("state", context.getConnectionState().name().toLowerCase());
         node.putPOJO("messages", context.getSession().drainMessages());
 
         for ( String id : ids )
@@ -213,11 +213,16 @@ public class ClientResource
                 @Override
                 protected String getMessage(CuratorEvent event)
                 {
-                    if ( event.getResultCode() != 0 )
+                    PathAndId pathAndId = new PathAndId(String.valueOf(event.getName()), id);
+                    try
+                    {
+                        return context.getWriter().writeValueAsString(pathAndId);
+                    }
+                    catch ( IOException e )
                     {
-                        return Constants.ERROR;
+                        log.error("Could not serialize PathAndId", e);
                     }
-                    return event.getName();
+                    return "{}";
                 }
 
                 @Override
@@ -261,7 +266,11 @@ public class ClientResource
                 @Override
                 protected String getMessage(CuratorEvent event)
                 {
-                    return (event.getData() != null) ? new String(event.getData()) : "";
+                    if ( event.getResultCode() == 0 )
+                    {
+                        return (event.getData() != null) ? new String(event.getData()) : "";
+                    }
+                    return "";
                 }
             };
             castBuilder(builder, Backgroundable.class).inBackground(backgroundCallback);
@@ -297,7 +306,26 @@ public class ClientResource
 
         if ( existsSpec.isAsync() )
         {
-            BackgroundCallback backgroundCallback = new RestBackgroundCallback(context, Constants.CLIENT_EXISTS_ASYNC, existsSpec.getAsyncId());
+            BackgroundCallback backgroundCallback = new RestBackgroundCallback(context, Constants.CLIENT_EXISTS_ASYNC, existsSpec.getAsyncId())
+            {
+                @Override
+                protected String getMessage(CuratorEvent event)
+                {
+                    Stat stat = event.getStat();
+                    if ( stat != null )
+                    {
+                        try
+                        {
+                            return context.getWriter().writeValueAsString(stat);
+                        }
+                        catch ( IOException e )
+                        {
+                            log.error("Could not serialize stat object", e);
+                        }
+                    }
+                    return "{}";
+                }
+            };
             castBuilder(builder, Backgroundable.class).inBackground(backgroundCallback);
         }
 

http://git-wip-us.apache.org/repos/asf/curator/blob/b4c76c79/curator-x-rest/src/main/java/org/apache/curator/x/rest/api/Constants.java
----------------------------------------------------------------------
diff --git a/curator-x-rest/src/main/java/org/apache/curator/x/rest/api/Constants.java b/curator-x-rest/src/main/java/org/apache/curator/x/rest/api/Constants.java
index a516322..5ee1982 100644
--- a/curator-x-rest/src/main/java/org/apache/curator/x/rest/api/Constants.java
+++ b/curator-x-rest/src/main/java/org/apache/curator/x/rest/api/Constants.java
@@ -34,7 +34,6 @@ class Constants
     static final String CLIENT_SET_DATA_ASYNC = "client-set-data-async";
     static final String CLIENT_EXISTS_ASYNC = "client-exists-async";
     static final String CLIENT_DELETE_ASYNC = "client-delete-async";
-    static final String ERROR = "error";
     static final String WATCH = "watch";
     static final String PATH_CACHE = "path-cache";
     static final String NODE_CACHE = "node-cache";

http://git-wip-us.apache.org/repos/asf/curator/blob/b4c76c79/curator-x-rest/src/main/java/org/apache/curator/x/rest/api/LeaderResource.java
----------------------------------------------------------------------
diff --git a/curator-x-rest/src/main/java/org/apache/curator/x/rest/api/LeaderResource.java b/curator-x-rest/src/main/java/org/apache/curator/x/rest/api/LeaderResource.java
index 2590597..43316a1 100644
--- a/curator-x-rest/src/main/java/org/apache/curator/x/rest/api/LeaderResource.java
+++ b/curator-x-rest/src/main/java/org/apache/curator/x/rest/api/LeaderResource.java
@@ -18,24 +18,33 @@
  */
 package org.apache.curator.x.rest.api;
 
+import com.google.common.base.Function;
+import com.google.common.collect.Lists;
 import org.apache.curator.framework.recipes.leader.LeaderLatch;
 import org.apache.curator.framework.recipes.leader.LeaderLatchListener;
+import org.apache.curator.framework.recipes.leader.Participant;
 import org.apache.curator.x.rest.CuratorRestContext;
 import org.apache.curator.x.rest.entities.LeaderSpec;
+import org.apache.curator.x.rest.entities.ParticipantSpec;
 import org.apache.curator.x.rest.entities.StatusMessage;
 import org.codehaus.jackson.node.ObjectNode;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
+import javax.annotation.Nullable;
 import javax.ws.rs.Consumes;
 import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
 import javax.ws.rs.POST;
 import javax.ws.rs.Path;
 import javax.ws.rs.PathParam;
 import javax.ws.rs.Produces;
 import javax.ws.rs.core.Context;
+import javax.ws.rs.core.GenericEntity;
 import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Response;
 import java.io.IOException;
+import java.util.Collection;
+import java.util.List;
 
 @Path("/curator/v1/recipes/leader")
 public class LeaderResource
@@ -53,7 +62,7 @@ public class LeaderResource
     @Produces(MediaType.APPLICATION_JSON)
     public Response startLeaderSelection(final LeaderSpec leaderSpec) throws Exception
     {
-        LeaderLatch leaderLatch = new LeaderLatch(context.getClient(), leaderSpec.getPath(), leaderSpec.getId());
+        LeaderLatch leaderLatch = new LeaderLatch(context.getClient(), leaderSpec.getPath(), leaderSpec.getParticipantId());
         leaderLatch.start();
 
         Closer<LeaderLatch> closer = new Closer<LeaderLatch>()
@@ -101,4 +110,29 @@ public class LeaderResource
         leaderLatch.close();
         return Response.ok().build();
     }
+
+    @GET
+    @Path("{leader-id}")
+    public Response getParticipants(@PathParam("leader-id") String leaderId) throws Exception
+    {
+        LeaderLatch leaderLatch = Constants.getThing(context.getSession(), leaderId, LeaderLatch.class);
+        Collection<Participant> participants = leaderLatch.getParticipants();
+
+        List<ParticipantSpec> transformed = Lists.transform
+        (
+            Lists.newArrayList(participants),
+            new Function<Participant, ParticipantSpec>()
+            {
+                @Nullable
+                @Override
+                public ParticipantSpec apply(Participant participant)
+                {
+                    return new ParticipantSpec(participant.getId(), participant.isLeader());
+                }
+            }
+        );
+
+        GenericEntity<List<ParticipantSpec>> entity = new GenericEntity<List<ParticipantSpec>>(transformed){};
+        return Response.ok(entity).build();
+    }
 }

http://git-wip-us.apache.org/repos/asf/curator/blob/b4c76c79/curator-x-rest/src/main/java/org/apache/curator/x/rest/api/PathChildrenCacheResource.java
----------------------------------------------------------------------
diff --git a/curator-x-rest/src/main/java/org/apache/curator/x/rest/api/PathChildrenCacheResource.java b/curator-x-rest/src/main/java/org/apache/curator/x/rest/api/PathChildrenCacheResource.java
index 76fae7d..4622ac1 100644
--- a/curator-x-rest/src/main/java/org/apache/curator/x/rest/api/PathChildrenCacheResource.java
+++ b/curator-x-rest/src/main/java/org/apache/curator/x/rest/api/PathChildrenCacheResource.java
@@ -84,7 +84,7 @@ public class PathChildrenCacheResource
             @Override
             public void childEvent(CuratorFramework client, PathChildrenCacheEvent event) throws Exception
             {
-                context.getSession().pushMessage(new StatusMessage(Constants.PATH_CACHE, id, event.getType().name(), ""));
+                context.getSession().pushMessage(new StatusMessage(Constants.PATH_CACHE, id, event.getType().name().toLowerCase(), event.getData().getPath()));
             }
         };
         cache.getListenable().addListener(listener);

http://git-wip-us.apache.org/repos/asf/curator/blob/b4c76c79/curator-x-rest/src/main/java/org/apache/curator/x/rest/api/RestBackgroundCallback.java
----------------------------------------------------------------------
diff --git a/curator-x-rest/src/main/java/org/apache/curator/x/rest/api/RestBackgroundCallback.java b/curator-x-rest/src/main/java/org/apache/curator/x/rest/api/RestBackgroundCallback.java
index a5e2284..a8231bb 100644
--- a/curator-x-rest/src/main/java/org/apache/curator/x/rest/api/RestBackgroundCallback.java
+++ b/curator-x-rest/src/main/java/org/apache/curator/x/rest/api/RestBackgroundCallback.java
@@ -43,13 +43,13 @@ class RestBackgroundCallback implements BackgroundCallback
         context.getSession().pushMessage(new StatusMessage(type, asyncId, getMessage(event), getDetails(event)));
     }
 
-    protected String getDetails(CuratorEvent event)
+    protected String getMessage(CuratorEvent event)
     {
-        return Integer.toString(event.getResultCode());
+        return String.valueOf(event.getPath());
     }
 
-    protected String getMessage(CuratorEvent event)
+    protected String getDetails(CuratorEvent event)
     {
-        return String.valueOf(event.getName());
+        return Integer.toString(event.getResultCode());
     }
 }

http://git-wip-us.apache.org/repos/asf/curator/blob/b4c76c79/curator-x-rest/src/main/java/org/apache/curator/x/rest/api/Session.java
----------------------------------------------------------------------
diff --git a/curator-x-rest/src/main/java/org/apache/curator/x/rest/api/Session.java b/curator-x-rest/src/main/java/org/apache/curator/x/rest/api/Session.java
index 36a2654..1a487f8 100644
--- a/curator-x-rest/src/main/java/org/apache/curator/x/rest/api/Session.java
+++ b/curator-x-rest/src/main/java/org/apache/curator/x/rest/api/Session.java
@@ -75,7 +75,7 @@ public class Session implements Closeable
             if ( elapsedSinceLastUse > sessionLengthMs )
             {
                 String id = mapEntry.getKey();
-                pushMessage(new StatusMessage(Constants.EXPIRED, id, "expired", entry.thing.getClass().getName()));
+                pushMessage(new StatusMessage(Constants.EXPIRED, id, entry.thing.getClass().getSimpleName(), ""));
                 log.warn(String.format("Expiring object. Elapsed time: %d, id: %s, Class: %s", elapsedSinceLastUse, id, entry.thing.getClass().getName()));
 
                 things.remove(id);

http://git-wip-us.apache.org/repos/asf/curator/blob/b4c76c79/curator-x-rest/src/main/java/org/apache/curator/x/rest/entities/LeaderSpec.java
----------------------------------------------------------------------
diff --git a/curator-x-rest/src/main/java/org/apache/curator/x/rest/entities/LeaderSpec.java b/curator-x-rest/src/main/java/org/apache/curator/x/rest/entities/LeaderSpec.java
index fde9701..0af2a89 100644
--- a/curator-x-rest/src/main/java/org/apache/curator/x/rest/entities/LeaderSpec.java
+++ b/curator-x-rest/src/main/java/org/apache/curator/x/rest/entities/LeaderSpec.java
@@ -24,17 +24,17 @@ import javax.xml.bind.annotation.XmlRootElement;
 public class LeaderSpec
 {
     private String path;
-    private String id;
+    private String participantId;
 
     public LeaderSpec()
     {
         this("/", "");
     }
 
-    public LeaderSpec(String path, String id)
+    public LeaderSpec(String path, String participantId)
     {
         this.path = path;
-        this.id = id;
+        this.participantId = participantId;
     }
 
     public String getPath()
@@ -47,13 +47,13 @@ public class LeaderSpec
         this.path = path;
     }
 
-    public String getId()
+    public String getParticipantId()
     {
-        return id;
+        return participantId;
     }
 
-    public void setId(String id)
+    public void setParticipantId(String participantId)
     {
-        this.id = id;
+        this.participantId = participantId;
     }
 }

http://git-wip-us.apache.org/repos/asf/curator/blob/b4c76c79/curator-x-rest/src/main/java/org/apache/curator/x/rest/entities/ParticipantSpec.java
----------------------------------------------------------------------
diff --git a/curator-x-rest/src/main/java/org/apache/curator/x/rest/entities/ParticipantSpec.java b/curator-x-rest/src/main/java/org/apache/curator/x/rest/entities/ParticipantSpec.java
new file mode 100644
index 0000000..b695e59
--- /dev/null
+++ b/curator-x-rest/src/main/java/org/apache/curator/x/rest/entities/ParticipantSpec.java
@@ -0,0 +1,60 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.curator.x.rest.entities;
+
+import javax.xml.bind.annotation.XmlRootElement;
+
+@XmlRootElement
+public class ParticipantSpec
+{
+    private String participantId;
+    private boolean isLeader;
+
+    public ParticipantSpec()
+    {
+        this("", false);
+    }
+
+    public ParticipantSpec(String participantId, boolean isLeader)
+    {
+        this.participantId = participantId;
+        this.isLeader = isLeader;
+    }
+
+    public String getParticipantId()
+    {
+        return participantId;
+    }
+
+    public void setParticipantId(String participantId)
+    {
+        this.participantId = participantId;
+    }
+
+    public boolean isLeader()
+    {
+        return isLeader;
+    }
+
+    public void setLeader(boolean isLeader)
+    {
+        this.isLeader = isLeader;
+    }
+}

http://git-wip-us.apache.org/repos/asf/curator/blob/b4c76c79/curator-x-rest/src/site/assets/client.png
----------------------------------------------------------------------
diff --git a/curator-x-rest/src/site/assets/client.png b/curator-x-rest/src/site/assets/client.png
deleted file mode 100644
index 27d10c2..0000000
Binary files a/curator-x-rest/src/site/assets/client.png and /dev/null differ

http://git-wip-us.apache.org/repos/asf/curator/blob/b4c76c79/curator-x-rest/src/site/confluence/apis.confluence
----------------------------------------------------------------------
diff --git a/curator-x-rest/src/site/confluence/apis.confluence b/curator-x-rest/src/site/confluence/apis.confluence
new file mode 100644
index 0000000..abde4ca
--- /dev/null
+++ b/curator-x-rest/src/site/confluence/apis.confluence
@@ -0,0 +1,56 @@
+[[Curator REST Proxy|index.html]] / APIs
+
+h1. APIs
+
+Here are the available APIs:
+
+h2. Status APIs
+
+||URL||Method||Request Entity||Response Entity||Description||
+|/curator/v1/client/status|GET|n/a|Status|Call to get the status of the Curator connection as well as any pending messages.|
+|/curator/v1/client/status|POST|List of string ids|Status|Call to get the status of the Curator connection as well as any pending messages. Additionally, stateful instances with the specified IDs are "touched" thus preventing timeout expiration.|
+
+h2. Client APIs
+
+NOTE: Not all combinations are valid *TBD*
+
+||URL||Method||Request Entity||Response Entity||Description||
+|/get-children|POST|GetChildrenSpec|Array of strings|This is the equivalent of CuratorFramework.getChildren().|
+|/create|POST|CreateSpec|PathAndId|This is the equivalent of CuratorFramework.create().|
+|/delete|POST|DeleteSpec|n/a|This is the equivalent of CuratorFramework.delete().|
+|/set-data|POST|SetDataSpec|n/a|This is the equivalent of CuratorFramework.setData().|
+|/get-data|POST|GetDataSpec|DataAndStat|This is the equivalent of CuratorFramework.setData().|
+|/exists|POST|ExistsSpec|ZK Stat or empty|This is the equivalent of CuratorFramework.exists().|
+
+h3. How Asynchronous APIs Are Handled
+
+*TBD*
+
+h3. How Watchers Are Handled
+
+*TBD*
+
+h3. How Ephemeral Nodes Are Handled
+
+*TBD*
+
+h2. Recipe APIs
+||URL||Method||Request Entity||Response Entity||Description||
+|/curator/v1/recipes/lock|POST|LockSpec|IdSpec|An InterProcessSemaphoreMutex. On successful return, your client will be holding the specified lock until you delete the lock via the delete API.|
+|/curator/v1/recipes/lock/{lock-id}|DELETE|n/a|n/a|Release and delete a lock.|
+|/curator/v1/recipes/leader|POST|LeaderSpec|IdSpec|Start a LeaderLatch instance. When you gain leadership, it will be notified via status.|
+|/curator/v1/recipes/leader/{leader-id}|DELETE|n/a|n/a|Release/delete leadership.|
+|/curator/v1/recipes/leader/{leader-id}|GET|n/a|array of ParticipantSpecs|List of participants in the leader election.|
+
+h3. Handling Timeouts, Status and Releasing
+
+*TBD - releases must go to same server, etc.
+
+h2. Entities
+
+See the [[Entity Descriptions Page|entities.html]] for details on the Entities used in the APIs.
+
+h2. Status Message Types
+
+See the [[Status Message Page|status.html]] for details of the status messages for each type.
+

http://git-wip-us.apache.org/repos/asf/curator/blob/b4c76c79/curator-x-rest/src/site/confluence/entities.confluence
----------------------------------------------------------------------
diff --git a/curator-x-rest/src/site/confluence/entities.confluence b/curator-x-rest/src/site/confluence/entities.confluence
new file mode 100644
index 0000000..dcf6bc5
--- /dev/null
+++ b/curator-x-rest/src/site/confluence/entities.confluence
@@ -0,0 +1,86 @@
+[[Curator REST Proxy|index.html]] / Entity Descriptions
+
+h1. Entity Descriptions
+
+Here are the entity descriptions for the entities used in the APIs:
+
+||Field||Type||Description||
+|*Status*| | |
+|state|string|This instance's Curator connection state. One of: "connected", "suspended", or "lost". If the state is other than "connected" you must assume that any open locks and/or watchers are no longer valid.|
+|messages|array of StatusMessages|Any pending messages from this instance.|
+| | | |
+|*StatusMessage*| | |
+|type|string|The status message type. See the Managing Status section for details.|
+|message|string|Type-dependent message|
+|details|string|Type-dependent details|
+|sourceId|string|Type-dependent sourceId|
+| | | |
+|*GetChildrenSpec*| | |
+|path|string|The ZK path|
+|async|boolean|If true, perform asynchronously|
+|asyncId|string|for async, a user-defined ID to return in the status message|
+|asyncListSeparator|string|for async, the separator to use for the child names. Usually you'd set this to ",".|
+|watched|boolean|if true, set a watch|
+|watchId|string|if watched, a user-defined ID to return in the status when the watch triggers|
+| | | |
+|*CreateSpec*| | |
+|path|string|The ZK path|
+|data|string|The data to store in the node|
+|mode|string|The create mode. One of: "persistent", "persistent_sequential", "ephemeral", or "ephemeral_sequential"|
+| | | |
+| *PathAndId* | | |
+|path|string|The created ZK Path (possibly with a sequence suffix)|
+|id|string|The internally generated id for this node (used for ephemerals)|
+| | | |
+| *DeleteSpec* | | |
+|path|string|The ZK path|
+|async|boolean|If true, perform asynchronously|
+|asyncId|string|for async, a user-defined ID to return in the status message|
+|guaranteed|boolean|if true, use Curator's guaranteed delete mechanism|
+|version|int|the expected version to delete or -1|
+| | | |
+| *SetDataSpec* | | |
+|path|string|The ZK path|
+|data|string|The data to set|
+|async|boolean|If true, perform asynchronously|
+|asyncId|string|for async, a user-defined ID to return in the status message|
+|watched|boolean|if true, set a watch|
+|watchId|string|if watched, a user-defined ID to return in the status when the watch triggers|
+|compressed|boolean|if true, compress the data using Curator's compression mechanism|
+|version|int|the expected version or -1|
+| | | |
+| *GetDataSpec* | | |
+|path|string|The ZK path|
+|async|boolean|If true, perform asynchronously|
+|asyncId|string|for async, a user-defined ID to return in the status message|
+|watched|boolean|if true, set a watch|
+|watchId|string|if watched, a user-defined ID to return in the status when the watch triggers|
+|decompressed|boolean|if true, decompress the data using Curator's compression mechanism|
+| | | |
+| *DataAndStat* | | |
+|data|string|the data from the node|
+|stat|ZK Stat|the ZooKeeper stat for the node|
+| | | |
+| *ExistsSpec* | | |
+|path|string|The ZK path|
+|async|boolean|If true, perform asynchronously|
+|asyncId|string|for async, a user-defined ID to return in the status message|
+|watched|boolean|if true, set a watch|
+|watchId|string|if watched, a user-defined ID to return in the status when the watch triggers|
+| | | |
+| *IdSpec* | | |
+|id|string|The ID of the created recipe, etc. Used for subsequent calls to delete, close, etc. the instance.|
+| | | |
+| *LockSpec* | | |
+|path|string|The ZK path|
+|maxWaitMs|int|Maximum time to wait to acquire the lock (in milliseconds)|
+| | | |
+| *LeaderSpec* | | |
+|path|string|The ZK path|
+|maxWaitMs|int|Maximum time to wait to acquire the lock (in milliseconds)|
+| | | |
+| *ParticipantSpec* | | |
+|participantId|string|The participant ID|
+|isLeader|boolean|true if this is the leader|
+
+*TBD*

http://git-wip-us.apache.org/repos/asf/curator/blob/b4c76c79/curator-x-rest/src/site/confluence/index.confluence
----------------------------------------------------------------------
diff --git a/curator-x-rest/src/site/confluence/index.confluence b/curator-x-rest/src/site/confluence/index.confluence
index 22755d5..da36433 100644
--- a/curator-x-rest/src/site/confluence/index.confluence
+++ b/curator-x-rest/src/site/confluence/index.confluence
@@ -8,6 +8,8 @@ any language.
 
 *TBD*
 
+!images/client.png!
+
 h2. Building and Packaging
 
 Dropwizard
@@ -32,111 +34,13 @@ h2. Managing Status
 
 *TBD*
 
-h2. Status APIs
-
-||URL||METHOD||Request Entity||Response Entity||Description||
-|/curator/v1/client/status|GET|n/a|Status|Call to get the status of the Curator connection as well as any pending messages.|
-|/curator/v1/client/status|POST|List of string ids|Status|Call to get the status of the Curator connection as well as any pending messages. Additionally, stateful instances with the specified IDs are "touched" thus preventing timeout expiration.|
-
-h2. Client APIs
-
-NOTE: Not all combinations are valid *TBD*
-
-||URL||METHOD||Request Entity||Response Entity||Description||
-|/get-children|POST|GetChildrenSpec|Array of strings|This is the equivalent of CuratorFramework.getChildren().|
-|/create|POST|CreateSpec|PathAndId|This is the equivalent of CuratorFramework.create().|
-|/delete|POST|DeleteSpec|n/a|This is the equivalent of CuratorFramework.delete().|
-|/set-data|POST|SetDataSpec|n/a|This is the equivalent of CuratorFramework.setData().|
-|/get-data|POST|GetDataSpec|DataAndStat|This is the equivalent of CuratorFramework.setData().|
-|/exists|POST|ExistsSpec|ZK Stat or empty|This is the equivalent of CuratorFramework.exists().|
-
-h3. How Asynchronous APIs Are Handled
-
-*TBD*
-
-h3. How Watchers Are Handled
-
-*TBD*
-
-h3. How Ephemeral Nodes Are Handled
+See the [[Status Message Page|status.html]] for details of the status messages for each type.
 
-*TBD*
-
-h2. Recipe APIs
-||URL||METHOD||Request Entity||Response Entity||Description||
-|/curator/v1/recipes/lock|POST|LockSpec|IdSpec|An InterProcessSemaphoreMutex. On successful return, your client will be holding the specified lock until you delete the lock via the delete API.|
-|/curator/v1/recipes/lock/{lock-id}|DELETE|n/a|n/a|Release and delete a lock.|
-|/curator/v1/recipes/leader|POST|LeaderSpec|IdSpec|Start a LeaderLatch instance. When you gain leadership, it will be notified via status.|
-|/curator/v1/recipes/leader/{leader-id}|DELETE|n/a|n/a|Release/delete leadership.|
+h2. APIs
 
-h3. Handling Timeouts, Status and Releasing
-
-*TBD - releases must go to same server, etc.
+See the [[APIs Page|apis.html]] for list of available APIs.
 
 h2. Entities
 
-||Field||Type||Description||
-|*Status*| | |
-|state|string|This instance's Curator connection state. One of: "connected", "suspended", or "lost". If the state is other than "connected" you must assume that any open locks and/or watchers are no longer valid.|
-|messages|array of StatusMessages|Any pending messages from this instance.|
-| | | |
-|*StatusMessage*| | |
-|type|string|The status message type. See the Managing Status section for details.|
-|message|string|Type-dependent message|
-|details|string|Type-dependent details|
-|sourceId|string|Type-dependent sourceId|
-| | | |
-|*GetChildrenSpec*| | |
-|path|string|The ZK path|
-|async|boolean|If true, perform asynchronously|
-|asyncId|string|for async, a user-defined ID to return in the status message|
-|asyncListSeparator|string|for async, the separator to use for the child names. Usually you'd set this to ",".|
-|watched|boolean|if true, set a watch|
-|watchId|string|if watched, a user-defined ID to return in the status when the watch triggers|
-| | | |
-|*CreateSpec*| | |
-|path|string|The ZK path|
-|data|string|The data to store in the node|
-|mode|string|The create mode. One of: "persistent", "persistent_sequential", "ephemeral", or "ephemeral_sequential"|
-| | | |
-| *PathAndId* | | |
-|path|string|The created ZK Path (possibly with a sequence suffix)|
-|id|string|The internally generated id for this node (used for ephemerals)|
-| | | |
-| *DeleteSpec* | | |
-|path|string|The ZK path|
-|async|boolean|If true, perform asynchronously|
-|asyncId|string|for async, a user-defined ID to return in the status message|
-|guaranteed|boolean|if true, use Curator's guaranteed delete mechanism|
-|version|int|the expected version to delete or -1|
-| | | |
-| *SetDataSpec* | | |
-|path|string|The ZK path|
-|data|string|The data to set|
-|async|boolean|If true, perform asynchronously|
-|asyncId|string|for async, a user-defined ID to return in the status message|
-|watched|boolean|if true, set a watch|
-|watchId|string|if watched, a user-defined ID to return in the status when the watch triggers|
-|compressed|boolean|if true, compress the data using Curator's compression mechanism|
-|version|int|the expected version or -1|
-| | | |
-| *GetDataSpec* | | |
-|path|string|The ZK path|
-|async|boolean|If true, perform asynchronously|
-|asyncId|string|for async, a user-defined ID to return in the status message|
-|watched|boolean|if true, set a watch|
-|watchId|string|if watched, a user-defined ID to return in the status when the watch triggers|
-|decompressed|boolean|if true, decompress the data using Curator's compression mechanism|
-| | | |
-| *DataAndStat* | | |
-|data|string|the data from the node|
-|stat|ZK Stat|the ZooKeeper stat for the node|
-| | | |
-| *ExistsSpec* | | |
-|path|string|The ZK path|
-|async|boolean|If true, perform asynchronously|
-|asyncId|string|for async, a user-defined ID to return in the status message|
-|watched|boolean|if true, set a watch|
-|watchId|string|if watched, a user-defined ID to return in the status when the watch triggers|
+See the [[Entity Descriptions Page|entities.html]] for details on the Entities used in the APIs.
 
-*TBD*

http://git-wip-us.apache.org/repos/asf/curator/blob/b4c76c79/curator-x-rest/src/site/confluence/status.confluence
----------------------------------------------------------------------
diff --git a/curator-x-rest/src/site/confluence/status.confluence b/curator-x-rest/src/site/confluence/status.confluence
new file mode 100644
index 0000000..5957771
--- /dev/null
+++ b/curator-x-rest/src/site/confluence/status.confluence
@@ -0,0 +1,75 @@
+[[Curator REST Proxy|index.html]] / Status Messages
+
+h1. Status Messages
+
+h2. Status Messages
+
+|*Watchers*| |
+|Type|watch|
+|Source Id|The watchId passed in the original request|
+|Message|Either "NodeCreated", "NodeDeleted", "NodeDataChanged", or "NodeChildrenChanged"|
+|Details|The event path|
+| | |
+|*Expired Instances*| |
+|Type|expired|
+|Source Id|Generated Id of the instance that is expiring|
+|Message|Class name of the expiring instance. Either: "LeaderLatch.class", "InterProcessSemaphoreMutex.class", "NodeCache.class", "PathChildrenCache.class", "PersistentEphemeralNode.class", "InterProcessMutex.class", "LeasesHolder.class" (for semaphores)|
+|Details|n/a|
+
+h2. Asynchronous Client APIs
+
+|API: */curator/v1/client/create*| |
+|Type|client-create-async|
+|Source Id|The asyncId passed in the original request|
+|Message|PathAndId as a JSON string|
+|Details|The ZooKeeper "rc" result code|
+| | |
+|API: */curator/v1/client/delete*| |
+|Type|client-delete-async|
+|Source Id|The asyncId passed in the original request|
+|Message|n/a|
+|Details|The ZooKeeper "rc" result code|
+| | |
+|API: */curator/v1/client/get-children*| |
+|Type|client-get-children-async|
+|Source Id|The asyncId passed in the original request|
+|Message|List of children nodes separated by the value passed as asyncListSeparator in the original request|
+|Details|The ZooKeeper "rc" result code|
+| | |
+|API: */curator/v1/client/set-data*| |
+|Type|client-set-data-async|
+|Source Id|The asyncId passed in the original request|
+|Message|n/a|
+|Details|The ZooKeeper "rc" result code|
+| | |
+|API: */curator/v1/client/get-data*| |
+|Type|client-get-data-async|
+|Source Id|The asyncId passed in the original request|
+|Message|The data|
+|Details|The ZooKeeper "rc" result code|
+| | |
+|API: */curator/v1/client/exists*| |
+|Type|client-exists-async|
+|Source Id|The asyncId passed in the original request|
+|Message|ZK Stat as a JSON string|
+|Details|The ZooKeeper "rc" result code|
+
+h2. Recipe Messages
+
+|API: */curator/v1/recipes/leader*| |
+|Type|leader|
+|Source Id|generated leader Id|
+|Message|"true" if leader, "false" if leadership is lost|
+|Details|n/a|
+| | |
+|API: */curator/v1/recipes/path-cache*| |
+|Type|path-cache|
+|Source Id|generated leader Id|
+|Message|n/a|
+|Details|n/a|
+| | |
+|API: */curator/v1/recipes/node-cache*| |
+|Type|node-cache|
+|Source Id|generated leader Id|
+|Message|Either "child_added", "child_updated", "child_removed", "connection_suspended", "connection_reconnected", "connection_lost", or "initialized"|
+|Details|Node path|

http://git-wip-us.apache.org/repos/asf/curator/blob/b4c76c79/curator-x-rest/src/site/resources/images/client.png
----------------------------------------------------------------------
diff --git a/curator-x-rest/src/site/resources/images/client.png b/curator-x-rest/src/site/resources/images/client.png
new file mode 100644
index 0000000..27d10c2
Binary files /dev/null and b/curator-x-rest/src/site/resources/images/client.png differ


[2/4] git commit: wip

Posted by ra...@apache.org.
wip


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

Branch: refs/heads/CURATOR-88
Commit: 6f21cf5dce1865b873309d3dab9708dce195239d
Parents: 4ab6476
Author: randgalt <ra...@apache.org>
Authored: Mon Feb 17 17:30:37 2014 -0500
Committer: randgalt <ra...@apache.org>
Committed: Mon Feb 17 17:30:37 2014 -0500

----------------------------------------------------------------------
 .../curator/x/rest/dropwizard/CuratorRestBundle.java | 15 +++++++++------
 1 file changed, 9 insertions(+), 6 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/curator/blob/6f21cf5d/curator-x-rest/src/main/java/org/apache/curator/x/rest/dropwizard/CuratorRestBundle.java
----------------------------------------------------------------------
diff --git a/curator-x-rest/src/main/java/org/apache/curator/x/rest/dropwizard/CuratorRestBundle.java b/curator-x-rest/src/main/java/org/apache/curator/x/rest/dropwizard/CuratorRestBundle.java
index 2edc06f..dd8b60a 100644
--- a/curator-x-rest/src/main/java/org/apache/curator/x/rest/dropwizard/CuratorRestBundle.java
+++ b/curator-x-rest/src/main/java/org/apache/curator/x/rest/dropwizard/CuratorRestBundle.java
@@ -63,6 +63,7 @@ public class CuratorRestBundle implements ConfiguredBundle<CuratorConfiguration>
             @Override
             public void lifeCycleStopping(LifeCycle event)
             {
+                closeCuratorClient(context.getClient());
                 context.close();
             }
         };
@@ -71,6 +72,11 @@ public class CuratorRestBundle implements ConfiguredBundle<CuratorConfiguration>
         environment.healthChecks().register("Curator", new CuratorHealthCheck(context));
     }
 
+    protected void closeCuratorClient(CuratorFramework client)
+    {
+        client.close();
+    }
+
     protected CuratorRestContext newCuratorRestContext(CuratorConfiguration configuration)
     {
         CuratorFramework client = newCuratorClient(configuration);
@@ -80,11 +86,8 @@ public class CuratorRestBundle implements ConfiguredBundle<CuratorConfiguration>
     protected CuratorFramework newCuratorClient(CuratorConfiguration configuration)
     {
         ExponentialBackoffRetry retryPolicy = new ExponentialBackoffRetry(configuration.getRetryBaseSleepMs(), configuration.getRetryQty());
-        return CuratorFrameworkFactory.newClient
-        (
-            configuration.getZooKeeperConnectionString(),
-            configuration.getSessionLengthMs(),
-            configuration.getConnectionTimeoutMs(), retryPolicy
-        );
+        CuratorFramework client = CuratorFrameworkFactory.newClient(configuration.getZooKeeperConnectionString(), configuration.getSessionLengthMs(), configuration.getConnectionTimeoutMs(), retryPolicy);
+        client.start();
+        return client;
     }
 }


[3/4] git commit: work on doc for rest

Posted by ra...@apache.org.
work on doc for rest


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

Branch: refs/heads/CURATOR-88
Commit: 32672858843c6514a62ba8b70de17a1948e15384
Parents: 6f21cf5
Author: randgalt <ra...@apache.org>
Authored: Mon Feb 17 21:05:04 2014 -0500
Committer: randgalt <ra...@apache.org>
Committed: Mon Feb 17 21:05:04 2014 -0500

----------------------------------------------------------------------
 .../curator/x/rest/api/ClientResource.java      |   5 +
 .../curator/x/rest/api/LeaderResource.java      |   4 +-
 .../apache/curator/x/rest/api/LockResource.java |   4 +-
 curator-x-rest/src/site/assets/client.png       | Bin 0 -> 100105 bytes
 .../src/site/confluence/index.confluence        | 138 ++++++++++++++++++-
 5 files changed, 146 insertions(+), 5 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/curator/blob/32672858/curator-x-rest/src/main/java/org/apache/curator/x/rest/api/ClientResource.java
----------------------------------------------------------------------
diff --git a/curator-x-rest/src/main/java/org/apache/curator/x/rest/api/ClientResource.java b/curator-x-rest/src/main/java/org/apache/curator/x/rest/api/ClientResource.java
index 2321fa0..d866a21 100644
--- a/curator-x-rest/src/main/java/org/apache/curator/x/rest/api/ClientResource.java
+++ b/curator-x-rest/src/main/java/org/apache/curator/x/rest/api/ClientResource.java
@@ -31,6 +31,7 @@ import org.apache.curator.x.rest.entities.GetDataSpec;
 import org.apache.curator.x.rest.entities.PathAndId;
 import org.apache.curator.x.rest.entities.SetDataSpec;
 import org.apache.zookeeper.CreateMode;
+import org.apache.zookeeper.data.Stat;
 import org.codehaus.jackson.node.ObjectNode;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -266,6 +267,9 @@ public class ClientResource
             castBuilder(builder, Backgroundable.class).inBackground(backgroundCallback);
         }
 
+        Stat stat = new Stat();
+        builder = castBuilder(builder, Statable.class).storingStatIn(stat);
+
         String result = "";
         Object bytes = castBuilder(builder, Pathable.class).forPath(getDataSpec.getPath());
         if ( bytes != null )
@@ -275,6 +279,7 @@ public class ClientResource
 
         ObjectNode node = context.getMapper().createObjectNode();
         node.put("data", result);
+        node.putPOJO("stat", stat);
         return Response.ok(context.getWriter().writeValueAsString(node)).build();
     }
 

http://git-wip-us.apache.org/repos/asf/curator/blob/32672858/curator-x-rest/src/main/java/org/apache/curator/x/rest/api/LeaderResource.java
----------------------------------------------------------------------
diff --git a/curator-x-rest/src/main/java/org/apache/curator/x/rest/api/LeaderResource.java b/curator-x-rest/src/main/java/org/apache/curator/x/rest/api/LeaderResource.java
index e9c7ec4..2590597 100644
--- a/curator-x-rest/src/main/java/org/apache/curator/x/rest/api/LeaderResource.java
+++ b/curator-x-rest/src/main/java/org/apache/curator/x/rest/api/LeaderResource.java
@@ -28,7 +28,7 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import javax.ws.rs.Consumes;
 import javax.ws.rs.DELETE;
-import javax.ws.rs.PUT;
+import javax.ws.rs.POST;
 import javax.ws.rs.Path;
 import javax.ws.rs.PathParam;
 import javax.ws.rs.Produces;
@@ -48,7 +48,7 @@ public class LeaderResource
         this.context = context;
     }
 
-    @PUT
+    @POST
     @Consumes(MediaType.APPLICATION_JSON)
     @Produces(MediaType.APPLICATION_JSON)
     public Response startLeaderSelection(final LeaderSpec leaderSpec) throws Exception

http://git-wip-us.apache.org/repos/asf/curator/blob/32672858/curator-x-rest/src/main/java/org/apache/curator/x/rest/api/LockResource.java
----------------------------------------------------------------------
diff --git a/curator-x-rest/src/main/java/org/apache/curator/x/rest/api/LockResource.java b/curator-x-rest/src/main/java/org/apache/curator/x/rest/api/LockResource.java
index a5eebda..8104858 100644
--- a/curator-x-rest/src/main/java/org/apache/curator/x/rest/api/LockResource.java
+++ b/curator-x-rest/src/main/java/org/apache/curator/x/rest/api/LockResource.java
@@ -26,7 +26,7 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import javax.ws.rs.Consumes;
 import javax.ws.rs.DELETE;
-import javax.ws.rs.PUT;
+import javax.ws.rs.POST;
 import javax.ws.rs.Path;
 import javax.ws.rs.PathParam;
 import javax.ws.rs.Produces;
@@ -46,7 +46,7 @@ public class LockResource
         this.context = context;
     }
 
-    @PUT
+    @POST
     @Consumes(MediaType.APPLICATION_JSON)
     @Produces(MediaType.APPLICATION_JSON)
     public Response acquireLock(final LockSpec lockSpec) throws Exception

http://git-wip-us.apache.org/repos/asf/curator/blob/32672858/curator-x-rest/src/site/assets/client.png
----------------------------------------------------------------------
diff --git a/curator-x-rest/src/site/assets/client.png b/curator-x-rest/src/site/assets/client.png
new file mode 100644
index 0000000..27d10c2
Binary files /dev/null and b/curator-x-rest/src/site/assets/client.png differ

http://git-wip-us.apache.org/repos/asf/curator/blob/32672858/curator-x-rest/src/site/confluence/index.confluence
----------------------------------------------------------------------
diff --git a/curator-x-rest/src/site/confluence/index.confluence b/curator-x-rest/src/site/confluence/index.confluence
index d81c9a8..22755d5 100644
--- a/curator-x-rest/src/site/confluence/index.confluence
+++ b/curator-x-rest/src/site/confluence/index.confluence
@@ -2,5 +2,141 @@ h1. Curator REST Proxy
 
 NOTE: Curator REST Proxy is in its own package in Maven Central: {{curator-x-rest}}
 
-The Curator REST module implements a proxy that bridges non-java environments with the Curator framework and recipes. *TBD*
+The Curator REST module implements a proxy that bridges non-java environments with the Curator framework and recipes. Every major language
+today has a REST library available. With the Curator REST Proxy, you can now take advantage of the Curator framework and its recipes in
+any language.
 
+*TBD*
+
+h2. Building and Packaging
+
+Dropwizard
+
+*TBD*
+
+h2. Deployment
+
+Ideally, co-locate a Curator REST Proxy instance on each ZooKeeper instance. While this isn't a requirement, it is the simplest way to deploy.
+
+*TBD*
+
+h2. Stateful vs Stateless
+
+Some of the Proxy's APIs are stateful and some are stateless. For the Client APIs, if you make a call that is either asynchronous, sets a watcher,
+or creates an ephemeral node, there is some state that is stored. In these cases, you must periodically send a status heartbeat and examine the
+resulting messages. This status heartbeat must be sent to the *same server* to which you originated the request. E.g. if you have 3 Curator REST
+Proxies A, B and C and execute a lock API to server B, you must periodically send a status with the lock's ID to server B. See the section
+below on Managing Status for more details.
+
+h2. Managing Status
+
+*TBD*
+
+h2. Status APIs
+
+||URL||METHOD||Request Entity||Response Entity||Description||
+|/curator/v1/client/status|GET|n/a|Status|Call to get the status of the Curator connection as well as any pending messages.|
+|/curator/v1/client/status|POST|List of string ids|Status|Call to get the status of the Curator connection as well as any pending messages. Additionally, stateful instances with the specified IDs are "touched" thus preventing timeout expiration.|
+
+h2. Client APIs
+
+NOTE: Not all combinations are valid *TBD*
+
+||URL||METHOD||Request Entity||Response Entity||Description||
+|/get-children|POST|GetChildrenSpec|Array of strings|This is the equivalent of CuratorFramework.getChildren().|
+|/create|POST|CreateSpec|PathAndId|This is the equivalent of CuratorFramework.create().|
+|/delete|POST|DeleteSpec|n/a|This is the equivalent of CuratorFramework.delete().|
+|/set-data|POST|SetDataSpec|n/a|This is the equivalent of CuratorFramework.setData().|
+|/get-data|POST|GetDataSpec|DataAndStat|This is the equivalent of CuratorFramework.setData().|
+|/exists|POST|ExistsSpec|ZK Stat or empty|This is the equivalent of CuratorFramework.exists().|
+
+h3. How Asynchronous APIs Are Handled
+
+*TBD*
+
+h3. How Watchers Are Handled
+
+*TBD*
+
+h3. How Ephemeral Nodes Are Handled
+
+*TBD*
+
+h2. Recipe APIs
+||URL||METHOD||Request Entity||Response Entity||Description||
+|/curator/v1/recipes/lock|POST|LockSpec|IdSpec|An InterProcessSemaphoreMutex. On successful return, your client will be holding the specified lock until you delete the lock via the delete API.|
+|/curator/v1/recipes/lock/{lock-id}|DELETE|n/a|n/a|Release and delete a lock.|
+|/curator/v1/recipes/leader|POST|LeaderSpec|IdSpec|Start a LeaderLatch instance. When you gain leadership, it will be notified via status.|
+|/curator/v1/recipes/leader/{leader-id}|DELETE|n/a|n/a|Release/delete leadership.|
+
+h3. Handling Timeouts, Status and Releasing
+
+*TBD - releases must go to same server, etc.
+
+h2. Entities
+
+||Field||Type||Description||
+|*Status*| | |
+|state|string|This instance's Curator connection state. One of: "connected", "suspended", or "lost". If the state is other than "connected" you must assume that any open locks and/or watchers are no longer valid.|
+|messages|array of StatusMessages|Any pending messages from this instance.|
+| | | |
+|*StatusMessage*| | |
+|type|string|The status message type. See the Managing Status section for details.|
+|message|string|Type-dependent message|
+|details|string|Type-dependent details|
+|sourceId|string|Type-dependent sourceId|
+| | | |
+|*GetChildrenSpec*| | |
+|path|string|The ZK path|
+|async|boolean|If true, perform asynchronously|
+|asyncId|string|for async, a user-defined ID to return in the status message|
+|asyncListSeparator|string|for async, the separator to use for the child names. Usually you'd set this to ",".|
+|watched|boolean|if true, set a watch|
+|watchId|string|if watched, a user-defined ID to return in the status when the watch triggers|
+| | | |
+|*CreateSpec*| | |
+|path|string|The ZK path|
+|data|string|The data to store in the node|
+|mode|string|The create mode. One of: "persistent", "persistent_sequential", "ephemeral", or "ephemeral_sequential"|
+| | | |
+| *PathAndId* | | |
+|path|string|The created ZK Path (possibly with a sequence suffix)|
+|id|string|The internally generated id for this node (used for ephemerals)|
+| | | |
+| *DeleteSpec* | | |
+|path|string|The ZK path|
+|async|boolean|If true, perform asynchronously|
+|asyncId|string|for async, a user-defined ID to return in the status message|
+|guaranteed|boolean|if true, use Curator's guaranteed delete mechanism|
+|version|int|the expected version to delete or -1|
+| | | |
+| *SetDataSpec* | | |
+|path|string|The ZK path|
+|data|string|The data to set|
+|async|boolean|If true, perform asynchronously|
+|asyncId|string|for async, a user-defined ID to return in the status message|
+|watched|boolean|if true, set a watch|
+|watchId|string|if watched, a user-defined ID to return in the status when the watch triggers|
+|compressed|boolean|if true, compress the data using Curator's compression mechanism|
+|version|int|the expected version or -1|
+| | | |
+| *GetDataSpec* | | |
+|path|string|The ZK path|
+|async|boolean|If true, perform asynchronously|
+|asyncId|string|for async, a user-defined ID to return in the status message|
+|watched|boolean|if true, set a watch|
+|watchId|string|if watched, a user-defined ID to return in the status when the watch triggers|
+|decompressed|boolean|if true, decompress the data using Curator's compression mechanism|
+| | | |
+| *DataAndStat* | | |
+|data|string|the data from the node|
+|stat|ZK Stat|the ZooKeeper stat for the node|
+| | | |
+| *ExistsSpec* | | |
+|path|string|The ZK path|
+|async|boolean|If true, perform asynchronously|
+|asyncId|string|for async, a user-defined ID to return in the status message|
+|watched|boolean|if true, set a watch|
+|watchId|string|if watched, a user-defined ID to return in the status when the watch triggers|
+
+*TBD*