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/05/30 18:57:26 UTC

[3/3] git commit: initial stab at exception support

initial stab at exception support


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

Branch: refs/heads/curator-rpc
Commit: c6229cf2e09424fc57944397c7186fea2db9a1a4
Parents: 8bfaffd
Author: randgalt <ra...@apache.org>
Authored: Fri May 30 11:57:17 2014 -0500
Committer: randgalt <ra...@apache.org>
Committed: Fri May 30 11:57:17 2014 -0500

----------------------------------------------------------------------
 .../x/rpc/connections/ConnectionManager.java    |    3 +-
 .../curator/x/rpc/connections/CuratorEntry.java |   14 +
 .../x/rpc/idl/exceptions/ExceptionType.java     |    8 +
 .../x/rpc/idl/exceptions/NodeExceptionType.java |    9 +
 .../x/rpc/idl/exceptions/RpcException.java      |   80 +
 .../idl/exceptions/ZooKeeperExceptionType.java  |   22 +
 .../idl/services/CuratorProjectionService.java  |  718 +++--
 .../x/rpc/idl/services/EventService.java        |   17 +-
 curator-x-rpc/src/main/scripts/generate.sh      |    2 +-
 curator-x-rpc/src/main/thrift/curator.thrift    |   57 +-
 .../curator/generated/CuratorException.java     |  736 +++++
 .../curator/generated/CuratorService.java       | 2546 ++++++++++++++++--
 .../apache/curator/generated/EventService.java  |  133 +-
 .../apache/curator/generated/ExceptionType.java |   48 +
 .../curator/generated/NodeExceptionType.java    |   51 +
 .../generated/ZooKeeperExceptionType.java       |   90 +
 .../org/apache/curator/x/rpc/TestClient.java    |   12 +
 17 files changed, 3976 insertions(+), 570 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/curator/blob/c6229cf2/curator-x-rpc/src/main/java/org/apache/curator/x/rpc/connections/ConnectionManager.java
----------------------------------------------------------------------
diff --git a/curator-x-rpc/src/main/java/org/apache/curator/x/rpc/connections/ConnectionManager.java b/curator-x-rpc/src/main/java/org/apache/curator/x/rpc/connections/ConnectionManager.java
index 21fe762..5ee65f4 100644
--- a/curator-x-rpc/src/main/java/org/apache/curator/x/rpc/connections/ConnectionManager.java
+++ b/curator-x-rpc/src/main/java/org/apache/curator/x/rpc/connections/ConnectionManager.java
@@ -89,8 +89,7 @@ public class ConnectionManager implements Closeable
     public CuratorFramework newConnection(String name)
     {
         ConnectionConfiguration configuration = connections.get(name);
-        Preconditions.checkNotNull(configuration, "No connection configuration with that name was found: " + name);
-        return configuration.build();
+        return (configuration != null) ? configuration.build() : null;
     }
 
     public void add(String id, CuratorFramework client)

http://git-wip-us.apache.org/repos/asf/curator/blob/c6229cf2/curator-x-rpc/src/main/java/org/apache/curator/x/rpc/connections/CuratorEntry.java
----------------------------------------------------------------------
diff --git a/curator-x-rpc/src/main/java/org/apache/curator/x/rpc/connections/CuratorEntry.java b/curator-x-rpc/src/main/java/org/apache/curator/x/rpc/connections/CuratorEntry.java
index d5a6d8a..9e57c6f 100644
--- a/curator-x-rpc/src/main/java/org/apache/curator/x/rpc/connections/CuratorEntry.java
+++ b/curator-x-rpc/src/main/java/org/apache/curator/x/rpc/connections/CuratorEntry.java
@@ -3,6 +3,10 @@ package org.apache.curator.x.rpc.connections;
 import com.google.common.collect.Maps;
 import com.google.common.collect.Queues;
 import org.apache.curator.framework.CuratorFramework;
+import org.apache.curator.framework.api.CuratorEvent;
+import org.apache.curator.x.rpc.idl.exceptions.ExceptionType;
+import org.apache.curator.x.rpc.idl.exceptions.RpcException;
+import org.apache.curator.x.rpc.idl.structs.CuratorProjection;
 import org.apache.curator.x.rpc.idl.structs.RpcCuratorEvent;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -82,6 +86,16 @@ public class CuratorEntry implements Closeable
         }
     }
 
+    public static CuratorEntry mustGetEntry(ConnectionManager connectionManager, CuratorProjection projection) throws RpcException
+    {
+        CuratorEntry entry = connectionManager.get(projection.id);
+        if ( entry == null )
+        {
+            throw new RpcException(ExceptionType.GENERAL, null, null, "No CuratorProjection found with the id: " + projection.id);
+        }
+        return entry;
+    }
+
     public CuratorFramework getClient()
     {
         return (state.get() == State.OPEN) ? client : null;

http://git-wip-us.apache.org/repos/asf/curator/blob/c6229cf2/curator-x-rpc/src/main/java/org/apache/curator/x/rpc/idl/exceptions/ExceptionType.java
----------------------------------------------------------------------
diff --git a/curator-x-rpc/src/main/java/org/apache/curator/x/rpc/idl/exceptions/ExceptionType.java b/curator-x-rpc/src/main/java/org/apache/curator/x/rpc/idl/exceptions/ExceptionType.java
new file mode 100644
index 0000000..4879c61
--- /dev/null
+++ b/curator-x-rpc/src/main/java/org/apache/curator/x/rpc/idl/exceptions/ExceptionType.java
@@ -0,0 +1,8 @@
+package org.apache.curator.x.rpc.idl.exceptions;
+
+public enum ExceptionType
+{
+    GENERAL,
+    ZOOKEEPER,
+    NODE
+}

http://git-wip-us.apache.org/repos/asf/curator/blob/c6229cf2/curator-x-rpc/src/main/java/org/apache/curator/x/rpc/idl/exceptions/NodeExceptionType.java
----------------------------------------------------------------------
diff --git a/curator-x-rpc/src/main/java/org/apache/curator/x/rpc/idl/exceptions/NodeExceptionType.java b/curator-x-rpc/src/main/java/org/apache/curator/x/rpc/idl/exceptions/NodeExceptionType.java
new file mode 100644
index 0000000..4ad2488
--- /dev/null
+++ b/curator-x-rpc/src/main/java/org/apache/curator/x/rpc/idl/exceptions/NodeExceptionType.java
@@ -0,0 +1,9 @@
+package org.apache.curator.x.rpc.idl.exceptions;
+
+public enum NodeExceptionType
+{
+    NONODE,
+    BADVERSION,
+    NODEEXISTS,
+    NOTEMPTY
+}

http://git-wip-us.apache.org/repos/asf/curator/blob/c6229cf2/curator-x-rpc/src/main/java/org/apache/curator/x/rpc/idl/exceptions/RpcException.java
----------------------------------------------------------------------
diff --git a/curator-x-rpc/src/main/java/org/apache/curator/x/rpc/idl/exceptions/RpcException.java b/curator-x-rpc/src/main/java/org/apache/curator/x/rpc/idl/exceptions/RpcException.java
new file mode 100644
index 0000000..f3740db
--- /dev/null
+++ b/curator-x-rpc/src/main/java/org/apache/curator/x/rpc/idl/exceptions/RpcException.java
@@ -0,0 +1,80 @@
+package org.apache.curator.x.rpc.idl.exceptions;
+
+import com.facebook.swift.codec.ThriftField;
+import com.facebook.swift.codec.ThriftStruct;
+import com.facebook.swift.service.ThriftException;
+import org.apache.zookeeper.KeeperException;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+
+@ThriftException(id = 1, type = RpcException.class, name = "CuratorException")
+@ThriftStruct("CuratorException")
+public class RpcException extends Exception
+{
+    @ThriftField(1)
+    public ExceptionType type;
+
+    @ThriftField(2)
+    public ZooKeeperExceptionType zooKeeperException;
+
+    @ThriftField(3)
+    public NodeExceptionType nodeException;
+
+    @ThriftField(4)
+    public String message;
+
+    public RpcException()
+    {
+    }
+
+    public RpcException(Exception e)
+    {
+        this.message = e.getLocalizedMessage();
+        if ( this.message == null )
+        {
+            StringWriter str = new StringWriter();
+            e.printStackTrace(new PrintWriter(str));
+            this.message = str.toString();
+        }
+
+        if ( KeeperException.class.isAssignableFrom(e.getClass()) )
+        {
+            KeeperException keeperException = (KeeperException)e;
+            switch ( keeperException.code() )
+            {
+                default:
+                {
+                    type = ExceptionType.ZOOKEEPER;
+                    zooKeeperException = ZooKeeperExceptionType.valueOf(keeperException.code().name());
+                    nodeException = null;
+                    break;
+                }
+
+                case NONODE:
+                case NODEEXISTS:
+                case NOTEMPTY:
+                case BADVERSION:
+                {
+                    type = ExceptionType.NODE;
+                    zooKeeperException = null;
+                    nodeException = NodeExceptionType.valueOf(keeperException.code().name());
+                    break;
+                }
+            }
+        }
+        else
+        {
+            type = ExceptionType.GENERAL;
+        }
+    }
+
+    public RpcException(ExceptionType type, ZooKeeperExceptionType zooKeeperException, NodeExceptionType nodeException, String message)
+    {
+        this.type = type;
+        this.zooKeeperException = zooKeeperException;
+        this.nodeException = nodeException;
+        this.message = message;
+    }
+
+
+}

http://git-wip-us.apache.org/repos/asf/curator/blob/c6229cf2/curator-x-rpc/src/main/java/org/apache/curator/x/rpc/idl/exceptions/ZooKeeperExceptionType.java
----------------------------------------------------------------------
diff --git a/curator-x-rpc/src/main/java/org/apache/curator/x/rpc/idl/exceptions/ZooKeeperExceptionType.java b/curator-x-rpc/src/main/java/org/apache/curator/x/rpc/idl/exceptions/ZooKeeperExceptionType.java
new file mode 100644
index 0000000..ca5049b
--- /dev/null
+++ b/curator-x-rpc/src/main/java/org/apache/curator/x/rpc/idl/exceptions/ZooKeeperExceptionType.java
@@ -0,0 +1,22 @@
+package org.apache.curator.x.rpc.idl.exceptions;
+
+public enum ZooKeeperExceptionType
+{
+    SYSTEMERROR,
+    RUNTIMEINCONSISTENCY,
+    DATAINCONSISTENCY,
+    CONNECTIONLOSS,
+    MARSHALLINGERROR,
+    UNIMPLEMENTED,
+    OPERATIONTIMEOUT,
+    BADARGUMENTS,
+    APIERROR,
+    NOAUTH,
+    NOCHILDRENFOREPHEMERALS,
+    INVALIDACL,
+    AUTHFAILED,
+    SESSIONEXPIRED,
+    INVALIDCALLBACK,
+    SESSIONMOVED,
+    NOTREADONLY
+}

http://git-wip-us.apache.org/repos/asf/curator/blob/c6229cf2/curator-x-rpc/src/main/java/org/apache/curator/x/rpc/idl/services/CuratorProjectionService.java
----------------------------------------------------------------------
diff --git a/curator-x-rpc/src/main/java/org/apache/curator/x/rpc/idl/services/CuratorProjectionService.java b/curator-x-rpc/src/main/java/org/apache/curator/x/rpc/idl/services/CuratorProjectionService.java
index 7e9e9c1..07397ea 100644
--- a/curator-x-rpc/src/main/java/org/apache/curator/x/rpc/idl/services/CuratorProjectionService.java
+++ b/curator-x-rpc/src/main/java/org/apache/curator/x/rpc/idl/services/CuratorProjectionService.java
@@ -47,6 +47,8 @@ import org.apache.curator.x.rpc.connections.ConnectionManager;
 import org.apache.curator.x.rpc.connections.CuratorEntry;
 import org.apache.curator.x.rpc.details.RpcBackgroundCallback;
 import org.apache.curator.x.rpc.details.RpcWatcher;
+import org.apache.curator.x.rpc.idl.exceptions.ExceptionType;
+import org.apache.curator.x.rpc.idl.exceptions.RpcException;
 import org.apache.curator.x.rpc.idl.structs.*;
 import org.apache.zookeeper.CreateMode;
 import org.apache.zookeeper.data.Stat;
@@ -69,9 +71,13 @@ public class CuratorProjectionService
     }
 
     @ThriftMethod
