You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by lb...@apache.org on 2016/06/07 14:32:05 UTC
[5/7] camel git commit: CAMEL-9988: Create an Etcd based ServiceCall
EIP
CAMEL-9988: Create an Etcd based ServiceCall EIP
Project: http://git-wip-us.apache.org/repos/asf/camel/repo
Commit: http://git-wip-us.apache.org/repos/asf/camel/commit/bafe28e4
Tree: http://git-wip-us.apache.org/repos/asf/camel/tree/bafe28e4
Diff: http://git-wip-us.apache.org/repos/asf/camel/diff/bafe28e4
Branch: refs/heads/master
Commit: bafe28e477d6bc3419fba3a5806d6cd09fe86e58
Parents: dbfcd60
Author: lburgazzoli <lb...@gmail.com>
Authored: Tue Jun 7 10:29:19 2016 +0200
Committer: lburgazzoli <lb...@gmail.com>
Committed: Tue Jun 7 16:30:43 2016 +0200
----------------------------------------------------------------------
.../remote/DefaultServiceCallProcessor.java | 12 +-
.../DefaultServiceCallProcessorFactory.java | 22 ++--
.../remote/EtcdConfigurationDefinition.java | 125 +++++++++++++++++++
.../model/remote/ServiceCallDefinition.java | 9 ++
.../org/apache/camel/model/remote/jaxb.index | 1 +
.../blueprint/CamelContextFactoryBean.java | 1 +
components/camel-etcd/pom.xml | 15 +++
.../component/etcd/AbstractEtcdEndpoint.java | 33 +----
.../camel/component/etcd/EtcdComponent.java | 2 +-
.../camel/component/etcd/EtcdConfiguration.java | 58 +++++++++
.../apache/camel/component/etcd/EtcdHelper.java | 9 ++
.../processor/remote/EtcdProcessorFactory.java | 24 ----
.../remote/EtcdServiceCallProcessor.java | 43 +++++++
.../remote/EtcdServiceCallProcessorFactory.java | 68 ++++++++++
.../processor/remote/EtcdServiceCallServer.java | 59 +++++++++
.../EtcdServiceCallServerListStrategies.java | 83 ++++++++++++
.../EtcdServiceCallServerListStrategy.java | 74 +++++++++++
.../apache/camel/model/ServiceCallDefinition | 18 +++
.../camel/component/etcd/EtcdKeysTest.java | 2 +-
.../camel/component/etcd/EtcdStatsTest.java | 2 +-
.../apache/camel/component/etcd/EtcdTest.java | 45 -------
.../camel/component/etcd/EtcdTestSupport.java | 45 +++++++
.../camel/component/etcd/EtcdWatchTest.java | 2 +-
.../remote/EtcdServiceCallRouteTest.java | 117 +++++++++++++++++
.../camel/spring/CamelContextFactoryBean.java | 5 +-
.../spring/handler/CamelNamespaceHandler.java | 14 +--
26 files changed, 757 insertions(+), 131 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/camel/blob/bafe28e4/camel-core/src/main/java/org/apache/camel/impl/remote/DefaultServiceCallProcessor.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/impl/remote/DefaultServiceCallProcessor.java b/camel-core/src/main/java/org/apache/camel/impl/remote/DefaultServiceCallProcessor.java
index 31b145c..9340406 100644
--- a/camel-core/src/main/java/org/apache/camel/impl/remote/DefaultServiceCallProcessor.java
+++ b/camel-core/src/main/java/org/apache/camel/impl/remote/DefaultServiceCallProcessor.java
@@ -234,12 +234,12 @@ public class DefaultServiceCallProcessor<S extends ServiceCallServer> extends Se
List<S> servers = serverListStrategy.getUpdatedListOfServers(serviceName);
if (servers == null || servers.isEmpty()) {
exchange.setException(new RejectedExecutionException("No active services with name " + name));
- }
-
- // let the client load balancer chose which server to use
- server = servers.size() > 1 ? loadBalancer.chooseServer(servers) : servers.get(0);
- if (server == null) {
- exchange.setException(new RejectedExecutionException("No active services with name " + name));
+ } else {
+ // let the client load balancer chose which server to use
+ server = servers.size() > 1 ? loadBalancer.chooseServer(servers) : servers.get(0);
+ if (server == null) {
+ exchange.setException(new RejectedExecutionException("No active services with name " + name));
+ }
}
} catch (Throwable e) {
exchange.setException(e);
http://git-wip-us.apache.org/repos/asf/camel/blob/bafe28e4/camel-core/src/main/java/org/apache/camel/impl/remote/DefaultServiceCallProcessorFactory.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/impl/remote/DefaultServiceCallProcessorFactory.java b/camel-core/src/main/java/org/apache/camel/impl/remote/DefaultServiceCallProcessorFactory.java
index 0cdc0f4..d74023e 100644
--- a/camel-core/src/main/java/org/apache/camel/impl/remote/DefaultServiceCallProcessorFactory.java
+++ b/camel-core/src/main/java/org/apache/camel/impl/remote/DefaultServiceCallProcessorFactory.java
@@ -84,16 +84,16 @@ public abstract class DefaultServiceCallProcessorFactory<C, S extends ServiceCal
throw new IllegalStateException("The ServiceCall: " + definition + " must be configured before it can be used.");
}
- // extract the properties from the configuration from the model
- Map<String, Object> parameters = new HashMap<>();
- if (configRef != null) {
- IntrospectionSupport.getProperties(configRef, parameters, null);
- }
- if (config != null) {
- IntrospectionSupport.getProperties(config, parameters, null);
- }
-
if (cfg != null) {
+ // extract the properties from the configuration from the model
+ Map<String, Object> parameters = new HashMap<>();
+ if (configRef != null) {
+ IntrospectionSupport.getProperties(configRef, parameters, null);
+ }
+ if (config != null) {
+ IntrospectionSupport.getProperties(config, parameters, null);
+ }
+
IntrospectionSupport.setProperties(cfg, parameters);
}
@@ -139,10 +139,10 @@ public abstract class DefaultServiceCallProcessorFactory<C, S extends ServiceCal
Map<String, String> properties = configureProperties(routeContext, config, configRef);
DefaultServiceCallProcessor processor = createProcessor(name, component, uri, mep, cfg, properties);
- if (sl != null && processor.getServerListStrategy() != null) {
+ if (sl != null && processor.getServerListStrategy() == null) {
processor.setServerListStrategy(sl);
}
- if (lb != null && processor.getLoadBalancer() != null) {
+ if (lb != null && processor.getLoadBalancer() == null) {
processor.setLoadBalancer(lb);
}
http://git-wip-us.apache.org/repos/asf/camel/blob/bafe28e4/camel-core/src/main/java/org/apache/camel/model/remote/EtcdConfigurationDefinition.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/model/remote/EtcdConfigurationDefinition.java b/camel-core/src/main/java/org/apache/camel/model/remote/EtcdConfigurationDefinition.java
new file mode 100644
index 0000000..1edd5f0
--- /dev/null
+++ b/camel-core/src/main/java/org/apache/camel/model/remote/EtcdConfigurationDefinition.java
@@ -0,0 +1,125 @@
+/**
+ * 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.model.remote;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlRootElement;
+
+import org.apache.camel.spi.Metadata;
+
+/**
+ * Etcd remote service call configuration
+ */
+@Metadata(label = "eip,routing,remote")
+@XmlRootElement(name = "etcdConfiguration")
+@XmlAccessorType(XmlAccessType.FIELD)
+public class EtcdConfigurationDefinition extends ServiceCallConfigurationDefinition {
+ @XmlAttribute
+ private String uris;
+ @XmlAttribute @Metadata(label = "security")
+ private String userName;
+ @XmlAttribute @Metadata(label = "security")
+ private String password;
+ @XmlAttribute
+ private Long timeout;
+ @XmlAttribute @Metadata(defaultValue = "/services/")
+ private String servicePath = "/services/";
+
+ public EtcdConfigurationDefinition() {
+ }
+
+ public EtcdConfigurationDefinition(ServiceCallDefinition parent) {
+ super(parent);
+ }
+
+ // -------------------------------------------------------------------------
+ // Getter/Setter
+ // -------------------------------------------------------------------------
+
+ public String getUris() {
+ return uris;
+ }
+
+ public void setUris(String uris) {
+ this.uris = uris;
+ }
+
+ public String getUserName() {
+ return userName;
+ }
+
+ public void setUserName(String userName) {
+ this.userName = userName;
+ }
+
+ public String getPassword() {
+ return password;
+ }
+
+ public void setPassword(String password) {
+ this.password = password;
+ }
+
+ public Long getTimeout() {
+ return timeout;
+ }
+
+ public void setTimeout(Long timeout) {
+ this.timeout = timeout;
+ }
+
+ public String getServicePath() {
+ return servicePath;
+ }
+
+ public void setServicePath(String servicePath) {
+ this.servicePath = servicePath;
+ }
+
+
+ // -------------------------------------------------------------------------
+ // Fluent API
+ // -------------------------------------------------------------------------
+
+ public EtcdConfigurationDefinition uris(String uris) {
+ setUris(uris);
+ return this;
+ }
+
+ public EtcdConfigurationDefinition userName(String userName) {
+ setUserName(userName);
+ return this;
+ }
+
+ public EtcdConfigurationDefinition password(String password) {
+ setPassword(password);
+ return this;
+ }
+
+ public EtcdConfigurationDefinition timeout(Long timeout) {
+ setTimeout(timeout);
+ return this;
+ }
+
+ public EtcdConfigurationDefinition servicePath(String servicePath) {
+ setServicePath(servicePath);
+ return this;
+ }
+}
http://git-wip-us.apache.org/repos/asf/camel/blob/bafe28e4/camel-core/src/main/java/org/apache/camel/model/remote/ServiceCallDefinition.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/model/remote/ServiceCallDefinition.java b/camel-core/src/main/java/org/apache/camel/model/remote/ServiceCallDefinition.java
index ed1c2aa..a778b96 100644
--- a/camel-core/src/main/java/org/apache/camel/model/remote/ServiceCallDefinition.java
+++ b/camel-core/src/main/java/org/apache/camel/model/remote/ServiceCallDefinition.java
@@ -135,6 +135,15 @@ public class ServiceCallDefinition extends NoOutputDefinition<ServiceCallDefinit
}
/**
+ * Configures the Service Call EIP using Etcd
+ * <p/>
+ * Use <tt>end</tt> when configuration is complete, to return back to the Service Call EIP.
+ */
+ public EtcdConfigurationDefinition etcdConfiguration() {
+ serviceCallConfiguration = new EtcdConfigurationDefinition(this);
+ return (EtcdConfigurationDefinition) serviceCallConfiguration;
+ }
+ /**
* Configures the ServiceCall using the given configuration
*/
public ServiceCallDefinition serviceCallConfiguration(ServiceCallConfigurationDefinition configuration) {
http://git-wip-us.apache.org/repos/asf/camel/blob/bafe28e4/camel-core/src/main/resources/org/apache/camel/model/remote/jaxb.index
----------------------------------------------------------------------
diff --git a/camel-core/src/main/resources/org/apache/camel/model/remote/jaxb.index b/camel-core/src/main/resources/org/apache/camel/model/remote/jaxb.index
index 6d7d250..8100bd3 100644
--- a/camel-core/src/main/resources/org/apache/camel/model/remote/jaxb.index
+++ b/camel-core/src/main/resources/org/apache/camel/model/remote/jaxb.index
@@ -15,6 +15,7 @@
## limitations under the License.
## ------------------------------------------------------------------------
ConsulConfigurationDefinition
+EtcdConfigurationDefinition
KubernetesConfigurationDefinition
RibbonConfigurationDefinition
ServiceCallDefinition
http://git-wip-us.apache.org/repos/asf/camel/blob/bafe28e4/components/camel-blueprint/src/main/java/org/apache/camel/blueprint/CamelContextFactoryBean.java
----------------------------------------------------------------------
diff --git a/components/camel-blueprint/src/main/java/org/apache/camel/blueprint/CamelContextFactoryBean.java b/components/camel-blueprint/src/main/java/org/apache/camel/blueprint/CamelContextFactoryBean.java
index 1ca4507..dda9a98 100644
--- a/components/camel-blueprint/src/main/java/org/apache/camel/blueprint/CamelContextFactoryBean.java
+++ b/components/camel-blueprint/src/main/java/org/apache/camel/blueprint/CamelContextFactoryBean.java
@@ -147,6 +147,7 @@ public class CamelContextFactoryBean extends AbstractCamelContextFactoryBean<Blu
@XmlElement(name = "kubernetesConfiguration", type = KubernetesConfigurationDefinition.class, required = false),
@XmlElement(name = "ribbonConfiguration", type = RibbonConfigurationDefinition.class, required = false),
@XmlElement(name = "consulConfiguration", type = RibbonConfigurationDefinition.class, required = false),
+ @XmlElement(name = "etcdConfiguration", type = RibbonConfigurationDefinition.class, required = false),
@XmlElement(name = "template", type = CamelProducerTemplateFactoryBean.class, required = false),
@XmlElement(name = "consumerTemplate", type = CamelConsumerTemplateFactoryBean.class, required = false),
@XmlElement(name = "proxy", type = CamelProxyFactoryBean.class, required = false),
http://git-wip-us.apache.org/repos/asf/camel/blob/bafe28e4/components/camel-etcd/pom.xml
----------------------------------------------------------------------
diff --git a/components/camel-etcd/pom.xml b/components/camel-etcd/pom.xml
index 1868850..4e307b9 100644
--- a/components/camel-etcd/pom.xml
+++ b/components/camel-etcd/pom.xml
@@ -83,6 +83,21 @@
<artifactId>camel-test</artifactId>
<scope>test</scope>
</dependency>
+ <dependency>
+ <groupId>org.apache.camel</groupId>
+ <artifactId>camel-test-spring</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.camel</groupId>
+ <artifactId>camel-http</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.camel</groupId>
+ <artifactId>camel-jetty</artifactId>
+ <scope>test</scope>
+ </dependency>
</dependencies>
http://git-wip-us.apache.org/repos/asf/camel/blob/bafe28e4/components/camel-etcd/src/main/java/org/apache/camel/component/etcd/AbstractEtcdEndpoint.java
----------------------------------------------------------------------
diff --git a/components/camel-etcd/src/main/java/org/apache/camel/component/etcd/AbstractEtcdEndpoint.java b/components/camel-etcd/src/main/java/org/apache/camel/component/etcd/AbstractEtcdEndpoint.java
index 6847d85..423d482 100644
--- a/components/camel-etcd/src/main/java/org/apache/camel/component/etcd/AbstractEtcdEndpoint.java
+++ b/components/camel-etcd/src/main/java/org/apache/camel/component/etcd/AbstractEtcdEndpoint.java
@@ -16,11 +16,7 @@
*/
package org.apache.camel.component.etcd;
-import java.net.URI;
-import javax.net.ssl.SSLContext;
-
import mousio.etcd4j.EtcdClient;
-import mousio.etcd4j.EtcdSecurityContext;
import org.apache.camel.impl.DefaultEndpoint;
import org.apache.camel.spi.Metadata;
import org.apache.camel.spi.UriEndpoint;
@@ -68,33 +64,6 @@ public abstract class AbstractEtcdEndpoint extends DefaultEndpoint {
}
public EtcdClient createClient() throws Exception {
- String[] uris;
- if (configuration.getUris() != null) {
- uris = configuration.getUris().split(",");
- } else {
- uris = EtcdConstants.ETCD_DEFAULT_URIS.split(",");
- }
-
- URI[] etcdUriList = new URI[uris.length];
-
- int i = 0;
- for (String uri : uris) {
- etcdUriList[i++] = URI.create(getCamelContext().resolvePropertyPlaceholders(uri));
- }
-
- return new EtcdClient(
- new EtcdSecurityContext(
- createSslContext(configuration),
- configuration.getUserName(),
- configuration.getPassword()),
- etcdUriList
- );
- }
-
- private SSLContext createSslContext(EtcdConfiguration configuration) throws Exception {
- if (configuration.getSslContextParameters() != null) {
- return configuration.getSslContextParameters().createSSLContext(getCamelContext());
- }
- return null;
+ return configuration.createClient();
}
}
http://git-wip-us.apache.org/repos/asf/camel/blob/bafe28e4/components/camel-etcd/src/main/java/org/apache/camel/component/etcd/EtcdComponent.java
----------------------------------------------------------------------
diff --git a/components/camel-etcd/src/main/java/org/apache/camel/component/etcd/EtcdComponent.java b/components/camel-etcd/src/main/java/org/apache/camel/component/etcd/EtcdComponent.java
index 3b81579..9c07b2a 100644
--- a/components/camel-etcd/src/main/java/org/apache/camel/component/etcd/EtcdComponent.java
+++ b/components/camel-etcd/src/main/java/org/apache/camel/component/etcd/EtcdComponent.java
@@ -49,7 +49,7 @@ public class EtcdComponent extends UriEndpointComponent {
}
EtcdNamespace namespace = getCamelContext().getTypeConverter().mandatoryConvertTo(EtcdNamespace.class, ns);
- EtcdConfiguration configuration = loadConfiguration(new EtcdConfiguration(), parameters);
+ EtcdConfiguration configuration = loadConfiguration(new EtcdConfiguration(getCamelContext()), parameters);
if (namespace != null) {
// path must start with leading slash
http://git-wip-us.apache.org/repos/asf/camel/blob/bafe28e4/components/camel-etcd/src/main/java/org/apache/camel/component/etcd/EtcdConfiguration.java
----------------------------------------------------------------------
diff --git a/components/camel-etcd/src/main/java/org/apache/camel/component/etcd/EtcdConfiguration.java b/components/camel-etcd/src/main/java/org/apache/camel/component/etcd/EtcdConfiguration.java
index 5edad92..2f80e8d 100644
--- a/components/camel-etcd/src/main/java/org/apache/camel/component/etcd/EtcdConfiguration.java
+++ b/components/camel-etcd/src/main/java/org/apache/camel/component/etcd/EtcdConfiguration.java
@@ -16,6 +16,11 @@
*/
package org.apache.camel.component.etcd;
+import java.net.URI;
+
+import mousio.etcd4j.EtcdClient;
+import mousio.etcd4j.EtcdSecurityContext;
+import org.apache.camel.CamelContext;
import org.apache.camel.spi.UriParam;
import org.apache.camel.spi.UriParams;
import org.apache.camel.util.jsse.SSLContextParameters;
@@ -41,6 +46,18 @@ public class EtcdConfiguration {
private Long timeout;
@UriParam(label = "consumer,advanced", defaultValue = "0")
private Long fromIndex = 0L;
+ @UriParam(defaultValue = "/services/")
+ private String servicePath = "/services/";
+
+ private final CamelContext camelContext;
+
+ public EtcdConfiguration(CamelContext camelContext) {
+ this.camelContext = camelContext;
+ }
+
+ public CamelContext getCamelContext() {
+ return this.camelContext;
+ }
public String getUris() {
return uris;
@@ -123,6 +140,10 @@ public class EtcdConfiguration {
return timeout;
}
+ public boolean hasTimeout() {
+ return timeout != null && timeout > 0;
+ }
+
/**
* To set the maximum time an action could take to complete.
*/
@@ -140,4 +161,41 @@ public class EtcdConfiguration {
public void setFromIndex(Long fromIndex) {
this.fromIndex = fromIndex;
}
+
+ public String getServicePath() {
+ return servicePath;
+ }
+
+ /**
+ * The path to look for for service discovery
+ */
+ public void setServicePath(String servicePath) {
+ this.servicePath = servicePath;
+ }
+
+ public EtcdClient createClient() throws Exception {
+ String[] uris;
+ if (getUris() != null) {
+ uris = getUris().split(",");
+ } else {
+ uris = EtcdConstants.ETCD_DEFAULT_URIS.split(",");
+ }
+
+ URI[] etcdUriList = new URI[uris.length];
+
+ int i = 0;
+ for (String uri : uris) {
+ etcdUriList[i++] = URI.create(camelContext.resolvePropertyPlaceholders(uri));
+ }
+
+ return new EtcdClient(
+ new EtcdSecurityContext(
+ sslContextParameters != null
+ ? sslContextParameters.createSSLContext(camelContext)
+ : null,
+ userName,
+ password),
+ etcdUriList
+ );
+ }
}
http://git-wip-us.apache.org/repos/asf/camel/blob/bafe28e4/components/camel-etcd/src/main/java/org/apache/camel/component/etcd/EtcdHelper.java
----------------------------------------------------------------------
diff --git a/components/camel-etcd/src/main/java/org/apache/camel/component/etcd/EtcdHelper.java b/components/camel-etcd/src/main/java/org/apache/camel/component/etcd/EtcdHelper.java
index c86e1a0..b222037 100644
--- a/components/camel-etcd/src/main/java/org/apache/camel/component/etcd/EtcdHelper.java
+++ b/components/camel-etcd/src/main/java/org/apache/camel/component/etcd/EtcdHelper.java
@@ -16,6 +16,9 @@
*/
package org.apache.camel.component.etcd;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.databind.DeserializationFeature;
+import com.fasterxml.jackson.databind.ObjectMapper;
import mousio.etcd4j.responses.EtcdErrorCode;
import mousio.etcd4j.responses.EtcdException;
@@ -32,4 +35,10 @@ public final class EtcdHelper {
return false;
}
+
+ public static ObjectMapper createObjectMapper() {
+ return new ObjectMapper()
+ .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
+ .setSerializationInclusion(JsonInclude.Include.NON_NULL);
+ }
}
http://git-wip-us.apache.org/repos/asf/camel/blob/bafe28e4/components/camel-etcd/src/main/java/org/apache/camel/component/etcd/processor/remote/EtcdProcessorFactory.java
----------------------------------------------------------------------
diff --git a/components/camel-etcd/src/main/java/org/apache/camel/component/etcd/processor/remote/EtcdProcessorFactory.java b/components/camel-etcd/src/main/java/org/apache/camel/component/etcd/processor/remote/EtcdProcessorFactory.java
deleted file mode 100644
index 0e60a77..0000000
--- a/components/camel-etcd/src/main/java/org/apache/camel/component/etcd/processor/remote/EtcdProcessorFactory.java
+++ /dev/null
@@ -1,24 +0,0 @@
-/**
- * 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.etcd.processor.remote;
-
-/**
- * @author lburgazzoli
- */
-public class EtcdProcessorFactory {
-}
http://git-wip-us.apache.org/repos/asf/camel/blob/bafe28e4/components/camel-etcd/src/main/java/org/apache/camel/component/etcd/processor/remote/EtcdServiceCallProcessor.java
----------------------------------------------------------------------
diff --git a/components/camel-etcd/src/main/java/org/apache/camel/component/etcd/processor/remote/EtcdServiceCallProcessor.java b/components/camel-etcd/src/main/java/org/apache/camel/component/etcd/processor/remote/EtcdServiceCallProcessor.java
new file mode 100644
index 0000000..3251ae5
--- /dev/null
+++ b/components/camel-etcd/src/main/java/org/apache/camel/component/etcd/processor/remote/EtcdServiceCallProcessor.java
@@ -0,0 +1,43 @@
+/**
+ * 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.etcd.processor.remote;
+
+import org.apache.camel.ExchangePattern;
+import org.apache.camel.component.etcd.EtcdConfiguration;
+import org.apache.camel.impl.remote.DefaultServiceCallProcessor;
+import org.apache.camel.spi.ProcessorFactory;
+import org.apache.camel.spi.ServiceCallServer;
+import org.apache.camel.spi.ServiceCallServerListStrategy;
+
+/**
+ * {@link ProcessorFactory} that creates the Etcd implementation of the ServiceCall EIP.
+ */
+public class EtcdServiceCallProcessor extends DefaultServiceCallProcessor<ServiceCallServer> {
+ public EtcdServiceCallProcessor(String name, String scheme, String uri, ExchangePattern exchangePattern, EtcdConfiguration conf) {
+ super(name, scheme, uri, exchangePattern);
+ }
+
+ @Override
+ public void setServerListStrategy(ServiceCallServerListStrategy<ServiceCallServer> serverListStrategy) {
+ if (!(serverListStrategy instanceof EtcdServiceCallServerListStrategy)) {
+ throw new IllegalArgumentException("ServerListStrategy is not an instance of EtcdServiceCallServerListStrategy");
+ }
+
+ super.setServerListStrategy(serverListStrategy);
+ }
+}
http://git-wip-us.apache.org/repos/asf/camel/blob/bafe28e4/components/camel-etcd/src/main/java/org/apache/camel/component/etcd/processor/remote/EtcdServiceCallProcessorFactory.java
----------------------------------------------------------------------
diff --git a/components/camel-etcd/src/main/java/org/apache/camel/component/etcd/processor/remote/EtcdServiceCallProcessorFactory.java b/components/camel-etcd/src/main/java/org/apache/camel/component/etcd/processor/remote/EtcdServiceCallProcessorFactory.java
new file mode 100644
index 0000000..9f25738
--- /dev/null
+++ b/components/camel-etcd/src/main/java/org/apache/camel/component/etcd/processor/remote/EtcdServiceCallProcessorFactory.java
@@ -0,0 +1,68 @@
+/**
+ * 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.etcd.processor.remote;
+
+import java.util.Map;
+import java.util.Optional;
+
+import org.apache.camel.ExchangePattern;
+import org.apache.camel.component.etcd.EtcdConfiguration;
+import org.apache.camel.impl.remote.DefaultServiceCallProcessor;
+import org.apache.camel.impl.remote.DefaultServiceCallProcessorFactory;
+import org.apache.camel.spi.ProcessorFactory;
+import org.apache.camel.spi.RouteContext;
+import org.apache.camel.spi.ServiceCallServer;
+import org.apache.camel.spi.ServiceCallServerListStrategy;
+import org.apache.camel.util.ObjectHelper;
+
+/**
+ * {@link ProcessorFactory} that creates the Etcd implementation of the ServiceCall EIP.
+ */
+public class EtcdServiceCallProcessorFactory extends DefaultServiceCallProcessorFactory<EtcdConfiguration, ServiceCallServer> {
+ @Override
+ protected EtcdConfiguration createConfiguration(RouteContext routeContext) throws Exception {
+ return new EtcdConfiguration(routeContext.getCamelContext());
+ }
+
+ @Override
+ protected DefaultServiceCallProcessor createProcessor(
+ String name,
+ String component,
+ String uri,
+ ExchangePattern mep,
+ EtcdConfiguration conf,
+ Map<String, String> properties) throws Exception {
+
+ return new EtcdServiceCallProcessor(name, component, uri, mep, conf);
+ }
+
+ @Override
+ protected Optional<ServiceCallServerListStrategy> builtInServerListStrategy(EtcdConfiguration conf, String name) throws Exception {
+ ServiceCallServerListStrategy strategy = null;
+ if (ObjectHelper.equal("ondemand", name, true)) {
+ strategy = new EtcdServiceCallServerListStrategies.OnDemand(conf);
+ }
+
+ return Optional.ofNullable(strategy);
+ }
+
+ @Override
+ protected ServiceCallServerListStrategy<ServiceCallServer> createDefaultServerListStrategy(EtcdConfiguration conf) throws Exception {
+ return new EtcdServiceCallServerListStrategies.OnDemand(conf);
+ }
+}
http://git-wip-us.apache.org/repos/asf/camel/blob/bafe28e4/components/camel-etcd/src/main/java/org/apache/camel/component/etcd/processor/remote/EtcdServiceCallServer.java
----------------------------------------------------------------------
diff --git a/components/camel-etcd/src/main/java/org/apache/camel/component/etcd/processor/remote/EtcdServiceCallServer.java b/components/camel-etcd/src/main/java/org/apache/camel/component/etcd/processor/remote/EtcdServiceCallServer.java
new file mode 100644
index 0000000..d5c25d9
--- /dev/null
+++ b/components/camel-etcd/src/main/java/org/apache/camel/component/etcd/processor/remote/EtcdServiceCallServer.java
@@ -0,0 +1,59 @@
+/**
+ * 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.etcd.processor.remote;
+
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Map;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import org.apache.camel.impl.remote.DefaultServiceCallServer;
+
+public class EtcdServiceCallServer extends DefaultServiceCallServer {
+ public static final Comparator<EtcdServiceCallServer> COMPARATOR = comparator();
+
+ private final String name;
+ private final Map<String, String> tags;
+
+ @JsonCreator
+ public EtcdServiceCallServer(
+ @JsonProperty("name") final String name,
+ @JsonProperty("address") final String address,
+ @JsonProperty("port") final Integer port,
+ @JsonProperty("tags") final Map<String, String> tags) {
+ super(address, port);
+
+ this.name = name;
+ this.tags = Collections.unmodifiableMap(tags != null ? tags : Collections.EMPTY_MAP);
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public Map<String, String> getTags() {
+ return tags;
+ }
+
+ public static Comparator<EtcdServiceCallServer> comparator() {
+ Comparator<EtcdServiceCallServer> byAddress = (e1, e2) -> e2.getIp().compareTo(e1.getIp());
+ Comparator<EtcdServiceCallServer> byPort = (e1, e2) -> Integer.compare(e2.getPort(), e1.getPort());
+
+ return byAddress.thenComparing(byPort);
+ }
+}
http://git-wip-us.apache.org/repos/asf/camel/blob/bafe28e4/components/camel-etcd/src/main/java/org/apache/camel/component/etcd/processor/remote/EtcdServiceCallServerListStrategies.java
----------------------------------------------------------------------
diff --git a/components/camel-etcd/src/main/java/org/apache/camel/component/etcd/processor/remote/EtcdServiceCallServerListStrategies.java b/components/camel-etcd/src/main/java/org/apache/camel/component/etcd/processor/remote/EtcdServiceCallServerListStrategies.java
new file mode 100644
index 0000000..e4b4a8a
--- /dev/null
+++ b/components/camel-etcd/src/main/java/org/apache/camel/component/etcd/processor/remote/EtcdServiceCallServerListStrategies.java
@@ -0,0 +1,83 @@
+/**
+ * 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.etcd.processor.remote;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Objects;
+import java.util.concurrent.TimeUnit;
+import java.util.stream.Collectors;
+
+import mousio.etcd4j.requests.EtcdKeyGetRequest;
+import mousio.etcd4j.responses.EtcdKeysResponse;
+import org.apache.camel.RuntimeCamelException;
+import org.apache.camel.component.etcd.EtcdConfiguration;
+import org.apache.camel.spi.ServiceCallServer;
+import org.apache.camel.util.ObjectHelper;
+
+public final class EtcdServiceCallServerListStrategies {
+ private EtcdServiceCallServerListStrategies() {
+ }
+
+ public static final class OnDemand extends EtcdServiceCallServerListStrategy {
+ public OnDemand(EtcdConfiguration configuration) throws Exception {
+ super(configuration);
+ }
+
+ @Override
+ public List<ServiceCallServer> getUpdatedListOfServers(String name) {
+ List<ServiceCallServer> servers = Collections.emptyList();
+ try {
+ final EtcdConfiguration conf = getConfiguration();
+ final EtcdKeyGetRequest request = getClient().get(conf.getServicePath()).recursive();
+ if (conf.hasTimeout()) {
+ request.timeout(conf.getTimeout(), TimeUnit.SECONDS);
+ }
+
+ final EtcdKeysResponse response = request.send().get();
+
+ if (Objects.nonNull(response.node) && !response.node.nodes.isEmpty()) {
+ servers = response.node.nodes.stream()
+ .map(node -> node.value)
+ .filter(ObjectHelper::isNotEmpty)
+ .map(this::nodeFromString)
+ .filter(Objects::nonNull)
+ .filter(s -> name.equalsIgnoreCase(s.getName()))
+ .sorted(EtcdServiceCallServer.COMPARATOR)
+ .collect(Collectors.toList());
+ }
+ } catch (Exception e) {
+ throw new RuntimeCamelException(e);
+ }
+
+ return servers;
+ }
+
+ @Override
+ public String toString() {
+ return "OnDemand";
+ }
+ }
+
+ // *************************************************************************
+ // Helpers
+ // *************************************************************************
+
+ public static EtcdServiceCallServerListStrategy onDemand(EtcdConfiguration configuration) throws Exception {
+ return new OnDemand(configuration);
+ }
+}
http://git-wip-us.apache.org/repos/asf/camel/blob/bafe28e4/components/camel-etcd/src/main/java/org/apache/camel/component/etcd/processor/remote/EtcdServiceCallServerListStrategy.java
----------------------------------------------------------------------
diff --git a/components/camel-etcd/src/main/java/org/apache/camel/component/etcd/processor/remote/EtcdServiceCallServerListStrategy.java b/components/camel-etcd/src/main/java/org/apache/camel/component/etcd/processor/remote/EtcdServiceCallServerListStrategy.java
new file mode 100644
index 0000000..38f6139
--- /dev/null
+++ b/components/camel-etcd/src/main/java/org/apache/camel/component/etcd/processor/remote/EtcdServiceCallServerListStrategy.java
@@ -0,0 +1,74 @@
+/**
+ * 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.etcd.processor.remote;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import mousio.etcd4j.EtcdClient;
+import org.apache.camel.component.etcd.EtcdConfiguration;
+import org.apache.camel.component.etcd.EtcdHelper;
+import org.apache.camel.impl.remote.DefaultServiceCallServerListStrategy;
+import org.apache.camel.spi.ServiceCallServer;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class EtcdServiceCallServerListStrategy extends DefaultServiceCallServerListStrategy<ServiceCallServer> {
+ private static final Logger LOGGER = LoggerFactory.getLogger(EtcdServiceCallServerListStrategy.class);
+ private static final ObjectMapper MAPPER = EtcdHelper.createObjectMapper();
+
+ private final EtcdConfiguration configuration;
+ private EtcdClient client;
+
+ public EtcdServiceCallServerListStrategy(EtcdConfiguration configuration) {
+ this.configuration = configuration;
+ this.client = null;
+ }
+
+ @Override
+ protected void doStart() throws Exception {
+ if (client == null) {
+ client = configuration.createClient();
+ }
+ }
+
+ @Override
+ protected void doStop() throws Exception {
+ if (client != null) {
+ client.close();
+ client = null;
+ }
+ }
+
+ protected EtcdConfiguration getConfiguration() {
+ return this.configuration;
+ }
+
+ protected EtcdClient getClient() {
+ return this.client;
+ }
+
+ protected EtcdServiceCallServer nodeFromString(String value) {
+ EtcdServiceCallServer server = null;
+
+ try {
+ server = MAPPER.readValue(value, EtcdServiceCallServer.class);
+ } catch (Exception e) {
+ LOGGER.warn("", e);
+ }
+
+ return server;
+ }
+}
http://git-wip-us.apache.org/repos/asf/camel/blob/bafe28e4/components/camel-etcd/src/main/resources/META-INF/services/org/apache/camel/model/ServiceCallDefinition
----------------------------------------------------------------------
diff --git a/components/camel-etcd/src/main/resources/META-INF/services/org/apache/camel/model/ServiceCallDefinition b/components/camel-etcd/src/main/resources/META-INF/services/org/apache/camel/model/ServiceCallDefinition
new file mode 100644
index 0000000..0cd6c42
--- /dev/null
+++ b/components/camel-etcd/src/main/resources/META-INF/services/org/apache/camel/model/ServiceCallDefinition
@@ -0,0 +1,18 @@
+#
+# 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.
+#
+
+class=org.apache.camel.component.etcd.processor.remote.EtcdServiceCallProcessorFactory
http://git-wip-us.apache.org/repos/asf/camel/blob/bafe28e4/components/camel-etcd/src/test/java/org/apache/camel/component/etcd/EtcdKeysTest.java
----------------------------------------------------------------------
diff --git a/components/camel-etcd/src/test/java/org/apache/camel/component/etcd/EtcdKeysTest.java b/components/camel-etcd/src/test/java/org/apache/camel/component/etcd/EtcdKeysTest.java
index cf16017..c2bc507 100644
--- a/components/camel-etcd/src/test/java/org/apache/camel/component/etcd/EtcdKeysTest.java
+++ b/components/camel-etcd/src/test/java/org/apache/camel/component/etcd/EtcdKeysTest.java
@@ -30,7 +30,7 @@ import org.apache.camel.component.mock.MockEndpoint;
import org.junit.Test;
//@Ignore("Etcd must be started manually")
-public class EtcdKeysTest extends EtcdTest {
+public class EtcdKeysTest extends EtcdTestSupport {
@Test(expected = EtcdException.class)
public void testKeys() throws Exception {
http://git-wip-us.apache.org/repos/asf/camel/blob/bafe28e4/components/camel-etcd/src/test/java/org/apache/camel/component/etcd/EtcdStatsTest.java
----------------------------------------------------------------------
diff --git a/components/camel-etcd/src/test/java/org/apache/camel/component/etcd/EtcdStatsTest.java b/components/camel-etcd/src/test/java/org/apache/camel/component/etcd/EtcdStatsTest.java
index aba6045..b3eeb13 100644
--- a/components/camel-etcd/src/test/java/org/apache/camel/component/etcd/EtcdStatsTest.java
+++ b/components/camel-etcd/src/test/java/org/apache/camel/component/etcd/EtcdStatsTest.java
@@ -26,7 +26,7 @@ import org.apache.camel.component.mock.MockEndpoint;
import org.junit.Test;
//@Ignore("Etcd must be started manually")
-public class EtcdStatsTest extends EtcdTest {
+public class EtcdStatsTest extends EtcdTestSupport {
@Test
public void testStats() throws Exception {
http://git-wip-us.apache.org/repos/asf/camel/blob/bafe28e4/components/camel-etcd/src/test/java/org/apache/camel/component/etcd/EtcdTest.java
----------------------------------------------------------------------
diff --git a/components/camel-etcd/src/test/java/org/apache/camel/component/etcd/EtcdTest.java b/components/camel-etcd/src/test/java/org/apache/camel/component/etcd/EtcdTest.java
deleted file mode 100644
index a8100e6..0000000
--- a/components/camel-etcd/src/test/java/org/apache/camel/component/etcd/EtcdTest.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/**
- * 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.etcd;
-
-import java.net.URI;
-
-import mousio.etcd4j.EtcdClient;
-import mousio.etcd4j.responses.EtcdKeysResponse;
-import org.apache.camel.Exchange;
-import org.apache.camel.Processor;
-import org.apache.camel.test.junit4.CamelTestSupport;
-
-public class EtcdTest extends CamelTestSupport {
- protected static final Processor NODE_TO_VALUE_IN = new Processor() {
- @Override
- public void process(Exchange exchange) throws Exception {
- EtcdKeysResponse response = exchange.getIn().getBody(EtcdKeysResponse.class);
- if (response != null) {
- exchange.getIn().setBody(response.node.key + "=" + response.node.value);
- }
- }
- };
-
- public boolean isCreateCamelContextPerClass() {
- return false;
- }
-
- protected EtcdClient getClient() {
- return new EtcdClient(URI.create("http://localhost:4001"));
- }
-}
http://git-wip-us.apache.org/repos/asf/camel/blob/bafe28e4/components/camel-etcd/src/test/java/org/apache/camel/component/etcd/EtcdTestSupport.java
----------------------------------------------------------------------
diff --git a/components/camel-etcd/src/test/java/org/apache/camel/component/etcd/EtcdTestSupport.java b/components/camel-etcd/src/test/java/org/apache/camel/component/etcd/EtcdTestSupport.java
new file mode 100644
index 0000000..e66466d
--- /dev/null
+++ b/components/camel-etcd/src/test/java/org/apache/camel/component/etcd/EtcdTestSupport.java
@@ -0,0 +1,45 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.etcd;
+
+import java.net.URI;
+
+import mousio.etcd4j.EtcdClient;
+import mousio.etcd4j.responses.EtcdKeysResponse;
+import org.apache.camel.Exchange;
+import org.apache.camel.Processor;
+import org.apache.camel.test.junit4.CamelTestSupport;
+
+public class EtcdTestSupport extends CamelTestSupport {
+ protected static final Processor NODE_TO_VALUE_IN = new Processor() {
+ @Override
+ public void process(Exchange exchange) throws Exception {
+ EtcdKeysResponse response = exchange.getIn().getBody(EtcdKeysResponse.class);
+ if (response != null) {
+ exchange.getIn().setBody(response.node.key + "=" + response.node.value);
+ }
+ }
+ };
+
+ public boolean isCreateCamelContextPerClass() {
+ return false;
+ }
+
+ protected EtcdClient getClient() {
+ return new EtcdClient(URI.create("http://localhost:2379"));
+ }
+}
http://git-wip-us.apache.org/repos/asf/camel/blob/bafe28e4/components/camel-etcd/src/test/java/org/apache/camel/component/etcd/EtcdWatchTest.java
----------------------------------------------------------------------
diff --git a/components/camel-etcd/src/test/java/org/apache/camel/component/etcd/EtcdWatchTest.java b/components/camel-etcd/src/test/java/org/apache/camel/component/etcd/EtcdWatchTest.java
index c511325..39aca62 100644
--- a/components/camel-etcd/src/test/java/org/apache/camel/component/etcd/EtcdWatchTest.java
+++ b/components/camel-etcd/src/test/java/org/apache/camel/component/etcd/EtcdWatchTest.java
@@ -24,7 +24,7 @@ import org.apache.camel.component.mock.MockEndpoint;
import org.junit.Test;
//@Ignore("Etcd must be started manually")
-public class EtcdWatchTest extends EtcdTest {
+public class EtcdWatchTest extends EtcdTestSupport {
@Test
public void testWatchWithPath() throws Exception {
http://git-wip-us.apache.org/repos/asf/camel/blob/bafe28e4/components/camel-etcd/src/test/java/org/apache/camel/component/etcd/processor/remote/EtcdServiceCallRouteTest.java
----------------------------------------------------------------------
diff --git a/components/camel-etcd/src/test/java/org/apache/camel/component/etcd/processor/remote/EtcdServiceCallRouteTest.java b/components/camel-etcd/src/test/java/org/apache/camel/component/etcd/processor/remote/EtcdServiceCallRouteTest.java
new file mode 100644
index 0000000..a20bd02
--- /dev/null
+++ b/components/camel-etcd/src/test/java/org/apache/camel/component/etcd/processor/remote/EtcdServiceCallRouteTest.java
@@ -0,0 +1,117 @@
+/**
+ * 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.etcd.processor.remote;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import mousio.etcd4j.EtcdClient;
+import org.apache.camel.RoutesBuilder;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.etcd.EtcdHelper;
+import org.apache.camel.component.etcd.EtcdTestSupport;
+import org.junit.Ignore;
+import org.junit.Test;
+
+@Ignore
+public class EtcdServiceCallRouteTest extends EtcdTestSupport {
+ private static final ObjectMapper MAPPER = EtcdHelper.createObjectMapper();
+ private static final String SERVICE_NAME = "http-service";
+ private static final int SERVICE_COUNT = 5;
+ private static final int SERVICE_PORT_BASE = 8080;
+
+ private EtcdClient client;
+ private List<Map<String, Object>> servers;
+ private List<String> expectedBodies;
+
+ // *************************************************************************
+ // Setup / tear down
+ // *************************************************************************
+
+ @Override
+ protected void doPreSetup() throws Exception {
+ client = getClient();
+
+ servers = new ArrayList<>(SERVICE_COUNT);
+ expectedBodies = new ArrayList<>(SERVICE_COUNT);
+
+ for (int i = 0; i < SERVICE_COUNT; i++) {
+ Map<String, Object> server = new HashMap<>();
+ server.put("name", SERVICE_NAME);
+ server.put("address", "127.0.0.1");
+ server.put("port", SERVICE_PORT_BASE + i);
+
+ client.put("/services/" + "service-" + i, MAPPER.writeValueAsString(server)).send().get();
+
+ servers.add(Collections.unmodifiableMap(server));
+ expectedBodies.add("ping on " + (SERVICE_PORT_BASE + i));
+ }
+ }
+
+ @Override
+ public void tearDown() throws Exception {
+ super.tearDown();
+ client.deleteDir("/services/").recursive().send().get();
+ }
+
+ // *************************************************************************
+ // Test
+ // *************************************************************************
+
+ @Test
+ public void testServiceCall() throws Exception {
+ getMockEndpoint("mock:result").expectedMessageCount(SERVICE_COUNT);
+ getMockEndpoint("mock:result").expectedBodiesReceivedInAnyOrder(expectedBodies);
+
+ servers.forEach(s -> template.sendBody("direct:start", "ping"));
+
+ assertMockEndpointsSatisfied();
+ }
+
+ // *************************************************************************
+ // Route
+ // *************************************************************************
+
+ @Override
+ protected RoutesBuilder createRouteBuilder() throws Exception {
+ return new RouteBuilder() {
+ @Override
+ public void configure() throws Exception {
+ from("direct:start")
+ .serviceCall()
+ .name(SERVICE_NAME)
+ .etcdConfiguration()
+ .component("http")
+ .loadBalancer("roundrobin")
+ .serverListStrategy("ondemand")
+ .end()
+ .to("log:org.apache.camel.component.etcd.processor.service?level=INFO&showAll=true&multiline=true")
+ .to("mock:result");
+
+ servers.forEach(s ->
+ fromF("jetty:http://%s:%d", s.get("address"), s.get("port"))
+ .transform().simple("${in.body} on " + s.get("port"))
+ );
+ }
+ };
+ }
+}
http://git-wip-us.apache.org/repos/asf/camel/blob/bafe28e4/components/camel-spring/src/main/java/org/apache/camel/spring/CamelContextFactoryBean.java
----------------------------------------------------------------------
diff --git a/components/camel-spring/src/main/java/org/apache/camel/spring/CamelContextFactoryBean.java b/components/camel-spring/src/main/java/org/apache/camel/spring/CamelContextFactoryBean.java
index 9f48921..7527881 100644
--- a/components/camel-spring/src/main/java/org/apache/camel/spring/CamelContextFactoryBean.java
+++ b/components/camel-spring/src/main/java/org/apache/camel/spring/CamelContextFactoryBean.java
@@ -19,7 +19,6 @@ package org.apache.camel.spring;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
-
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
@@ -58,6 +57,7 @@ import org.apache.camel.model.RouteDefinition;
import org.apache.camel.model.ThreadPoolProfileDefinition;
import org.apache.camel.model.dataformat.DataFormatsDefinition;
import org.apache.camel.model.remote.ConsulConfigurationDefinition;
+import org.apache.camel.model.remote.EtcdConfigurationDefinition;
import org.apache.camel.model.remote.KubernetesConfigurationDefinition;
import org.apache.camel.model.remote.RibbonConfigurationDefinition;
import org.apache.camel.model.rest.RestConfigurationDefinition;
@@ -155,7 +155,8 @@ public class CamelContextFactoryBean extends AbstractCamelContextFactoryBean<Spr
private CamelJMXAgentDefinition camelJMXAgent;
@XmlElements({
@XmlElement(name = "hystrixConfiguration", type = HystrixConfigurationDefinition.class, required = false),
- @XmlElement(name = "consulConfiguration", type = KubernetesConfigurationDefinition.class, required = false),
+ @XmlElement(name = "consulConfiguration", type = ConsulConfigurationDefinition.class, required = false),
+ @XmlElement(name = "etcdConfiguration", type = EtcdConfigurationDefinition.class, required = false),
@XmlElement(name = "kubernetesConfiguration", type = KubernetesConfigurationDefinition.class, required = false),
@XmlElement(name = "ribbonConfiguration", type = RibbonConfigurationDefinition.class, required = false),
@XmlElement(name = "template", type = CamelProducerTemplateFactoryBean.class, required = false),
http://git-wip-us.apache.org/repos/asf/camel/blob/bafe28e4/components/camel-spring/src/main/java/org/apache/camel/spring/handler/CamelNamespaceHandler.java
----------------------------------------------------------------------
diff --git a/components/camel-spring/src/main/java/org/apache/camel/spring/handler/CamelNamespaceHandler.java b/components/camel-spring/src/main/java/org/apache/camel/spring/handler/CamelNamespaceHandler.java
index 7470126..eae9f61 100644
--- a/components/camel-spring/src/main/java/org/apache/camel/spring/handler/CamelNamespaceHandler.java
+++ b/components/camel-spring/src/main/java/org/apache/camel/spring/handler/CamelNamespaceHandler.java
@@ -21,17 +21,10 @@ import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
-
import javax.xml.bind.Binder;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
-import org.w3c.dom.Document;
-import org.w3c.dom.Element;
-import org.w3c.dom.NamedNodeMap;
-import org.w3c.dom.Node;
-import org.w3c.dom.NodeList;
-
import org.apache.camel.builder.xml.Namespaces;
import org.apache.camel.core.xml.CamelJMXAgentDefinition;
import org.apache.camel.core.xml.CamelPropertyPlaceholderDefinition;
@@ -41,6 +34,7 @@ import org.apache.camel.model.FromDefinition;
import org.apache.camel.model.HystrixConfigurationDefinition;
import org.apache.camel.model.SendDefinition;
import org.apache.camel.model.remote.ConsulConfigurationDefinition;
+import org.apache.camel.model.remote.EtcdConfigurationDefinition;
import org.apache.camel.model.remote.KubernetesConfigurationDefinition;
import org.apache.camel.model.remote.RibbonConfigurationDefinition;
import org.apache.camel.spi.CamelContextNameStrategy;
@@ -71,6 +65,11 @@ import org.springframework.beans.factory.parsing.BeanComponentDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.xml.NamespaceHandlerSupport;
import org.springframework.beans.factory.xml.ParserContext;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
/**
* Camel namespace for the spring XML configuration file.
@@ -148,6 +147,7 @@ public class CamelNamespaceHandler extends NamespaceHandlerSupport {
addBeanDefinitionParser("propertyPlaceholder", CamelPropertyPlaceholderDefinition.class, false, false);
addBeanDefinitionParser("hystrixConfiguration", HystrixConfigurationDefinition.class, false, false);
addBeanDefinitionParser("consulConfiguration", ConsulConfigurationDefinition.class, false, false);
+ addBeanDefinitionParser("etcdConfiguration", EtcdConfigurationDefinition.class, false, false);
addBeanDefinitionParser("kubernetesConfiguration", KubernetesConfigurationDefinition.class, false, false);
addBeanDefinitionParser("ribbonConfiguration", RibbonConfigurationDefinition.class, false, false);