You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by ac...@apache.org on 2016/10/28 08:53:05 UTC
[2/3] camel git commit: CAMEL-10292 - camel-zookeeper added new
RoutePolicy
CAMEL-10292 - camel-zookeeper added new RoutePolicy
Project: http://git-wip-us.apache.org/repos/asf/camel/repo
Commit: http://git-wip-us.apache.org/repos/asf/camel/commit/34ea6c98
Tree: http://git-wip-us.apache.org/repos/asf/camel/tree/34ea6c98
Diff: http://git-wip-us.apache.org/repos/asf/camel/diff/34ea6c98
Branch: refs/heads/master
Commit: 34ea6c98e37cbcd65a725f1e34d0f27ec0e56dd3
Parents: 495f081
Author: Paolo Antinori <pa...@redhat.com>
Authored: Thu Oct 27 17:36:36 2016 +0200
Committer: Andrea Cosentino <an...@gmail.com>
Committed: Fri Oct 28 10:49:27 2016 +0200
----------------------------------------------------------------------
components/camel-zookeeper/pom.xml | 15 ++
.../component/zookeeper/ZooKeeperProducer.java | 3 +
.../zookeeper/policy/CuratorLeaderElection.java | 171 +++++++++++++++++++
.../policy/CuratorLeaderRoutePolicy.java | 167 ++++++++++++++++++
.../FailoverCuratorLeaderRoutePolicyTest.java | 143 ++++++++++++++++
.../src/test/resources/log4j2.properties | 10 +-
parent/pom.xml | 1 +
7 files changed, 509 insertions(+), 1 deletion(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/camel/blob/34ea6c98/components/camel-zookeeper/pom.xml
----------------------------------------------------------------------
diff --git a/components/camel-zookeeper/pom.xml b/components/camel-zookeeper/pom.xml
index 689c064..2021d2c 100644
--- a/components/camel-zookeeper/pom.xml
+++ b/components/camel-zookeeper/pom.xml
@@ -44,6 +44,7 @@
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
+ <version>${zookeeper-version}</version>
<!-- Just exclude the old version of netty to avoid netty version conflict-->
<exclusions>
<exclusion>
@@ -66,6 +67,20 @@
<version>${netty3-version}</version>
</dependency>
+ <dependency>
+ <groupId>org.apache.curator</groupId>
+ <artifactId>curator-framework</artifactId>
+ <version>${curator-version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.curator</groupId>
+ <artifactId>curator-recipes</artifactId>
+ <version>${curator-version}</version>
+ </dependency>
+
+
+
<!-- test dependencies -->
<dependency>
<groupId>org.apache.camel</groupId>
http://git-wip-us.apache.org/repos/asf/camel/blob/34ea6c98/components/camel-zookeeper/src/main/java/org/apache/camel/component/zookeeper/ZooKeeperProducer.java
----------------------------------------------------------------------
diff --git a/components/camel-zookeeper/src/main/java/org/apache/camel/component/zookeeper/ZooKeeperProducer.java b/components/camel-zookeeper/src/main/java/org/apache/camel/component/zookeeper/ZooKeeperProducer.java
index 449a138..9c01632 100644
--- a/components/camel-zookeeper/src/main/java/org/apache/camel/component/zookeeper/ZooKeeperProducer.java
+++ b/components/camel-zookeeper/src/main/java/org/apache/camel/component/zookeeper/ZooKeeperProducer.java
@@ -64,6 +64,9 @@ public class ZooKeeperProducer extends DefaultProducer {
public void process(Exchange exchange) throws Exception {
+ if(connection == null){
+ connection = this.zkm.getConnection();
+ }
ProductionContext context = new ProductionContext(connection, exchange);
String operation = exchange.getIn().getHeader(ZooKeeperMessage.ZOOKEEPER_OPERATION, String.class);
http://git-wip-us.apache.org/repos/asf/camel/blob/34ea6c98/components/camel-zookeeper/src/main/java/org/apache/camel/component/zookeeper/policy/CuratorLeaderElection.java
----------------------------------------------------------------------
diff --git a/components/camel-zookeeper/src/main/java/org/apache/camel/component/zookeeper/policy/CuratorLeaderElection.java b/components/camel-zookeeper/src/main/java/org/apache/camel/component/zookeeper/policy/CuratorLeaderElection.java
new file mode 100644
index 0000000..b0cf654
--- /dev/null
+++ b/components/camel-zookeeper/src/main/java/org/apache/camel/component/zookeeper/policy/CuratorLeaderElection.java
@@ -0,0 +1,171 @@
+/**
+ * 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.camel.component.zookeeper.policy;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.ProducerTemplate;
+import org.apache.camel.StatefulService;
+import org.apache.camel.impl.JavaUuidGenerator;
+import org.apache.camel.spi.UuidGenerator;
+import org.apache.curator.RetryPolicy;
+import org.apache.curator.framework.CuratorFramework;
+import org.apache.curator.framework.CuratorFrameworkFactory;
+import org.apache.curator.framework.recipes.leader.LeaderSelector;
+import org.apache.curator.framework.recipes.leader.LeaderSelectorListenerAdapter;
+import org.apache.curator.retry.ExponentialBackoffRetry;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
+
+/**
+ * <code>CuratorLeaderElection</code> uses the leader election capabilities of a
+ * ZooKeeper cluster to control which nodes are enabled. It is typically used in
+ * fail-over scenarios controlling identical instances of an application across
+ * a cluster of Camel based servers. <p> The election is configured with a single
+ * server that should be marked as master.
+ * <p> All instances of the election must also be configured with the same path on the ZooKeeper
+ * cluster where the election will be carried out. It is good practice for this
+ * to indicate the application e.g. <tt>/someapplication/someroute/</tt> note
+ * that these nodes should exist before using the election. <p> See <a
+ * href="http://hadoop.apache.org/zookeeper/docs/current/recipes.html#sc_leaderElection">
+ * for more on how Leader election</a> is archived with ZooKeeper.
+ */
+public class CuratorLeaderElection {
+
+ private static final Logger LOG = LoggerFactory.getLogger(CuratorLeaderElection.class);
+ private final ProducerTemplate producerTemplate;
+ private final CamelContext camelContext;
+ private final String uri;
+
+ private final String candidateName;
+ private final Lock lock = new ReentrantLock();
+ private final CountDownLatch electionComplete = new CountDownLatch(1);
+ private AtomicBoolean masterNode = new AtomicBoolean(false);
+ private volatile boolean isCandidateCreated;
+ private int enabledCount = 1;
+ private UuidGenerator uuidGenerator = new JavaUuidGenerator();
+ private final List<ElectionWatcher> watchers = new ArrayList<ElectionWatcher>();
+
+ private LeaderSelector leaderSelector;
+ private CuratorFramework client;
+
+ public CuratorLeaderElection(CamelContext camelContext, String uri) {
+ this(camelContext.createProducerTemplate(), camelContext, uri);
+ }
+
+ public CuratorLeaderElection(ProducerTemplate producerTemplate, CamelContext camelContext, String uri) {
+ this.camelContext = camelContext;
+ this.producerTemplate = producerTemplate;
+ this.uri = uri;
+ this.candidateName = createCandidateName();
+
+ String connectionString = uri.substring( 1 + uri.indexOf(':')).split("/")[0];
+ String protocol = uri.substring(0, uri.indexOf(':'));
+ String path = uri.replace(protocol + ":" + connectionString, "" );
+ client = CuratorFrameworkFactory.newClient(connectionString, new ExponentialBackoffRetry(1000, 3));
+ client.start();
+
+ leaderSelector = new LeaderSelector(client, path, new CamelLeaderElectionListener());
+ leaderSelector.start();
+ }
+
+ public void shutdownClients(){
+ try {
+ leaderSelector.close();
+ } finally{
+ client.close();
+ }
+ }
+
+ public boolean isMaster() {
+ return masterNode.get();
+ }
+
+ private String createCandidateName() {
+ StringBuilder builder = new StringBuilder();
+ try {
+ /* UUID would be enough, also using hostname for human readability */
+ builder.append(InetAddress.getLocalHost().getCanonicalHostName());
+ } catch (UnknownHostException ex) {
+ LOG.warn("Failed to get the local hostname.", ex);
+ builder.append("unknown-host");
+ }
+ builder.append("-").append(uuidGenerator.generateUuid());
+ return builder.toString();
+ }
+
+ public String getCandidateName() {
+ return candidateName;
+ }
+
+
+ private void notifyElectionWatchers() {
+ for (ElectionWatcher watcher : watchers) {
+ try {
+ watcher.electionResultChanged();
+ } catch (Exception e) {
+ LOG.warn("Election watcher " + watcher + " of type " + watcher.getClass() + " threw an exception.", e);
+ }
+ }
+ }
+
+ public boolean addElectionWatcher(ElectionWatcher e) {
+ return watchers.add(e);
+ }
+
+ // stolen from org/apache/camel/processor/CamelInternalProcessor
+ public static boolean isCamelStopping(CamelContext context) {
+ if (context instanceof StatefulService) {
+ StatefulService ss = (StatefulService) context;
+ return ss.isStopping() || ss.isStopped();
+ }
+ return false;
+ }
+
+ class CamelLeaderElectionListener extends LeaderSelectorListenerAdapter{
+
+ @Override
+ public void takeLeadership(CuratorFramework curatorFramework) throws Exception {
+ masterNode.set(true);
+ LOG.info("{} is now leader", getCandidateName());
+ notifyElectionWatchers();
+
+ // this is supposed to never return as long as it wants to keep its own leader status
+ while(!isCamelStopping(camelContext)){
+ try {
+ Thread.sleep(5000);
+ } catch (InterruptedException e){
+ Thread.interrupted();
+ break;
+ }
+ }
+ masterNode.set(false);
+ LOG.info("{} has given up its own leadership", getCandidateName());
+ notifyElectionWatchers();
+ }
+ }
+}
+
+
http://git-wip-us.apache.org/repos/asf/camel/blob/34ea6c98/components/camel-zookeeper/src/main/java/org/apache/camel/component/zookeeper/policy/CuratorLeaderRoutePolicy.java
----------------------------------------------------------------------
diff --git a/components/camel-zookeeper/src/main/java/org/apache/camel/component/zookeeper/policy/CuratorLeaderRoutePolicy.java b/components/camel-zookeeper/src/main/java/org/apache/camel/component/zookeeper/policy/CuratorLeaderRoutePolicy.java
new file mode 100644
index 0000000..6033989
--- /dev/null
+++ b/components/camel-zookeeper/src/main/java/org/apache/camel/component/zookeeper/policy/CuratorLeaderRoutePolicy.java
@@ -0,0 +1,167 @@
+/**
+ * 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
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * 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.camel.component.zookeeper.policy;
+
+import org.apache.camel.NonManagedService;
+import org.apache.camel.Route;
+import org.apache.camel.support.RoutePolicySupport;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Set;
+import java.util.concurrent.CopyOnWriteArraySet;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
+
+/**
+ * <code>CuratorLeaderRoutePolicy</code> uses Apache Curator LeaderElection receipe to implement the behavior of having
+ * at max 1 instance of a route, controlled by a specific policy, running. It is typically used in
+ * fail-over scenarios controlling identical instances of a route across a
+ * cluster of Camel based servers.
+ * <p>
+ * The policy affects the normal startup lifecycle of CamelContext and Routes, automatically set autoStart property of
+ * routes controlled by this policy to false.
+ * After Curator receipe identiffies the current Policy instance as the Leader between a set of clients that are
+ * competing for the role, it will start the route, and only at that moment the route will start its business.
+ * This specific behavior is designed to avoid scenarios where such a policy would kick in only after a route had
+ * already been started, with the risk, for consumers for example, that some source event might have already been
+ * consumed.
+ * <p>
+ * All instances of the policy must also be configured with the same path on the
+ * ZooKeeper cluster where the election will be carried out. It is good practice
+ * for this to indicate the application e.g. <tt>/someapplication/someroute/</tt> note
+ * that these nodes should exist before using the policy.
+ * <p>
+ * See <a href="http://hadoop.apache.org/zookeeper/docs/current/recipes.html#sc_leaderElection">
+ * for more on how Leader election</a> is archived with ZooKeeper.
+ */
+public class CuratorLeaderRoutePolicy extends RoutePolicySupport implements ElectionWatcher, NonManagedService {
+
+ private static final Logger LOG = LoggerFactory.getLogger(CuratorLeaderRoutePolicy.class);
+ private final String uri;
+ private final Lock lock = new ReentrantLock();
+ private final Set<Route> suspendedRoutes = new CopyOnWriteArraySet<Route>();
+ private final AtomicBoolean shouldProcessExchanges = new AtomicBoolean();
+ private volatile boolean shouldStopRoute = true;
+
+ private final Lock electionLock = new ReentrantLock();
+ private CuratorLeaderElection election;
+
+ public CuratorLeaderRoutePolicy(String uri) {
+ this.uri = uri;
+ }
+
+ public CuratorLeaderRoutePolicy(CuratorLeaderElection election) {
+ this.election = election;
+ this.uri = null;
+ }
+
+ @Override
+ public void onInit(Route route) {
+ ensureElectionIsCreated(route);
+ LOG.info("Route managed by {}. Setting route {} AutoStartup flag to false.", this.getClass(), route.getId());
+ route.getRouteContext().getRoute().setAutoStartup("false");
+ ensureElectionIsCreated(route);
+
+ if (election.isMaster()) {
+ if (shouldStopRoute) {
+ startManagedRoute(route);
+ }
+ } else {
+ if (shouldStopRoute) {
+ stopManagedRoute(route);
+ }
+ }
+ }
+
+ private void ensureElectionIsCreated(Route route) {
+ if (election == null) {
+ electionLock.lock();
+ try {
+ if (election == null) { // re-test
+ election = new CuratorLeaderElection(route.getRouteContext().getCamelContext(), uri);
+ election.addElectionWatcher(this);
+ }
+ } finally {
+ electionLock.unlock();
+ }
+ }
+ }
+
+ private void startManagedRoute(Route route) {
+ try {
+ lock.lock();
+ if (suspendedRoutes.contains(route)) {
+ startRoute(route);
+ suspendedRoutes.remove(route);
+ }
+ } catch (Exception e) {
+ handleException(e);
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ private void stopManagedRoute(Route route) {
+ try {
+ lock.lock();
+ // check that we should still suspend once the lock is acquired
+ if (!suspendedRoutes.contains(route) && !shouldProcessExchanges.get()) {
+ stopRoute(route);
+ suspendedRoutes.add(route);
+ }
+ } catch (Exception e) {
+ handleException(e);
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ @Override
+ public void electionResultChanged() {
+ if (election.isMaster()) {
+ startAllStoppedRoutes();
+ }
+ }
+
+ private void startAllStoppedRoutes() {
+ try {
+ lock.lock();
+ if (!suspendedRoutes.isEmpty()) {
+ if (log.isDebugEnabled()) {
+ log.debug("{} route(s) have been stopped previously by policy, restarting.", suspendedRoutes.size());
+ }
+ for (Route suspended : suspendedRoutes) {
+ log.debug("Starting route {}.", suspended.getId());
+ startRoute(suspended);
+ }
+ suspendedRoutes.clear();
+ }
+
+ } catch (Exception e) {
+ handleException(e);
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ @Override
+ protected void doShutdown() throws Exception {
+ election.shutdownClients();
+ }
+}
http://git-wip-us.apache.org/repos/asf/camel/blob/34ea6c98/components/camel-zookeeper/src/test/java/org/apache/camel/component/zookeeper/policy/FailoverCuratorLeaderRoutePolicyTest.java
----------------------------------------------------------------------
diff --git a/components/camel-zookeeper/src/test/java/org/apache/camel/component/zookeeper/policy/FailoverCuratorLeaderRoutePolicyTest.java b/components/camel-zookeeper/src/test/java/org/apache/camel/component/zookeeper/policy/FailoverCuratorLeaderRoutePolicyTest.java
new file mode 100644
index 0000000..4cc9742
--- /dev/null
+++ b/components/camel-zookeeper/src/test/java/org/apache/camel/component/zookeeper/policy/FailoverCuratorLeaderRoutePolicyTest.java
@@ -0,0 +1,143 @@
+/**
+ * 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
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * 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.camel.component.zookeeper.policy;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.ExchangePattern;
+import org.apache.camel.ProducerTemplate;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.component.zookeeper.ZooKeeperTestSupport;
+import org.apache.camel.impl.DefaultCamelContext;
+import org.apache.commons.logging.LogFactory;
+import org.junit.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.concurrent.TimeUnit;
+
+import static org.hamcrest.CoreMatchers.is;
+
+public class FailoverCuratorLeaderRoutePolicyTest extends ZooKeeperTestSupport {
+ private static final Logger LOG = LoggerFactory.getLogger(FailoverCuratorLeaderRoutePolicyTest.class);
+ static final String ZNODE = "/curatorleader";
+ public static final String BASE_ZNODE = "/someapp";
+
+ protected CamelContext createCamelContext() throws Exception {
+ disableJMX();
+ return super.createCamelContext();
+ }
+
+ @Test
+ public void masterSlaveScenarioContolledByPolicy() throws Exception {
+ ZookeeperPolicyEnforcedContext master = createEnforcedContext("master");
+ ZookeeperPolicyEnforcedContext slave = createEnforcedContext("slave");
+ Thread.sleep(5000);
+ // Send messages to the master and the slave.
+ // The route is enabled in the master and gets through, but that sent to
+ // the slave context is rejected.
+ master.sendMessageToEnforcedRoute("message for master", 1);
+ slave.sendMessageToEnforcedRoute("message for slave", 0);
+
+ // trigger failover by killing the master... then assert that the slave
+ // can now receive messages.
+ master.shutdown();
+ slave.sendMessageToEnforcedRoute("second message for slave", 1);
+ slave.shutdown();
+ }
+
+
+ @Test
+ public void ensureRoutesDoNotStartBeforeElection() throws Exception {
+ DefaultCamelContext context = new DefaultCamelContext();
+
+ context.addRoutes(new RouteBuilder() {
+ @Override
+ public void configure() throws Exception {
+ CuratorLeaderRoutePolicy policy = new CuratorLeaderRoutePolicy("zookeeper:localhost:" + getServerPort() + BASE_ZNODE + ZNODE + 2);
+ from("timer://foo?fixedRate=true&period=5").routePolicy(policy).id("single_route").autoStartup(true).to("mock:controlled");
+ }
+ });
+ context.start();
+ // this check verifies that a route marked as autostartable is not started automatically. It will be the policy responsibility to eventually start it.
+ assertThat(context.getRouteStatus("single_route").isStarted(), is(false));
+ assertThat(context.getRouteStatus("single_route").isStarting(), is(false));
+
+ context.shutdown();
+ }
+
+ private static class ZookeeperPolicyEnforcedContext {
+ private CamelContext controlledContext;
+ private ProducerTemplate template;
+ private MockEndpoint mock;
+ private String routename;
+
+ ZookeeperPolicyEnforcedContext(String name) throws Exception {
+ controlledContext = new DefaultCamelContext();
+ routename = name;
+ template = controlledContext.createProducerTemplate();
+ mock = controlledContext.getEndpoint("mock:controlled", MockEndpoint.class);
+ controlledContext.addRoutes(new FailoverRoute(name));
+ controlledContext.start();
+ }
+
+ public void sendMessageToEnforcedRoute(String message, int expected) throws InterruptedException {
+ mock.expectedMessageCount(expected);
+ try {
+ template.sendBody("vm:" + routename, ExchangePattern.InOut, message);
+ } catch (Exception e) {
+ if (expected > 0) {
+ LOG.error(e.getMessage(), e);
+ fail("Expected messages...");
+ }
+ }
+ mock.await(2, TimeUnit.SECONDS);
+ mock.assertIsSatisfied(2000);
+ }
+
+ public void shutdown() throws Exception {
+ LogFactory.getLog(getClass()).debug("stopping");
+ controlledContext.stop();
+ LogFactory.getLog(getClass()).debug("stopped");
+ }
+ }
+
+ private ZookeeperPolicyEnforcedContext createEnforcedContext(String name) throws Exception, InterruptedException {
+ ZookeeperPolicyEnforcedContext context = new ZookeeperPolicyEnforcedContext(name);
+ delay(1000);
+ return context;
+ }
+
+ public static class FailoverRoute extends RouteBuilder {
+
+ private String routename;
+
+ public FailoverRoute(String routename) {
+ // need names as if we use the same direct ep name in two contexts
+ // in the same vm shutting down one context shuts the endpoint for
+ // both.
+ this.routename = routename;
+ }
+
+ public void configure() throws Exception {
+ CuratorLeaderRoutePolicy policy = new CuratorLeaderRoutePolicy("zookeeper:localhost:" + getServerPort() + BASE_ZNODE + ZNODE);
+ from("vm:" + routename).routePolicy(policy).id(routename).to("mock:controlled");
+ }
+ }
+
+ ;
+}
http://git-wip-us.apache.org/repos/asf/camel/blob/34ea6c98/components/camel-zookeeper/src/test/resources/log4j2.properties
----------------------------------------------------------------------
diff --git a/components/camel-zookeeper/src/test/resources/log4j2.properties b/components/camel-zookeeper/src/test/resources/log4j2.properties
index c1843bb..81447cc 100644
--- a/components/camel-zookeeper/src/test/resources/log4j2.properties
+++ b/components/camel-zookeeper/src/test/resources/log4j2.properties
@@ -25,8 +25,16 @@ appender.out.name = out
appender.out.layout.type = PatternLayout
appender.out.layout.pattern = [%t] %c{1} %-5p %m%n
logger.zookeeper.name = org.apache.zookeeper
-logger.zookeeper.level = WARN
+logger.zookeeper.level = INFO
+logger.camel-zookeeper.name = org.apache.camel.component.zookeeper
+logger.camel-zookeeper.level = INFO
+logger.camel-support.name = org.apache.camel.support
+logger.camel-support.level = INFO
+
logger.springframework.name = org.springframework
logger.springframework.level = WARN
rootLogger.level = INFO
+# rootLogger.appenderRef.stdout.ref = out
rootLogger.appenderRef.file.ref = file
+
+
http://git-wip-us.apache.org/repos/asf/camel/blob/34ea6c98/parent/pom.xml
----------------------------------------------------------------------
diff --git a/parent/pom.xml b/parent/pom.xml
index bd3f1bf..34d9d8b 100644
--- a/parent/pom.xml
+++ b/parent/pom.xml
@@ -147,6 +147,7 @@
<consul-client-version>0.12.7</consul-client-version>
<consul-client-bundle-version>0.12.7_1</consul-client-bundle-version>
<cobertura-maven-plugin-version>2.7</cobertura-maven-plugin-version>
+ <curator-version>2.11.0</curator-version>
<cxf-version>3.1.7</cxf-version>
<cxf-version-range>[3.0,4.0)</cxf-version-range>
<cxf-xjc-plugin-version>3.0.5</cxf-xjc-plugin-version>