-    public CuratorProjection newCuratorProjection(String connectionName)
+    public CuratorProjection newCuratorProjection(String connectionName) throws RpcException
     {
         CuratorFramework client = connectionManager.newConnection(connectionName);
+        if ( client == null )
+        {
+            throw new RpcException(ExceptionType.GENERAL, null, null, "No connection configuration was found with the name: " + connectionName);
+        }
 
         String id = CuratorEntry.newId();
         client.start();
@@ -108,433 +114,513 @@ public class CuratorProjectionService
     }
 
     @ThriftMethod
-    public OptionalPath createNode(CuratorProjection projection, CreateSpec spec) throws Exception
+    public OptionalPath createNode(CuratorProjection projection, CreateSpec spec) throws RpcException
     {
-        CuratorFramework client = getEntry(projection).getClient();
-
-        Object builder = client.create();
-        if ( spec.creatingParentsIfNeeded )
-        {
-            builder = castBuilder(builder, CreateBuilder.class).creatingParentsIfNeeded();
-        }
-        if ( spec.compressed )
-        {
-            builder = castBuilder(builder, Compressible.class).compressed();
-        }
-        if ( spec.withProtection )
-        {
-            builder = castBuilder(builder, CreateBuilder.class).withProtection();
-        }
-        if ( spec.mode != null )
+        try
         {
-            builder = castBuilder(builder, CreateModable.class).withMode(CreateMode.valueOf(spec.mode.name()));
-        }
+            CuratorFramework client = CuratorEntry.mustGetEntry(connectionManager, projection).getClient();
 
-        if ( spec.asyncContext != null )
+            Object builder = client.create();
+            if ( spec.creatingParentsIfNeeded )
+            {
+                builder = castBuilder(builder, CreateBuilder.class).creatingParentsIfNeeded();
+            }
+            if ( spec.compressed )
+            {
+                builder = castBuilder(builder, Compressible.class).compressed();
+            }
+            if ( spec.withProtection )
+            {
+                builder = castBuilder(builder, CreateBuilder.class).withProtection();
+            }
+            if ( spec.mode != null )
+            {
+                builder = castBuilder(builder, CreateModable.class).withMode(CreateMode.valueOf(spec.mode.name()));
+            }
+
+            if ( spec.asyncContext != null )
+            {
+                BackgroundCallback backgroundCallback = new RpcBackgroundCallback(this, projection);
+                builder = castBuilder(builder, Backgroundable.class).inBackground(backgroundCallback, spec.asyncContext);
+            }
+
+            Object path = castBuilder(builder, PathAndBytesable.class).forPath(spec.path, spec.data);
+            return new OptionalPath((path != null) ? String.valueOf(path) : null);
+        }
+        catch ( Exception e )
         {
-            BackgroundCallback backgroundCallback = new RpcBackgroundCallback(this, projection);
-            builder = castBuilder(builder, Backgroundable.class).inBackground(backgroundCallback, spec.asyncContext);
+            throw new RpcException(e);
         }
-
-        Object path = castBuilder(builder, PathAndBytesable.class).forPath(spec.path, spec.data);
-        return new OptionalPath((path != null) ? String.valueOf(path) : null);
     }
 
     @ThriftMethod
-    public void deleteNode(CuratorProjection projection, DeleteSpec spec) throws Exception
+    public void deleteNode(CuratorProjection projection, DeleteSpec spec) throws RpcException
     {
-        CuratorFramework client = getEntry(projection).getClient();
-
-        Object builder = client.delete();
-        if ( spec.guaranteed )
+        try
         {
-            builder = castBuilder(builder, DeleteBuilder.class).guaranteed();
-        }
-        if ( spec.version != null )
-        {
-            builder = castBuilder(builder, Versionable.class).withVersion(spec.version.version);
-        }
+            CuratorFramework client = CuratorEntry.mustGetEntry(connectionManager, projection).getClient();
+
+            Object builder = client.delete();
+            if ( spec.guaranteed )
+            {
+                builder = castBuilder(builder, DeleteBuilder.class).guaranteed();
+            }
+            if ( spec.version != null )
+            {
+                builder = castBuilder(builder, Versionable.class).withVersion(spec.version.version);
+            }
 
-        if ( spec.asyncContext != null )
+            if ( spec.asyncContext != null )
+            {
+                BackgroundCallback backgroundCallback = new RpcBackgroundCallback(this, projection);
+                builder = castBuilder(builder, Backgroundable.class).inBackground(backgroundCallback, spec.asyncContext);
+            }
+
+            castBuilder(builder, Pathable.class).forPath(spec.path);
+        }
+        catch ( Exception e )
         {
-            BackgroundCallback backgroundCallback = new RpcBackgroundCallback(this, projection);
-            builder = castBuilder(builder, Backgroundable.class).inBackground(backgroundCallback, spec.asyncContext);
+            throw new RpcException(e);
         }
-
-        castBuilder(builder, Pathable.class).forPath(spec.path);
     }
 
     @ThriftMethod
-    public byte[] getData(CuratorProjection projection, GetDataSpec spec) throws Exception
+    public byte[] getData(CuratorProjection projection, GetDataSpec spec) throws RpcException
     {
-        CuratorFramework client = getEntry(projection).getClient();
-
-        Object builder = client.getData();
-        if ( spec.watched )
+        try
         {
-            builder = castBuilder(builder, Watchable.class).usingWatcher(new RpcWatcher(this, projection));
-        }
+            CuratorFramework client = CuratorEntry.mustGetEntry(connectionManager, projection).getClient();
 
-        if ( spec.decompressed )
-        {
-            builder = castBuilder(builder, Decompressible.class).decompressed();
-        }
+            Object builder = client.getData();
+            if ( spec.watched )
+            {
+                builder = castBuilder(builder, Watchable.class).usingWatcher(new RpcWatcher(this, projection));
+            }
 
-        if ( spec.asyncContext != null )
-        {
-            BackgroundCallback backgroundCallback = new RpcBackgroundCallback(this, projection);
-            builder = castBuilder(builder, Backgroundable.class).inBackground(backgroundCallback);
-        }
+            if ( spec.decompressed )
+            {
+                builder = castBuilder(builder, Decompressible.class).decompressed();
+            }
+
+            if ( spec.asyncContext != null )
+            {
+                BackgroundCallback backgroundCallback = new RpcBackgroundCallback(this, projection);
+                builder = castBuilder(builder, Backgroundable.class).inBackground(backgroundCallback);
+            }
 
-        Stat stat = new Stat();
-        builder = castBuilder(builder, Statable.class).storingStatIn(stat);
+            Stat stat = new Stat();
+            builder = castBuilder(builder, Statable.class).storingStatIn(stat);
 
-        return (byte[])castBuilder(builder, Pathable.class).forPath(spec.path);
+            return (byte[])castBuilder(builder, Pathable.class).forPath(spec.path);
+        }
+        catch ( Exception e )
+        {
+            throw new RpcException(e);
+        }
     }
 
     @ThriftMethod
