I am using the Apache ZooKeeper component (version 2.10.1) and I have two
routes defined: one using a zookeeper consumer endpoint and one using a
zookeeper producer endpoint. Each route works fine on its own, but I get an
exception when I have both together. The URI parameters on my consumer endpoint
seem to be affecting the behaviour of my producer endpoint.
The problem seems to be caused by this code in the ZooKeeperComponent class:
protected Endpoint createEndpoint(String uri, String remaining, Map
parameters) throws Exception {
if (getCamelContext() == null) {
throw new CamelException("No Camel context has been provided to
this zookeeper component");
}
ZooKeeperConfiguration config = getConfiguration();
extractConfigFromUri(uri, config);
setProperties(config, parameters);
return new ZooKeeperEndpoint(uri, this, config.copy());
}
This retrieves a configuration settings wrapper object that is stored in the
component, adds to it the settings from the endpoint being created, and then
stores a copy in the new endpoint. Surely this code should copy the component
configuration, and then change the *copy* and store it in the endpoint, as
follows:
// Below I have added ".copy()"
ZooKeeperConfiguration config = getConfiguration().copy();
extractConfigFromUri(uri, config);
setProperties(config, parameters);
// Below I have changed "config.copy()" to "config"
return new ZooKeeperEndpoint(uri, this, config);
This change fixes the problem for the sample code below:
CamelContext camel = new DefaultCamelContext();
camel.addRoutes(new RouteBuilder() {
@Override
public void configure() {
// Get message containing children of zookeeper node /agents whenever
// there is a change
from("zookeeper://127.0.0.1:2181/agents?listChildren=true&repeat=true")
.to("mock:children");
// Create a zookeeper sequence node /agents/agentX (where X is a
// zero-padded 10 digit integer)
from("direct:createSequenceNode")
.to("zookeeper://127.0.0.1:2181/agents/agent?create=true&createMode=EPHEMERAL_SEQUENTIAL")
.to("mock:createdNode");
}});
camel.start();
MockEndpoint mock = camel.getEndpoint("mock:createdNode",
MockEndpoint.class);
mock.expectedMessageCount(1);
mock.message(0).body().contains("/agents/agent0");
ProducerTemplate template = camel.createProducerTemplate();
template.sendBody("direct:createSequenceNode", ExchangePattern.InOut,
"irrelevant");
mock.assertIsSatisfied();
}
Here is the exception I get (if I don't change the ZooKeeperComponent code as
shown above). The zookeeper producer endpoint seems to be performing a
getChildren operation, even though the "listChildren" URI parameter appears
only on the consumer endpoint. As part of that operation it tries to read from
the the path /agents/agent, which doesn't exist because the node was created as
a sequence node and so had a zero-padded 10 digit number appended to its path.
Exception in thread "main" org.apache.camel.CamelExecutionException: Exception
occurred during execution on the exchange: Exchange[Message: [Body is null]]
at
org.apache.camel.util.ObjectHelper.wrapCamelExecutionException(ObjectHelper.java:1237)
at
org.apache.camel.util.ExchangeHelper.extractResultBody(ExchangeHelper.java:509)
at
org.apache.camel.impl.DefaultProducerTemplate.extractResultBody(DefaultProducerTemplate.java:442)
at
org.apache.camel.impl.DefaultProducerTemplate.sendBody(DefaultProducerTemplate.java:120)
at
org.apache.camel.impl.DefaultProducerTemplate.sendBody(DefaultProducerTemplate.java:136)
at bdi.BdiCamel.main(BdiCamel.java:107)
Caused by: org.apache.zookeeper.KeeperException$NoNodeException:
KeeperErrorCode = NoNode for /agents/agent
at org.apache.zookeeper.KeeperException.create(KeeperException.java:102)
at org.apache.zookeeper.KeeperException.create(KeeperException.java:42)
at org.apache.zookeeper.ZooKeeper.getChildren(ZooKeeper.java:1369)
at org.apache.zookeeper.ZooKeeper.getChildren(ZooKeeper.java:1404)
at
org.apache.camel.component.zookeeper.operations.GetChildrenOperation.getResult(GetChildrenOperation.java:40)
at
org.apache.camel.component.zookeeper.operations.ZooKeeperOperation.get(ZooKeeperOperation.java:71)
at
org.apache.camel.component.zookeeper.ZookeeperProducer.listChildren(ZookeeperProducer.java:101)
at
org.apache.camel.component.zookeeper.ZookeeperProducer.process(ZookeeperProducer.java:73)
...
Regards,
Stephen