diff --git a/flink-runtime/src/main/java/org/apache/flink/runtime/zookeeper/ZookeeperAccess.java b/flink-runtime/src/main/java/org/apache/flink/runtime/zookeeper/ZookeeperAccess.java
new file mode 100644
index 0000000000000..2c6160a7a9b65
--- /dev/null
+++ b/flink-runtime/src/main/java/org/apache/flink/runtime/zookeeper/ZookeeperAccess.java
@@ -0,0 +1,66 @@
+/*
+ * 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.flink.runtime.zookeeper;
+
+import org.apache.zookeeper.KeeperException;
+
+import java.util.ConcurrentModificationException;
+
+/**
+ * Utility class providing access to relocated zookeeper classes.
+ *
+ * This class is necessary as flink-runtime relocates its ZooKeeper dependency.
+ * Other modules may still depend on this dependency but will encounter a ClassNotFoundException
+ * on access as they don't apply the relocation pattern of flink-runtime.
+ */
+public final class ZookeeperAccess {
+
+ private ZookeeperAccess(){
+ }
+
+ /**
+ * Wraps and returns the given exception in a {@link ConcurrentModificationException} if it is a
+ * {@link org.apache.zookeeper.KeeperException.NodeExistsException}. Otherwise the
+ * given exception is returned.
+ *
+ * @param ex exception to wrap
+ * @return wrapping ConcurrentModificationException if it is a NodeExistsException, otherwise the given exception
+ */
+ public static Exception wrapIfZooKeeperNodeExistsException(Exception ex) {
+ if (ex instanceof KeeperException.NodeExistsException) {
+ return new ConcurrentModificationException("ZooKeeper unexpectedly modified", ex);
+ }
+ return ex;
+ }
+
+ /**
+ * Wraps and returns the given exception in a {@link ConcurrentModificationException} if it is a
+ * {@link org.apache.zookeeper.KeeperException.NoNodeException}. Otherwise the
+ * given exception is returned.
+ *
+ * @param ex exception to wrap
+ * @return wrapping ConcurrentModificationException if it is a NoNodeException, otherwise the given exception
+ */
+ public static Exception wrapIfZooKeeperNoNodeException(Exception ex) {
+ if (ex instanceof KeeperException.NoNodeException) {
+ return new ConcurrentModificationException("ZooKeeper unexpectedly modified", ex);
+ }
+ return ex;
+ }
+}
diff --git a/flink-shaded-curator-recipes/pom.xml b/flink-shaded-curator-recipes/pom.xml
new file mode 100644
index 0000000000000..06d38216cee71
--- /dev/null
+++ b/flink-shaded-curator-recipes/pom.xml
@@ -0,0 +1,88 @@
+
+
+
+
+ 4.0.0
+
+
+ org.apache.flink
+ flink-parent
+ 1.4-SNAPSHOT
+ ..
+
+
+ flink-shaded-curator-recipes
+ flink-shaded-curator-recipes
+
+ jar
+
+
+
+
+ org.apache.curator
+ curator-recipes
+ ${curator.version}
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-shade-plugin
+
+
+ shade-flink
+ package
+
+ shade
+
+
+
+
+ com.google.guava:guava
+ org.apache.curator:*
+
+
+
+
+ com.google.guava:guava
+
+
+ com/google/common/base/Function.class
+ com/google/common/base/Predicate.class
+ com/google/common/reflect/TypeToken.class
+
+
+
+
+
+ com.google.common
+ org.apache.flink.curator.shaded.com.google.common
+
+
+
+
+
+
+
+
+
diff --git a/flink-shaded-hadoop/pom.xml b/flink-shaded-hadoop/pom.xml
index f4b0816125dc5..ba90fc9f18717 100644
--- a/flink-shaded-hadoop/pom.xml
+++ b/flink-shaded-hadoop/pom.xml
@@ -52,11 +52,6 @@ under the License.
slf4j-api
provided
-
- org.apache.zookeeper
- zookeeper
- provided
-
org.apache.avro
avro
diff --git a/pom.xml b/pom.xml
index a5f99f70dec9c..faddab4a6543e 100644
--- a/pom.xml
+++ b/pom.xml
@@ -54,6 +54,7 @@ under the License.
tools/force-shading
flink-annotations
flink-shaded-hadoop
+ flink-shaded-curator-recipes
flink-core
flink-java
flink-java8
diff --git a/tools/travis_mvn_watchdog.sh b/tools/travis_mvn_watchdog.sh
index b7e3709f90b9f..978bc9f7acf87 100755
--- a/tools/travis_mvn_watchdog.sh
+++ b/tools/travis_mvn_watchdog.sh
@@ -325,6 +325,22 @@ check_shaded_artifacts() {
return 1
fi
+ ZOOKEEPER=`cat allClasses | grep '^org/apache/zookeeper' | wc -l`
+ if [ "$ZOOKEEPER" != "0" ]; then
+ echo "=============================================================================="
+ echo "Detected '$ZOOKEEPER' unshaded org.apache.zookeeper classes in fat jar"
+ echo "=============================================================================="
+ return 1
+ fi
+
+ CURATOR=`cat allClasses | grep '^org/apache/curator' | wc -l`
+ if [ "$CURATOR" != "0" ]; then
+ echo "=============================================================================="
+ echo "Detected '$CURATOR' unshaded org.apache.curator classes in fat jar"
+ echo "=============================================================================="
+ return 1
+ fi
+
FLINK_PYTHON=`cat allClasses | grep '^org/apache/flink/python' | wc -l`
if [ "$FLINK_PYTHON" != "0" ]; then
echo "=============================================================================="