-    public RpcStat setData(CuratorProjection projection, SetDataSpec spec) throws Exception
+    public RpcStat setData(CuratorProjection projection, SetDataSpec spec) throws RpcException
     {
-        CuratorFramework client = getEntry(projection).getClient();
-
-        Object builder = client.setData();
-        if ( spec.watched )
+        try
         {
-            builder = castBuilder(builder, Watchable.class).usingWatcher(new RpcWatcher(this, projection));
+            CuratorFramework client = CuratorEntry.mustGetEntry(connectionManager, projection).getClient();
+
+            Object builder = client.setData();
+            if ( spec.watched )
+            {
+                builder = castBuilder(builder, Watchable.class).usingWatcher(new RpcWatcher(this, projection));
+            }
+            if ( spec.version != null )
+            {
+                builder = castBuilder(builder, Versionable.class).withVersion(spec.version.version);
+            }
+
+            if ( spec.compressed )
+            {
+                builder = castBuilder(builder, Compressible.class).compressed();
+            }
+
+            if ( spec.asyncContext != null )
+            {
+                BackgroundCallback backgroundCallback = new RpcBackgroundCallback(this, projection);
+                builder = castBuilder(builder, Backgroundable.class).inBackground(backgroundCallback);
+            }
+
+            Stat stat = (Stat)castBuilder(builder, PathAndBytesable.class).forPath(spec.path, spec.data);
+            return RpcCuratorEvent.toRpcStat(stat);
         }
-        if ( spec.version != null )
+        catch ( Exception e )
         {
-            builder = castBuilder(builder, Versionable.class).withVersion(spec.version.version);
+            throw new RpcException(e);
         }
+    }
 
-        if ( spec.compressed )
+    @ThriftMethod
+    public OptionalRpcStat exists(CuratorProjection projection, ExistsSpec spec) throws RpcException
+    {
+        try
         {
-            builder = castBuilder(builder, Compressible.class).compressed();
-        }
+            CuratorFramework client = CuratorEntry.mustGetEntry(connectionManager, projection).getClient();
+
+            Object builder = client.checkExists();
+            if ( spec.watched )
+            {
+                builder = castBuilder(builder, Watchable.class).usingWatcher(new RpcWatcher(this, projection));
+            }
 
-        if ( spec.asyncContext != null )
+            if ( spec.asyncContext != null )
+            {
+                BackgroundCallback backgroundCallback = new RpcBackgroundCallback(this, projection);
+                castBuilder(builder, Backgroundable.class).inBackground(backgroundCallback);
+            }
+
+            Stat stat = (Stat)castBuilder(builder, Pathable.class).forPath(spec.path);
+            return new OptionalRpcStat((stat != null) ? RpcCuratorEvent.toRpcStat(stat) : null);
+        }
+        catch ( Exception e )
         {
-            BackgroundCallback backgroundCallback = new RpcBackgroundCallback(this, projection);
-            builder = castBuilder(builder, Backgroundable.class).inBackground(backgroundCallback);
+            throw new RpcException(e);
         }
-
-        Stat stat = (Stat)castBuilder(builder, PathAndBytesable.class).forPath(spec.path, spec.data);
-        return RpcCuratorEvent.toRpcStat(stat);
     }
 
     @ThriftMethod
-    public OptionalRpcStat exists(CuratorProjection projection, ExistsSpec spec) throws Exception
+    public OptionalChildrenList getChildren(CuratorProjection projection, GetChildrenSpec spec) throws RpcException
     {
-        CuratorFramework client = getEntry(projection).getClient();
-
-        Object builder = client.checkExists();
-        if ( spec.watched )
+        try
         {
-            builder = castBuilder(builder, Watchable.class).usingWatcher(new RpcWatcher(this, projection));
-        }
+            CuratorFramework client = CuratorEntry.mustGetEntry(connectionManager, projection).getClient();
 
-        if ( spec.asyncContext != null )
+            Object builder = client.getChildren();
+            if ( spec.watched )
+            {
+                builder = castBuilder(builder, Watchable.class).usingWatcher(new RpcWatcher(this, projection));
+            }
+
+            if ( spec.asyncContext != null )
+            {
+                BackgroundCallback backgroundCallback = new RpcBackgroundCallback(this, projection);
+                builder = castBuilder(builder, Backgroundable.class).inBackground(backgroundCallback);
+            }
+
+            @SuppressWarnings("unchecked")
+            List<String> children = (List<String>)castBuilder(builder, Pathable.class).forPath(spec.path);
+            return new OptionalChildrenList(children);
+        }
+        catch ( Exception e )
         {
-            BackgroundCallback backgroundCallback = new RpcBackgroundCallback(this, projection);
-            castBuilder(builder, Backgroundable.class).inBackground(backgroundCallback);
+            throw new RpcException(e);
         }
-
-        Stat stat = (Stat)castBuilder(builder, Pathable.class).forPath(spec.path);
-        return new OptionalRpcStat((stat != null) ? RpcCuratorEvent.toRpcStat(stat) : null);
     }
 
     @ThriftMethod
-    public OptionalChildrenList getChildren(CuratorProjection projection, GetChildrenSpec spec) throws Exception
+    public boolean closeGenericProjection(CuratorProjection projection, String id) throws RpcException
     {
-        CuratorFramework client = getEntry(projection).getClient();
-
-        Object builder = client.getChildren();
-        if ( spec.watched )
+        try
         {
-            builder = castBuilder(builder, Watchable.class).usingWatcher(new RpcWatcher(this, projection));
+            CuratorEntry entry = CuratorEntry.mustGetEntry(connectionManager, projection);
+            return entry.closeThing(id);
         }
-
-        if ( spec.asyncContext != null )
+        catch ( Exception e )
         {
-            BackgroundCallback backgroundCallback = new RpcBackgroundCallback(this, projection);
-            builder = castBuilder(builder, Backgroundable.class).inBackground(backgroundCallback);
+            throw new RpcException(e);
         }
-
-        @SuppressWarnings("unchecked")
-        List<String> children = (List<String>)castBuilder(builder, Pathable.class).forPath(spec.path);
-        return new OptionalChildrenList(children);
     }
 
     @ThriftMethod
-    public boolean closeGenericProjection(CuratorProjection curatorProjection, String id) throws Exception
+    public LockProjection acquireLock(CuratorProjection projection, final String path, int maxWaitMs) throws RpcException
     {
-        CuratorEntry entry = getEntry(curatorProjection);
-        return entry.closeThing(id);
+        try
+        {
+            CuratorEntry entry = CuratorEntry.mustGetEntry(connectionManager, projection);
+            final InterProcessSemaphoreMutex lock = new InterProcessSemaphoreMutex(entry.getClient(), path);
+            if ( !lock.acquire(maxWaitMs, TimeUnit.MILLISECONDS) )
+            {
+                return new LockProjection();
+            }
+
+            Closer closer = new Closer()
+            {
+                @Override
+                public void close()
+                {
+                    if ( lock.isAcquiredInThisProcess() )
+                    {
+                        try
+                        {
+                            lock.release();
+                        }
+                        catch ( Exception e )
+                        {
+                            log.error("Could not release left-over lock for path: " + path, e);
+                        }
+                    }
+                }
+            };
+            String id = entry.addThing(lock, closer);
+            return new LockProjection(id);
+        }
+        catch ( Exception e )
+        {
+            throw new RpcException(e);
+        }
     }
 
     @ThriftMethod
-    public LockProjection acquireLock(CuratorProjection projection, final String path, int maxWaitMs) throws Exception
+    public LeaderResult startLeaderSelector(final CuratorProjection projection, final String path, final String participantId, int waitForLeadershipMs) throws RpcException
     {
-        CuratorEntry entry = getEntry(projection);
-        final InterProcessSemaphoreMutex lock = new InterProcessSemaphoreMutex(entry.getClient(), path);
-        if ( !lock.acquire(maxWaitMs, TimeUnit.MILLISECONDS) )
+        try
         {
-            return new LockProjection();
-        }
+            CuratorEntry entry = CuratorEntry.mustGetEntry(connectionManager, projection);
 
-        Closer closer = new Closer()
-        {
-            @Override
-            public void close()
+            final LeaderLatch leaderLatch = new LeaderLatch(entry.getClient(), path, participantId);
+            leaderLatch.start();
+
+            Closer closer = new Closer()
             {
-                if ( lock.isAcquiredInThisProcess() )
+                @Override
+                public void close()
                 {
                     try
                     {
-                        lock.release();
+                        leaderLatch.close();
                     }
-                    catch ( Exception e )
+                    catch ( IOException e )
                     {
-                        log.error("Could not release left-over lock for path: " + path, e);
+                        log.error("Could not close left-over leader latch for path: " + path, e);
                     }
                 }
-            }
-        };
-        String id = entry.addThing(lock, closer);
-        return new LockProjection(id);
-    }
-
-    @ThriftMethod
-    public LeaderResult startLeaderSelector(final CuratorProjection projection, final String path, final String participantId, int waitForLeadershipMs) throws Exception
-    {
-        CuratorEntry entry = getEntry(projection);
-
-        final LeaderLatch leaderLatch = new LeaderLatch(entry.getClient(), path, participantId);
-        leaderLatch.start();
+            };
+            String id = entry.addThing(leaderLatch, closer);
 
-        Closer closer = new Closer()
-        {
-            @Override
-            public void close()
+            LeaderLatchListener listener = new LeaderLatchListener()
             {
-                try
+                @Override
+                public void isLeader()
                 {
-                    leaderLatch.close();
+                    addEvent(projection, new RpcCuratorEvent(new LeaderEvent(path, participantId, true)));
                 }
-                catch ( IOException e )
+
+                @Override
+                public void notLeader()
                 {
-                    log.error("Could not close left-over leader latch for path: " + path, e);
+                    addEvent(projection, new RpcCuratorEvent(new LeaderEvent(path, participantId, false)));
                 }
-            }
-        };
-        String id = entry.addThing(leaderLatch, closer);
-
-        LeaderLatchListener listener = new LeaderLatchListener()
-        {
-            @Override
-            public void isLeader()
-            {
-                addEvent(projection, new RpcCuratorEvent(new LeaderEvent(path, participantId, true)));
-            }
+            };
+            leaderLatch.addListener(listener);
 
-            @Override
-            public void notLeader()
+            if ( waitForLeadershipMs > 0 )
             {
-                addEvent(projection, new RpcCuratorEvent(new LeaderEvent(path, participantId, false)));
+                leaderLatch.await(waitForLeadershipMs, TimeUnit.MILLISECONDS);
             }
-        };
-        leaderLatch.addListener(listener);
 
-        if ( waitForLeadershipMs > 0 )
+            return new LeaderResult(new LeaderProjection(id), leaderLatch.hasLeadership());
+        }
+        catch ( Exception e )
         {
-            leaderLatch.await(waitForLeadershipMs, TimeUnit.MILLISECONDS);
+            throw new RpcException(e);
         }
-
-        return new LeaderResult(new LeaderProjection(id), leaderLatch.hasLeadership());
     }
 
     @ThriftMethod
-    public List<RpcParticipant> getLeaderParticipants(CuratorProjection projection, LeaderProjection leaderProjection) throws Exception
+    public List<RpcParticipant> getLeaderParticipants(CuratorProjection projection, LeaderProjection leaderProjection) throws RpcException
     {
-        CuratorEntry entry = getEntry(projection);
+        try
+        {
+            CuratorEntry entry = CuratorEntry.mustGetEntry(connectionManager, projection);
 
-        LeaderLatch leaderLatch = getThing(entry, leaderProjection.id, LeaderLatch.class);
-        Collection<Participant> participants = leaderLatch.getParticipants();
-        return Lists.transform(Lists.newArrayList(participants), new Function<Participant, RpcParticipant>()
-            {
-                @Override
-                public RpcParticipant apply(Participant participant)
+            LeaderLatch leaderLatch = getThing(entry, leaderProjection.id, LeaderLatch.class);
+            Collection<Participant> participants = leaderLatch.getParticipants();
+            return Lists.transform(Lists.newArrayList(participants), new Function<Participant, RpcParticipant>()
                 {
-                    return new RpcParticipant(participant.getId(), participant.isLeader());
-                }
-            });
+                    @Override
+                    public RpcParticipant apply(Participant participant)
+                    {
+                        return new RpcParticipant(participant.getId(), participant.isLeader());
+                    }
+                });
+        }
+        catch ( Exception e )
+        {
+            throw new RpcException(e);
+        }
     }
 
     @ThriftMethod
-    public boolean isLeader(CuratorProjection projection, LeaderProjection leaderProjection) throws Exception
+    public boolean isLeader(CuratorProjection projection, LeaderProjection leaderProjection) throws RpcException
     {
-        CuratorEntry entry = getEntry(projection);
+        try
+        {
+            CuratorEntry entry = CuratorEntry.mustGetEntry(connectionManager, projection);
 
-        LeaderLatch leaderLatch = getThing(entry, leaderProjection.id, LeaderLatch.class);
-        return leaderLatch.hasLeadership();
+            LeaderLatch leaderLatch = getThing(entry, leaderProjection.id, LeaderLatch.class);
+            return leaderLatch.hasLeadership();
+        }
+        catch ( Exception e )
+        {
+            throw new RpcException(e);
+        }
     }
 
     @ThriftMethod
-    public PathChildrenCacheProjection startPathChildrenCache(final CuratorProjection projection, final String path, boolean cacheData, boolean dataIsCompressed, PathChildrenCacheStartMode startMode) throws Exception
+    public PathChildrenCacheProjection startPathChildrenCache(final CuratorProjection projection, final String path, boolean cacheData, boolean dataIsCompressed, PathChildrenCacheStartMode startMode) throws RpcException
     {
-        final CuratorEntry entry = getEntry(projection);
+        try
+        {
+            final CuratorEntry entry = CuratorEntry.mustGetEntry(connectionManager, projection);
 
-        final PathChildrenCache cache = new PathChildrenCache(entry.getClient(), path, cacheData, dataIsCompressed, ThreadUtils.newThreadFactory("PathChildrenCacheResource"));
-        cache.start(PathChildrenCache.StartMode.valueOf(startMode.name()));
+            final PathChildrenCache cache = new PathChildrenCache(entry.getClient(), path, cacheData, dataIsCompressed, ThreadUtils.newThreadFactory("PathChildrenCacheResource"));
+            cache.start(PathChildrenCache.StartMode.valueOf(startMode.name()));
 
-        Closer closer = new Closer()
-        {
-            @Override
-            public void close()
+            Closer closer = new Closer()
             {
-                try
+                @Override
+                public void close()
                 {
-                    cache.close();
+                    try
+                    {
+                        cache.close();
+                    }
+                    catch ( IOException e )
+                    {
+                        log.error("Could not close left-over PathChildrenCache for path: " + path, e);
+                    }
                 }
-                catch ( IOException e )
+            };
+            String id = entry.addThing(cache, closer);
+
+            PathChildrenCacheListener listener = new PathChildrenCacheListener()
+            {
+                @Override
+                public void childEvent(CuratorFramework client, PathChildrenCacheEvent event) throws RpcException
                 {
-                    log.error("Could not close left-over PathChildrenCache for path: " + path, e);
+                    entry.addEvent(new RpcCuratorEvent(new RpcPathChildrenCacheEvent(path, event)));
                 }
-            }
-        };
-        String id = entry.addThing(cache, closer);
+            };
+            cache.getListenable().addListener(listener);
 
-        PathChildrenCacheListener listener = new PathChildrenCacheListener()
+            return new PathChildrenCacheProjection(id);
+        }
+        catch ( Exception e )
         {
-            @Override
-            public void childEvent(CuratorFramework client, PathChildrenCacheEvent event) throws Exception
-            {
-                entry.addEvent(new RpcCuratorEvent(new RpcPathChildrenCacheEvent(path, event)));
-            }
-        };
-        cache.getListenable().addListener(listener);
-
-        return new PathChildrenCacheProjection(id);
+            throw new RpcException(e);
+        }
     }
 
     @ThriftMethod
-    public List<RpcChildData> getPathChildrenCacheData(CuratorProjection projection, PathChildrenCacheProjection cacheProjection) throws Exception
+    public List<RpcChildData> getPathChildrenCacheData(CuratorProjection projection, PathChildrenCacheProjection cacheProjection) throws RpcException
     {
-        CuratorEntry entry = getEntry(projection);
+        try
+        {
+            CuratorEntry entry = CuratorEntry.mustGetEntry(connectionManager, projection);
 
-        PathChildrenCache pathChildrenCache = getThing(entry, cacheProjection.id, PathChildrenCache.class);
-        return Lists.transform
-        (
-            pathChildrenCache.getCurrentData(),
-            new Function<ChildData, RpcChildData>()
-            {
-                @Override
-                public RpcChildData apply(ChildData childData)
+            PathChildrenCache pathChildrenCache = getThing(entry, cacheProjection.id, PathChildrenCache.class);
+            return Lists.transform
+            (
+                pathChildrenCache.getCurrentData(),
+                new Function<ChildData, RpcChildData>()
                 {
-                    return new RpcChildData(childData);
+                    @Override
+                    public RpcChildData apply(ChildData childData)
+                    {
+                        return new RpcChildData(childData);
+                    }
                 }
-            }
-        );
+            );
+        }
+        catch ( Exception e )
+        {
+            throw new RpcException(e);
+        }
     }
 
     @ThriftMethod
-    public RpcChildData getPathChildrenCacheDataForPath(CuratorProjection projection, PathChildrenCacheProjection cacheProjection, String path) throws Exception
+    public RpcChildData getPathChildrenCacheDataForPath(CuratorProjection projection, PathChildrenCacheProjection cacheProjection, String path) throws RpcException
     {
-        CuratorEntry entry = getEntry(projection);
+        try
+        {
+            CuratorEntry entry = CuratorEntry.mustGetEntry(connectionManager, projection);
 
-        PathChildrenCache pathChildrenCache = getThing(entry, cacheProjection.id, PathChildrenCache.class);
-        return new RpcChildData(pathChildrenCache.getCurrentData(path));
+            PathChildrenCache pathChildrenCache = getThing(entry, cacheProjection.id, PathChildrenCache.class);
+            return new RpcChildData(pathChildrenCache.getCurrentData(path));
+        }
+        catch ( Exception e )
+        {
+            throw new RpcException(e);
+        }
     }
 
     @ThriftMethod
-    public NodeCacheProjection startNodeCache(CuratorProjection projection, final String path, boolean dataIsCompressed, boolean buildInitial) throws Exception
+    public NodeCacheProjection startNodeCache(CuratorProjection projection, final String path, boolean dataIsCompressed, boolean buildInitial) throws RpcException
     {
-        final CuratorEntry entry = getEntry(projection);
+        try
+        {
+            final CuratorEntry entry = CuratorEntry.mustGetEntry(connectionManager, projection);
 
-        final NodeCache cache = new NodeCache(entry.getClient(), path, dataIsCompressed);
-        cache.start(buildInitial);
+            final NodeCache cache = new NodeCache(entry.getClient(), path, dataIsCompressed);
+            cache.start(buildInitial);
 
-        Closer closer = new Closer()
-        {
-            @Override
-            public void close()
+            Closer closer = new Closer()
             {
-                try
+                @Override
+                public void close()
                 {
-                    cache.close();
+                    try
+                    {
+                        cache.close();
+                    }
+                    catch ( IOException e )
+                    {
+                        log.error("Could not close left-over NodeCache for path: " + path, e);
+                    }
                 }
-                catch ( IOException e )
+            };
+            String id = entry.addThing(cache, closer);
+
+            NodeCacheListener listener = new NodeCacheListener()
+            {
+                @Override
+                public void nodeChanged()
                 {
-                    log.error("Could not close left-over NodeCache for path: " + path, e);
+                    entry.addEvent(new RpcCuratorEvent(RpcCuratorEventType.NODE_CACHE, path));
                 }
-            }
-        };
-        String id = entry.addThing(cache, closer);
+            };
+            cache.getListenable().addListener(listener);
 
-        NodeCacheListener listener = new NodeCacheListener()
+            return new NodeCacheProjection(id);
+        }
+        catch ( Exception e )
         {
-            @Override
-            public void nodeChanged() throws Exception
-            {
-                entry.addEvent(new RpcCuratorEvent(RpcCuratorEventType.NODE_CACHE, path));
-            }
-        };
-        cache.getListenable().addListener(listener);
-
-        return new NodeCacheProjection(id);
-    }
-
-    @ThriftMethod
-    public RpcChildData getNodeCacheData(CuratorProjection projection, NodeCacheProjection cacheProjection) throws Exception
-    {
-        CuratorEntry entry = getEntry(projection);
-
-        NodeCache nodeCache = getThing(entry, cacheProjection.id, NodeCache.class);
-        return new RpcChildData(nodeCache.getCurrentData());
+            throw new RpcException(e);
+        }
     }
 
     @ThriftMethod
-    public PersistentEphemeralNodeProjection startPersistentEphemeralNode(CuratorProjection projection, final String path, byte[] data, RpcPersistentEphemeralNodeMode mode) throws Exception
+    public RpcChildData getNodeCacheData(CuratorProjection projection, NodeCacheProjection cacheProjection) throws RpcException
     {
-        CuratorEntry entry = getEntry(projection);
-
-        final PersistentEphemeralNode node = new PersistentEphemeralNode(entry.getClient(), PersistentEphemeralNode.Mode.valueOf(mode.name()), path, data);
-        node.start();
+        try
+        {
+            CuratorEntry entry = CuratorEntry.mustGetEntry(connectionManager, projection);
 
-        Closer closer = new Closer()
+            NodeCache nodeCache = getThing(entry, cacheProjection.id, NodeCache.class);
+            return new RpcChildData(nodeCache.getCurrentData());
+        }
+        catch ( Exception e )
         {
-            @Override
-            public void close()
-            {
-                try
-                {
-                    node.close();
-                }
-                catch ( Exception e )
-                {
-                    log.error("Could not release left-over persistent ephemeral node for path: " + path, e);
-                }
-            }
-        };
-        String id = entry.addThing(node, closer);
-        return new PersistentEphemeralNodeProjection(id);
+            throw new RpcException(e);
+        }
     }
 
     @ThriftMethod
-    public List<LeaseProjection> startSemaphore(CuratorProjection projection, final String path, int acquireQty, int maxWaitMs, int maxLeases) throws Exception
+    public PersistentEphemeralNodeProjection startPersistentEphemeralNode(CuratorProjection projection, final String path, byte[] data, RpcPersistentEphemeralNodeMode mode) throws RpcException
     {
-        CuratorEntry entry = getEntry(projection);
-
-        final InterProcessSemaphoreV2 semaphore = new InterProcessSemaphoreV2(entry.getClient(), path, maxLeases);
-        final Collection<Lease> leases = semaphore.acquire(acquireQty, maxWaitMs, TimeUnit.MILLISECONDS);
-        if ( leases == null )
+        try
         {
-            return Lists.newArrayList();
-        }
+            CuratorEntry entry = CuratorEntry.mustGetEntry(connectionManager, projection);
+
+            final PersistentEphemeralNode node = new PersistentEphemeralNode(entry.getClient(), PersistentEphemeralNode.Mode.valueOf(mode.name()), path, data);
+            node.start();
 
-        List<LeaseProjection> leaseProjections = Lists.newArrayList();
-        for ( final Lease lease : leases )
-        {
             Closer closer = new Closer()
             {
                 @Override
@@ -542,36 +628,72 @@ public class CuratorProjectionService
                 {
                     try
                     {
-                        semaphore.returnLease(lease);
+                        node.close();
                     }
                     catch ( Exception e )
                     {
-                        log.error("Could not release semaphore leases for path: " + path, e);
+                        log.error("Could not release left-over persistent ephemeral node for path: " + path, e);
                     }
                 }
             };
-            leaseProjections.add(new LeaseProjection(entry.addThing(lease, closer)));
+            String id = entry.addThing(node, closer);
+            return new PersistentEphemeralNodeProjection(id);
+        }
+        catch ( Exception e )
+        {
+            throw new RpcException(e);
         }
-        return leaseProjections;
     }
 
-    public void addEvent(CuratorProjection projection, RpcCuratorEvent event)
+    @ThriftMethod
+    public List<LeaseProjection> startSemaphore(CuratorProjection projection, final String path, int acquireQty, int maxWaitMs, int maxLeases) throws RpcException
     {
-        CuratorEntry entry = connectionManager.get(projection.id);
-        if ( entry != null )
+        try
         {
-            entry.addEvent(event);
+            CuratorEntry entry = CuratorEntry.mustGetEntry(connectionManager, projection);
+
+            final InterProcessSemaphoreV2 semaphore = new InterProcessSemaphoreV2(entry.getClient(), path, maxLeases);
+            final Collection<Lease> leases = semaphore.acquire(acquireQty, maxWaitMs, TimeUnit.MILLISECONDS);
+            if ( leases == null )
+            {
+                return Lists.newArrayList();
+            }
+
+            List<LeaseProjection> leaseProjections = Lists.newArrayList();
+            for ( final Lease lease : leases )
+            {
+                Closer closer = new Closer()
+                {
+                    @Override
+                    public void close()
+                    {
+                        try
+                        {
+                            semaphore.returnLease(lease);
+                        }
+                        catch ( Exception e )
+                        {
+                            log.error("Could not release semaphore leases for path: " + path, e);
+                        }
+                    }
+                };
+                leaseProjections.add(new LeaseProjection(entry.addThing(lease, closer)));
+            }
+            return leaseProjections;
+        }
+        catch ( Exception e )
+        {
+            throw new RpcException(e);
         }
     }
 
-    private CuratorEntry getEntry(CuratorProjection projection) throws Exception
+    public void addEvent(CuratorProjection projection, RpcCuratorEvent event)
     {
         CuratorEntry entry = connectionManager.get(projection.id);
-        if ( entry == null )
+        if ( entry != null )
         {
-            throw new Exception("No client found with id: " + projection.id);
+            entry.addEvent(event);
         }
-        return entry;
     }
 
     private static <T> T castBuilder(Object createBuilder, Class<T> clazz) throws Exception

http://git-wip-us.apache.org/repos/asf/curator/blob/c6229cf2/curator-x-rpc/src/main/java/org/apache/curator/x/rpc/idl/services/EventService.java
----------------------------------------------------------------------
diff --git a/curator-x-rpc/src/main/java/org/apache/curator/x/rpc/idl/services/EventService.java b/curator-x-rpc/src/main/java/org/apache/curator/x/rpc/idl/services/EventService.java
index c10c5df..7b2ef94 100644
--- a/curator-x-rpc/src/main/java/org/apache/curator/x/rpc/idl/services/EventService.java
+++ b/curator-x-rpc/src/main/java/org/apache/curator/x/rpc/idl/services/EventService.java
@@ -4,6 +4,7 @@ import com.facebook.swift.service.ThriftMethod;
 import com.facebook.swift.service.ThriftService;
 import org.apache.curator.x.rpc.connections.CuratorEntry;
 import org.apache.curator.x.rpc.connections.ConnectionManager;
+import org.apache.curator.x.rpc.idl.exceptions.RpcException;
 import org.apache.curator.x.rpc.idl.structs.CuratorProjection;
 import org.apache.curator.x.rpc.idl.structs.RpcCuratorEvent;
 
@@ -20,15 +21,17 @@ public class EventService
     }
 
     @ThriftMethod
-    public RpcCuratorEvent getNextEvent(CuratorProjection projection) throws InterruptedException
+    public RpcCuratorEvent getNextEvent(CuratorProjection projection) throws RpcException
     {
-        CuratorEntry entry = connectionManager.get(projection.id);
-        if ( entry == null )
+        try
         {
-            // TODO
-            return null;
+            CuratorEntry entry = CuratorEntry.mustGetEntry(connectionManager, projection);
+            RpcCuratorEvent event = entry.pollForEvent(pingTimeMs);
+            return (event != null) ? event : new RpcCuratorEvent();
+        }
+        catch ( InterruptedException e )
+        {
+            throw new RpcException(e);
         }
-        RpcCuratorEvent event = entry.pollForEvent(pingTimeMs);
-        return (event != null) ? event : new RpcCuratorEvent();
     }
 }

http://git-wip-us.apache.org/repos/asf/curator/blob/c6229cf2/curator-x-rpc/src/main/scripts/generate.sh
----------------------------------------------------------------------
diff --git a/curator-x-rpc/src/main/scripts/generate.sh b/curator-x-rpc/src/main/scripts/generate.sh
index de5e21c..684d8f5 100755
--- a/curator-x-rpc/src/main/scripts/generate.sh
+++ b/curator-x-rpc/src/main/scripts/generate.sh
@@ -31,7 +31,7 @@ RPC_PATH="$BASE_DIR/curator-x-rpc/target/classes"
 
 CLASSES=""
 
-for p in services structs; do
+for p in services structs exceptions; do
     for f in `ls -m1 $RPC_PATH/org/apache/curator/x/rpc/idl/$p/*.class | xargs -n 1 basename | sed s/\.[^\.]*$//`; do
         if [[ $f != *[\$]* ]]; then
             CLASSES="$CLASSES org.apache.curator.x.rpc.idl.$p.$f";

http://git-wip-us.apache.org/repos/asf/curator/blob/c6229cf2/curator-x-rpc/src/main/thrift/curator.thrift
----------------------------------------------------------------------
diff --git a/curator-x-rpc/src/main/thrift/curator.thrift b/curator-x-rpc/src/main/thrift/curator.thrift
index 7917a32..4de5cff 100644
--- a/curator-x-rpc/src/main/thrift/curator.thrift
+++ b/curator-x-rpc/src/main/thrift/curator.thrift
@@ -31,6 +31,18 @@ enum PersistentEphemeralNodeMode {
   EPHEMERAL, EPHEMERAL_SEQUENTIAL, PROTECTED_EPHEMERAL, PROTECTED_EPHEMERAL_SEQUENTIAL
 }
 
+enum ExceptionType {
+  GENERAL, ZOOKEEPER, NODE
+}
+
+enum NodeExceptionType {
+  NONODE, BADVERSION, NODEEXISTS, NOTEMPTY
+}
+
+enum ZooKeeperExceptionType {
+  SYSTEMERROR, RUNTIMEINCONSISTENCY, DATAINCONSISTENCY, CONNECTIONLOSS, MARSHALLINGERROR, UNIMPLEMENTED, OPERATIONTIMEOUT, BADARGUMENTS, APIERROR, NOAUTH, NOCHILDRENFOREPHEMERALS, INVALIDACL, AUTHFAILED, SESSIONEXPIRED, INVALIDCALLBACK, SESSIONMOVED, NOTREADONLY
+}
+
 struct CuratorProjection {
   1: string id;
 }
@@ -179,6 +191,13 @@ struct SetDataSpec {
   6: binary data;
 }
 
+exception CuratorException {
+  1: ExceptionType type;
+  2: ZooKeeperExceptionType zooKeeperException;
+  3: NodeExceptionType nodeException;
+  4: string message;
+}
+
 struct CuratorEvent {
   2: CuratorEventType type;
   3: i32 resultCode;
@@ -195,29 +214,29 @@ struct CuratorEvent {
 }
 
 service CuratorService {
-  LockProjection acquireLock(1: CuratorProjection projection, 2: string path, 3: i32 maxWaitMs);
+  LockProjection acquireLock(1: CuratorProjection projection, 2: string path, 3: i32 maxWaitMs) throws (1: CuratorException ex1);
   oneway void closeCuratorProjection(1: CuratorProjection projection);
-  bool closeGenericProjection(1: CuratorProjection curatorProjection, 2: string id);
-  OptionalPath createNode(1: CuratorProjection projection, 2: CreateSpec spec);
-  void deleteNode(1: CuratorProjection projection, 2: DeleteSpec spec);
-  OptionalStat exists(1: CuratorProjection projection, 2: ExistsSpec spec);
-  OptionalChildrenList getChildren(1: CuratorProjection projection, 2: GetChildrenSpec spec);
-  binary getData(1: CuratorProjection projection, 2: GetDataSpec spec);
-  list<Participant> getLeaderParticipants(1: CuratorProjection projection, 2: LeaderProjection leaderProjection);
-  ChildData getNodeCacheData(1: CuratorProjection projection, 2: NodeCacheProjection cacheProjection);
-  list<ChildData> getPathChildrenCacheData(1: CuratorProjection projection, 2: PathChildrenCacheProjection cacheProjection);
-  ChildData getPathChildrenCacheDataForPath(1: CuratorProjection projection, 2: PathChildrenCacheProjection cacheProjection, 3: string path);
-  bool isLeader(1: CuratorProjection projection, 2: LeaderProjection leaderProjection);
+  bool closeGenericProjection(1: CuratorProjection projection, 2: string id) throws (1: CuratorException ex1);
+  OptionalPath createNode(1: CuratorProjection projection, 2: CreateSpec spec) throws (1: CuratorException ex1);
+  void deleteNode(1: CuratorProjection projection, 2: DeleteSpec spec) throws (1: CuratorException ex1);
+  OptionalStat exists(1: CuratorProjection projection, 2: ExistsSpec spec) throws (1: CuratorException ex1);
+  OptionalChildrenList getChildren(1: CuratorProjection projection, 2: GetChildrenSpec spec) throws (1: CuratorException ex1);
+  binary getData(1: CuratorProjection projection, 2: GetDataSpec spec) throws (1: CuratorException ex1);
+  list<Participant> getLeaderParticipants(1: CuratorProjection projection, 2: LeaderProjection leaderProjection) throws (1: CuratorException ex1);
+  ChildData getNodeCacheData(1: CuratorProjection projection, 2: NodeCacheProjection cacheProjection) throws (1: CuratorException ex1);
+  list<ChildData> getPathChildrenCacheData(1: CuratorProjection projection, 2: PathChildrenCacheProjection cacheProjection) throws (1: CuratorException ex1);
+  ChildData getPathChildrenCacheDataForPath(1: CuratorProjection projection, 2: PathChildrenCacheProjection cacheProjection, 3: string path) throws (1: CuratorException ex1);
+  bool isLeader(1: CuratorProjection projection, 2: LeaderProjection leaderProjection) throws (1: CuratorException ex1);
   CuratorProjection newCuratorProjection(1: string connectionName);
   oneway void pingCuratorProjection(1: CuratorProjection projection);
-  Stat setData(1: CuratorProjection projection, 2: SetDataSpec spec);
-  LeaderResult startLeaderSelector(1: CuratorProjection projection, 2: string path, 3: string participantId, 4: i32 waitForLeadershipMs);
-  NodeCacheProjection startNodeCache(1: CuratorProjection projection, 2: string path, 3: bool dataIsCompressed, 4: bool buildInitial);
-  PathChildrenCacheProjection startPathChildrenCache(1: CuratorProjection projection, 2: string path, 3: bool cacheData, 4: bool dataIsCompressed, 5: PathChildrenCacheStartMode startMode);
-  PersistentEphemeralNodeProjection startPersistentEphemeralNode(1: CuratorProjection projection, 2: string path, 3: binary data, 4: PersistentEphemeralNodeMode mode);
-  list<LeaseProjection> startSemaphore(1: CuratorProjection projection, 2: string path, 3: i32 acquireQty, 4: i32 maxWaitMs, 5: i32 maxLeases);
+  Stat setData(1: CuratorProjection projection, 2: SetDataSpec spec) throws (1: CuratorException ex1);
+  LeaderResult startLeaderSelector(1: CuratorProjection projection, 2: string path, 3: string participantId, 4: i32 waitForLeadershipMs) throws (1: CuratorException ex1);
+  NodeCacheProjection startNodeCache(1: CuratorProjection projection, 2: string path, 3: bool dataIsCompressed, 4: bool buildInitial) throws (1: CuratorException ex1);
+  PathChildrenCacheProjection startPathChildrenCache(1: CuratorProjection projection, 2: string path, 3: bool cacheData, 4: bool dataIsCompressed, 5: PathChildrenCacheStartMode startMode) throws (1: CuratorException ex1);
+  PersistentEphemeralNodeProjection startPersistentEphemeralNode(1: CuratorProjection projection, 2: string path, 3: binary data, 4: PersistentEphemeralNodeMode mode) throws (1: CuratorException ex1);
+  list<LeaseProjection> startSemaphore(1: CuratorProjection projection, 2: string path, 3: i32 acquireQty, 4: i32 maxWaitMs, 5: i32 maxLeases) throws (1: CuratorException ex1);
 }
 
 service EventService {
-  CuratorEvent getNextEvent(1: CuratorProjection projection);
+  CuratorEvent getNextEvent(1: CuratorProjection projection) throws (1: CuratorException ex1);
 }

http://git-wip-us.apache.org/repos/asf/curator/blob/c6229cf2/curator-x-rpc/src/test/java/org/apache/curator/generated/CuratorException.java
----------------------------------------------------------------------
diff --git a/curator-x-rpc/src/test/java/org/apache/curator/generated/CuratorException.java b/curator-x-rpc/src/test/java/org/apache/curator/generated/CuratorException.java
new file mode 100644
index 0000000..b397813
--- /dev/null
+++ b/curator-x-rpc/src/test/java/org/apache/curator/generated/CuratorException.java
@@ -0,0 +1,736 @@
+/**
+ * Autogenerated by Thrift Compiler (0.9.1)
+ *
+ * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
+ *  @generated
+ */
+package org.apache.curator.generated;
+
+import org.apache.thrift.scheme.IScheme;
+import org.apache.thrift.scheme.SchemeFactory;
+import org.apache.thrift.scheme.StandardScheme;
+
+import org.apache.thrift.scheme.TupleScheme;
+import org.apache.thrift.protocol.TTupleProtocol;
+import org.apache.thrift.protocol.TProtocolException;
+import org.apache.thrift.EncodingUtils;
+import org.apache.thrift.TException;
+import org.apache.thrift.async.AsyncMethodCallback;
+import org.apache.thrift.server.AbstractNonblockingServer.*;
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Map;
+import java.util.HashMap;
+import java.util.EnumMap;
+import java.util.Set;
+import java.util.HashSet;
+import java.util.EnumSet;
+import java.util.Collections;
+import java.util.BitSet;
+import java.nio.ByteBuffer;
+import java.util.Arrays;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class CuratorException extends TException implements org.apache.thrift.TBase<CuratorException, CuratorException._Fields>, java.io.Serializable, Cloneable, Comparable<CuratorException> {
+  private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("CuratorException");
+
+  private static final org.apache.thrift.protocol.TField TYPE_FIELD_DESC = new org.apache.thrift.protocol.TField("type", org.apache.thrift.protocol.TType.I32, (short)1);
+  private static final org.apache.thrift.protocol.TField ZOO_KEEPER_EXCEPTION_FIELD_DESC = new org.apache.thrift.protocol.TField("zooKeeperException", org.apache.thrift.protocol.TType.I32, (short)2);
+  private static final org.apache.thrift.protocol.TField NODE_EXCEPTION_FIELD_DESC = new org.apache.thrift.protocol.TField("nodeException", org.apache.thrift.protocol.TType.I32, (short)3);
+  private static final org.apache.thrift.protocol.TField MESSAGE_FIELD_DESC = new org.apache.thrift.protocol.TField("message", org.apache.thrift.protocol.TType.STRING, (short)4);
+
+  private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
+  static {
+    schemes.put(StandardScheme.class, new CuratorExceptionStandardSchemeFactory());
+    schemes.put(TupleScheme.class, new CuratorExceptionTupleSchemeFactory());
+  }
+
+  /**
+   * 
+   * @see ExceptionType
+   */
+  public ExceptionType type; // required
+  /**
+   * 
+   * @see ZooKeeperExceptionType
+   */
+  public ZooKeeperExceptionType zooKeeperException; // required
+  /**
+   * 
+   * @see NodeExceptionType
+   */
+  public NodeExceptionType nodeException; // required
+  public String message; // required
+
+  /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
+  public enum _Fields implements org.apache.thrift.TFieldIdEnum {
+    /**
+     * 
+     * @see ExceptionType
+     */
+    TYPE((short)1, "type"),
+    /**
+     * 
+     * @see ZooKeeperExceptionType
+     */
+    ZOO_KEEPER_EXCEPTION((short)2, "zooKeeperException"),
+    /**
+     * 
+     * @see NodeExceptionType
+     */
+    NODE_EXCEPTION((short)3, "nodeException"),
+    MESSAGE((short)4, "message");
+
+    private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();
+
+    static {
+      for (_Fields field : EnumSet.allOf(_Fields.class)) {
+        byName.put(field.getFieldName(), field);
+      }
+    }
+
+    /**
+     * Find the _Fields constant that matches fieldId, or null if its not found.
+     */
+    public static _Fields findByThriftId(int fieldId) {
+      switch(fieldId) {
+        case 1: // TYPE
+          return TYPE;
+        case 2: // ZOO_KEEPER_EXCEPTION
+          return ZOO_KEEPER_EXCEPTION;
+        case 3: // NODE_EXCEPTION
+          return NODE_EXCEPTION;
+        case 4: // MESSAGE
+          return MESSAGE;
+        default:
+          return null;
+      }
+    }
+
+    /**
+     * Find the _Fields constant that matches fieldId, throwing an exception
+     * if it is not found.
+     */
+    public static _Fields findByThriftIdOrThrow(int fieldId) {
+      _Fields fields = findByThriftId(fieldId);
+      if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
+      return fields;
+    }
+
+    /**
+     * Find the _Fields constant that matches name, or null if its not found.
+     */
+    public static _Fields findByName(String name) {
+      return byName.get(name);
+    }
+
+    private final short _thriftId;
+    private final String _fieldName;
+
+    _Fields(short thriftId, String fieldName) {
+      _thriftId = thriftId;
+      _fieldName = fieldName;
+    }
+
+    public short getThriftFieldId() {
+      return _thriftId;
+    }
+
+    public String getFieldName() {
+      return _fieldName;
+    }
+  }
+
+  // isset id assignments
+  public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
+  static {
+    Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
+    tmpMap.put(_Fields.TYPE, new org.apache.thrift.meta_data.FieldMetaData("type", org.apache.thrift.TFieldRequirementType.DEFAULT, 
+        new org.apache.thrift.meta_data.EnumMetaData(org.apache.thrift.protocol.TType.ENUM, ExceptionType.class)));
+    tmpMap.put(_Fields.ZOO_KEEPER_EXCEPTION, new org.apache.thrift.meta_data.FieldMetaData("zooKeeperException", org.apache.thrift.TFieldRequirementType.DEFAULT, 
+        new org.apache.thrift.meta_data.EnumMetaData(org.apache.thrift.protocol.TType.ENUM, ZooKeeperExceptionType.class)));
+    tmpMap.put(_Fields.NODE_EXCEPTION, new org.apache.thrift.meta_data.FieldMetaData("nodeException", org.apache.thrift.TFieldRequirementType.DEFAULT, 
+        new org.apache.thrift.meta_data.EnumMetaData(org.apache.thrift.protocol.TType.ENUM, NodeExceptionType.class)));
+    tmpMap.put(_Fields.MESSAGE, new org.apache.thrift.meta_data.FieldMetaData("message", org.apache.thrift.TFieldRequirementType.DEFAULT, 
+        new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
+    metaDataMap = Collections.unmodifiableMap(tmpMap);
+    org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(CuratorException.class, metaDataMap);
+  }
+
+  public CuratorException() {
+  }
+
+  public CuratorException(
+    ExceptionType type,
+    ZooKeeperExceptionType zooKeeperException,
+    NodeExceptionType nodeException,
+    String message)
+  {
+    this();
+    this.type = type;
+    this.zooKeeperException = zooKeeperException;
+    this.nodeException = nodeException;
+    this.message = message;
+  }
+
+  /**
+   * Performs a deep copy on <i>other</i>.
+   */
+  public CuratorException(CuratorException other) {
+    if (other.isSetType()) {
+      this.type = other.type;
+    }
+    if (other.isSetZooKeeperException()) {
+      this.zooKeeperException = other.zooKeeperException;
+    }
+    if (other.isSetNodeException()) {
+      this.nodeException = other.nodeException;
+    }
+    if (other.isSetMessage()) {
+      this.message = other.message;
+    }
+  }
+
+  public CuratorException deepCopy() {
+    return new CuratorException(this);
+  }
+
+  @Override
+  public void clear() {
+    this.type = null;
+    this.zooKeeperException = null;
+    this.nodeException = null;
+    this.message = null;
+  }
+
+  /**
+   * 
+   * @see ExceptionType
+   */
+  public ExceptionType getType() {
+    return this.type;
+  }
+
+  /**
+   * 
+   * @see ExceptionType
+   */
+  public CuratorException setType(ExceptionType type) {
+    this.type = type;
+    return this;
+  }
+
+  public void unsetType() {
+    this.type = null;
+  }
+
+  /** Returns true if field type is set (has been assigned a value) and false otherwise */
+  public boolean isSetType() {
+    return this.type != null;
+  }
+
+  public void setTypeIsSet(boolean value) {
+    if (!value) {
+      this.type = null;
+    }
+  }
+
+  /**
+   * 
+   * @see ZooKeeperExceptionType
+   */
+  public ZooKeeperExceptionType getZooKeeperException() {
+    return this.zooKeeperException;
+  }
+
+  /**
+   * 
+   * @see ZooKeeperExceptionType
+   */
+  public CuratorException setZooKeeperException(ZooKeeperExceptionType zooKeeperException) {
+    this.zooKeeperException = zooKeeperException;
+    return this;
+  }
+
+  public void unsetZooKeeperException() {
+    this.zooKeeperException = null;
+  }
+
+  /** Returns true if field zooKeeperException is set (has been assigned a value) and false otherwise */
+  public boolean isSetZooKeeperException() {
+    return this.zooKeeperException != null;
+  }
+
+  public void setZooKeeperExceptionIsSet(boolean value) {
+    if (!value) {
+      this.zooKeeperException = null;
+    }
+  }
+
+  /**
+   * 
+   * @see NodeExceptionType
+   */
+  public NodeExceptionType getNodeException() {
+    return this.nodeException;
+  }
+
+  /**
+   * 
+   * @see NodeExceptionType
+   */
+  public CuratorException setNodeException(NodeExceptionType nodeException) {
+    this.nodeException = nodeException;
+    return this;
+  }
+
+  public void unsetNodeException() {
+    this.nodeException = null;
+  }
+
+  /** Returns true if field nodeException is set (has been assigned a value) and false otherwise */
+  public boolean isSetNodeException() {
+    return this.nodeException != null;
+  }
+
+  public void setNodeExceptionIsSet(boolean value) {
+    if (!value) {
+      this.nodeException = null;
+    }
+  }
+
+  public String getMessage() {
+    return this.message;
+  }
+
+  public CuratorException setMessage(String message) {
+    this.message = message;
+    return this;
+  }
+
+  public void unsetMessage() {
+    this.message = null;
+  }
+
+  /** Returns true if field message is set (has been assigned a value) and false otherwise */
+  public boolean isSetMessage() {
+    return this.message != null;
+  }
+
+  public void setMessageIsSet(boolean value) {
+    if (!value) {
+      this.message = null;
+    }
+  }
+
+  public void setFieldValue(_Fields field, Object value) {
+    switch (field) {
+    case TYPE:
+      if (value == null) {
+        unsetType();
+      } else {
+        setType((ExceptionType)value);
+      }
+      break;
+
+    case ZOO_KEEPER_EXCEPTION:
+      if (value == null) {
+        unsetZooKeeperException();
+      } else {
+        setZooKeeperException((ZooKeeperExceptionType)value);
+      }
+      break;
+
+    case NODE_EXCEPTION:
+      if (value == null) {
+        unsetNodeException();
+      } else {
+        setNodeException((NodeExceptionType)value);
+      }
+      break;
+
+    case MESSAGE:
+      if (value == null) {
+        unsetMessage();
+      } else {
+        setMessage((String)value);
+      }
+      break;
+
+    }
+  }
+
+  public Object getFieldValue(_Fields field) {
+    switch (field) {
+    case TYPE:
+      return getType();
+
+    case ZOO_KEEPER_EXCEPTION:
+      return getZooKeeperException();
+
+    case NODE_EXCEPTION:
+      return getNodeException();
+
+    case MESSAGE:
+      return getMessage();
+
+    }
+    throw new IllegalStateException();
+  }
+
+  /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
+  public boolean isSet(_Fields field) {
+    if (field == null) {
+      throw new IllegalArgumentException();
+    }
+
+    switch (field) {
+    case TYPE:
+      return isSetType();
+    case ZOO_KEEPER_EXCEPTION:
+      return isSetZooKeeperException();
+    case NODE_EXCEPTION:
+      return isSetNodeException();
+    case MESSAGE:
+      return isSetMessage();
+    }
+    throw new IllegalStateException();
+  }
+
+  @Override
+  public boolean equals(Object that) {
+    if (that == null)
+      return false;
+    if (that instanceof CuratorException)
+      return this.equals((CuratorException)that);
+    return false;
+  }
+
+  public boolean equals(CuratorException that) {
+    if (that == null)
+      return false;
+
+    boolean this_present_type = true && this.isSetType();
+    boolean that_present_type = true && that.isSetType();
+    if (this_present_type || that_present_type) {
+      if (!(this_present_type && that_present_type))
+        return false;
+      if (!this.type.equals(that.type))
+        return false;
+    }
+
+    boolean this_present_zooKeeperException = true && this.isSetZooKeeperException();
+    boolean that_present_zooKeeperException = true && that.isSetZooKeeperException();
+    if (this_present_zooKeeperException || that_present_zooKeeperException) {
+      if (!(this_present_zooKeeperException && that_present_zooKeeperException))
+        return false;
+      if (!this.zooKeeperException.equals(that.zooKeeperException))
+        return false;
+    }
+
+    boolean this_present_nodeException = true && this.isSetNodeException();
+    boolean that_present_nodeException = true && that.isSetNodeException();
+    if (this_present_nodeException || that_present_nodeException) {
+      if (!(this_present_nodeException && that_present_nodeException))
+        return false;
+      if (!this.nodeException.equals(that.nodeException))
+        return false;
+    }
+
+    boolean this_present_message = true && this.isSetMessage();
+    boolean that_present_message = true && that.isSetMessage();
+    if (this_present_message || that_present_message) {
+      if (!(this_present_message && that_present_message))
+        return false;
+      if (!this.message.equals(that.message))
+        return false;
+    }
+
+    return true;
+  }
+
+  @Override
+  public int hashCode() {
+    return 0;
+  }
+
+  @Override
+  public int compareTo(CuratorException other) {
+    if (!getClass().equals(other.getClass())) {
+      return getClass().getName().compareTo(other.getClass().getName());
+    }
+
+    int lastComparison = 0;
+
+    lastComparison = Boolean.valueOf(isSetType()).compareTo(other.isSetType());
+    if (lastComparison != 0) {
+      return lastComparison;
+    }
+    if (isSetType()) {
+      lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.type, other.type);
+      if (lastComparison != 0) {
+        return lastComparison;
+      }
+    }
+    lastComparison = Boolean.valueOf(isSetZooKeeperException()).compareTo(other.isSetZooKeeperException());
+    if (lastComparison != 0) {
+      return lastComparison;
+    }
+    if (isSetZooKeeperException()) {
+      lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.zooKeeperException, other.zooKeeperException);
+      if (lastComparison != 0) {
+        return lastComparison;
+      }
+    }
+    lastComparison = Boolean.valueOf(isSetNodeException()).compareTo(other.isSetNodeException());
+    if (lastComparison != 0) {
+      return lastComparison;
+    }
+    if (isSetNodeException()) {
+      lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.nodeException, other.nodeException);
+      if (lastComparison != 0) {
+        return lastComparison;
+      }
+    }
+    lastComparison = Boolean.valueOf(isSetMessage()).compareTo(other.isSetMessage());
+    if (lastComparison != 0) {
+      return lastComparison;
+    }
+    if (isSetMessage()) {
+      lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.message, other.message);
+      if (lastComparison != 0) {
+        return lastComparison;
+      }
+    }
+    return 0;
+  }
+
+  public _Fields fieldForId(int fieldId) {
+    return _Fields.findByThriftId(fieldId);
+  }
+
+  public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
+    schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
+  }
+
+  public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
+    schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
+  }
+
+  @Override
+  public String toString() {
+    StringBuilder sb = new StringBuilder("CuratorException(");
+    boolean first = true;
+
+    sb.append("type:");
+    if (this.type == null) {
+      sb.append("null");
+    } else {
+      sb.append(this.type);
+    }
+    first = false;
+    if (!first) sb.append(", ");
+    sb.append("zooKeeperException:");
+    if (this.zooKeeperException == null) {
+      sb.append("null");
+    } else {
+      sb.append(this.zooKeeperException);
+    }
+    first = false;
+    if (!first) sb.append(", ");
+    sb.append("nodeException:");
+    if (this.nodeException == null) {
+      sb.append("null");
+    } else {
+      sb.append(this.nodeException);
+    }
+    first = false;
+    if (!first) sb.append(", ");
+    sb.append("message:");
+    if (this.message == null) {
+      sb.append("null");
+    } else {
+      sb.append(this.message);
+    }
+    first = false;
+    sb.append(")");
+    return sb.toString();
+  }
+
+  public void validate() throws org.apache.thrift.TException {
+    // check for required fields
+    // check for sub-struct validity
+  }
+
+  private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
+    try {
+      write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
+    } catch (org.apache.thrift.TException te) {
+      throw new java.io.IOException(te);
+    }
+  }
+
+  private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
+    try {
+      read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
+    } catch (org.apache.thrift.TException te) {
+      throw new java.io.IOException(te);
+    }
+  }
+
+  private static class CuratorExceptionStandardSchemeFactory implements SchemeFactory {
+    public CuratorExceptionStandardScheme getScheme() {
+      return new CuratorExceptionStandardScheme();
+    }
+  }
+
+  private static class CuratorExceptionStandardScheme extends StandardScheme<CuratorException> {
+
+    public void read(org.apache.thrift.protocol.TProtocol iprot, CuratorException struct) throws org.apache.thrift.TException {
+      org.apache.thrift.protocol.TField schemeField;
+      iprot.readStructBegin();
+      while (true)
+      {
+        schemeField = iprot.readFieldBegin();
+        if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
+          break;
+        }
+        switch (schemeField.id) {
+          case 1: // TYPE
+            if (schemeField.type == org.apache.thrift.protocol.TType.I32) {
+              struct.type = ExceptionType.findByValue(iprot.readI32());
+              struct.setTypeIsSet(true);
+            } else { 
+              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
+            }
+            break;
+          case 2: // ZOO_KEEPER_EXCEPTION
+            if (schemeField.type == org.apache.thrift.protocol.TType.I32) {
+              struct.zooKeeperException = ZooKeeperExceptionType.findByValue(iprot.readI32());
+              struct.setZooKeeperExceptionIsSet(true);
+            } else { 
+              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
+            }
+            break;
+          case 3: // NODE_EXCEPTION
+            if (schemeField.type == org.apache.thrift.protocol.TType.I32) {
+              struct.nodeException = NodeExceptionType.findByValue(iprot.readI32());
+              struct.setNodeExceptionIsSet(true);
+            } else { 
+              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
+            }
+            break;
+          case 4: // MESSAGE
+            if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
+              struct.message = iprot.readString();
+              struct.setMessageIsSet(true);
+            } else { 
+              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
+            }
+            break;
+          default:
+            org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
+        }
+        iprot.readFieldEnd();
+      }
+      iprot.readStructEnd();
+
+      // check for required fields of primitive type, which can't be checked in the validate method
+      struct.validate();
+    }
+
+    public void write(org.apache.thrift.protocol.TProtocol oprot, CuratorException struct) throws org.apache.thrift.TException {
+      struct.validate();
+
+      oprot.writeStructBegin(STRUCT_DESC);
+      if (struct.type != null) {
+        oprot.writeFieldBegin(TYPE_FIELD_DESC);
+        oprot.writeI32(struct.type.getValue());
+        oprot.writeFieldEnd();
+      }
+      if (struct.zooKeeperException != null) {
+        oprot.writeFieldBegin(ZOO_KEEPER_EXCEPTION_FIELD_DESC);
+        oprot.writeI32(struct.zooKeeperException.getValue());
+        oprot.writeFieldEnd();
+      }
+      if (struct.nodeException != null) {
+        oprot.writeFieldBegin(NODE_EXCEPTION_FIELD_DESC);
+        oprot.writeI32(struct.nodeException.getValue());
+        oprot.writeFieldEnd();
+      }
+      if (struct.message != null) {
+        oprot.writeFieldBegin(MESSAGE_FIELD_DESC);
+        oprot.writeString(struct.message);
+        oprot.writeFieldEnd();
+      }
+      oprot.writeFieldStop();
+      oprot.writeStructEnd();
+    }
+
+  }
+
+  private static class CuratorExceptionTupleSchemeFactory implements SchemeFactory {
+    public CuratorExceptionTupleScheme getScheme() {
+      return new CuratorExceptionTupleScheme();
+    }
+  }
+
+  private static class CuratorExceptionTupleScheme extends TupleScheme<CuratorException> {
+
+    @Override
+    public void write(org.apache.thrift.protocol.TProtocol prot, CuratorException struct) throws org.apache.thrift.TException {
+      TTupleProtocol oprot = (TTupleProtocol) prot;
+      BitSet optionals = new BitSet();
+      if (struct.isSetType()) {
+        optionals.set(0);
+      }
+      if (struct.isSetZooKeeperException()) {
+        optionals.set(1);
+      }
+      if (struct.isSetNodeException()) {
+        optionals.set(2);
+      }
+      if (struct.isSetMessage()) {
+        optionals.set(3);
+      }
+      oprot.writeBitSet(optionals, 4);
+      if (struct.isSetType()) {
+        oprot.writeI32(struct.type.getValue());
+      }
+      if (struct.isSetZooKeeperException()) {
+        oprot.writeI32(struct.zooKeeperException.getValue());
+      }
+      if (struct.isSetNodeException()) {
+        oprot.writeI32(struct.nodeException.getValue());
+      }
+      if (struct.isSetMessage()) {
+        oprot.writeString(struct.message);
+      }
+    }
+
+    @Override
+    public void read(org.apache.thrift.protocol.TProtocol prot, CuratorException struct) throws org.apache.thrift.TException {
+      TTupleProtocol iprot = (TTupleProtocol) prot;
+      BitSet incoming = iprot.readBitSet(4);
+      if (incoming.get(0)) {
+        struct.type = ExceptionType.findByValue(iprot.readI32());
+        struct.setTypeIsSet(true);
+      }
+      if (incoming.get(1)) {
+        struct.zooKeeperException = ZooKeeperExceptionType.findByValue(iprot.readI32());
+        struct.setZooKeeperExceptionIsSet(true);
+      }
+      if (incoming.get(2)) {
+        struct.nodeException = NodeExceptionType.findByValue(iprot.readI32());
+        struct.setNodeExceptionIsSet(true);
+      }
+      if (incoming.get(3)) {
+        struct.message = iprot.readString();
+        struct.setMessageIsSet(true);
+      }
+    }
+  }
+
+}
+