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 2017/01/11 12:04:12 UTC

[01/10] camel git commit: CAMEL-10638: Refactor ServiceCall EIP

Repository: camel
Updated Branches:
  refs/heads/master c92845358 -> a811f4004


http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/components/camel-spring-cloud/src/test/java/org/apache/camel/spring/cloud/CamelCloudServiceCallConfigurationTest.java
----------------------------------------------------------------------
diff --git a/components/camel-spring-cloud/src/test/java/org/apache/camel/spring/cloud/CamelCloudServiceCallConfigurationTest.java b/components/camel-spring-cloud/src/test/java/org/apache/camel/spring/cloud/CamelCloudServiceCallConfigurationTest.java
new file mode 100644
index 0000000..cb992a4
--- /dev/null
+++ b/components/camel-spring-cloud/src/test/java/org/apache/camel/spring/cloud/CamelCloudServiceCallConfigurationTest.java
@@ -0,0 +1,76 @@
+/**
+ * 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.spring.cloud;
+
+import org.apache.camel.cloud.LoadBalancer;
+import org.apache.camel.cloud.ServiceChooser;
+import org.apache.camel.cloud.ServiceDiscovery;
+import org.apache.camel.cloud.ServiceFilter;
+import org.apache.camel.spring.boot.CamelAutoConfiguration;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.context.ApplicationContext;
+import org.springframework.core.env.Environment;
+import org.springframework.test.annotation.DirtiesContext;
+import org.springframework.test.context.junit4.SpringRunner;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+@DirtiesContext
+@RunWith(SpringRunner.class)
+@SpringBootApplication
+@SpringBootTest(
+    classes = {
+        CamelAutoConfiguration.class,
+        CamelCloudAutoConfiguration.class,
+        ServiceCallServiceChooserAutoConfiguration.class
+    },
+    properties = {
+        "camel.cloud.servicecall.enabled=false",
+        "camel.cloud.servicecall.service-discovery.enabled=false",
+        "camel.cloud.servicecall.service-filter.enabled=false",
+        "camel.cloud.servicecall.service-chooser.enabled=true",
+        "camel.cloud.servicecall.load-balancer.enabled=false",
+        "debug=false"
+    }
+)
+public class CamelCloudServiceCallConfigurationTest {
+    @Autowired
+    private ApplicationContext ctx;
+
+    @Test
+    public void doTest() throws Exception {
+        Environment env = ctx.getEnvironment();
+
+        assertFalse(env.getProperty("camel.cloud.servicecall.enabled", Boolean.class));
+        assertFalse(env.getProperty("camel.cloud.servicecall.service-discovery.enabled", Boolean.class));
+        assertFalse(env.getProperty("camel.cloud.servicecall.service-filter.enabled", Boolean.class));
+        assertTrue(env.getProperty("camel.cloud.servicecall.service-chooser.enabled", Boolean.class));
+        assertFalse(env.getProperty("camel.cloud.servicecall.load-balancer.enabled", Boolean.class));
+
+        assertTrue(ctx.getBeansOfType(ServiceDiscovery.class).isEmpty());
+        assertTrue(ctx.getBeansOfType(ServiceFilter.class).isEmpty());
+        assertFalse(ctx.getBeansOfType(ServiceChooser.class).isEmpty());
+        assertTrue(ctx.getBeansOfType(LoadBalancer.class).isEmpty());
+    }
+}
+

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/components/camel-spring-cloud/src/test/java/org/apache/camel/spring/cloud/CamelCloudServiceCallRibbonTest.java
----------------------------------------------------------------------
diff --git a/components/camel-spring-cloud/src/test/java/org/apache/camel/spring/cloud/CamelCloudServiceCallRibbonTest.java b/components/camel-spring-cloud/src/test/java/org/apache/camel/spring/cloud/CamelCloudServiceCallRibbonTest.java
new file mode 100644
index 0000000..b038a19
--- /dev/null
+++ b/components/camel-spring-cloud/src/test/java/org/apache/camel/spring/cloud/CamelCloudServiceCallRibbonTest.java
@@ -0,0 +1,85 @@
+/**
+ * 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.spring.cloud;
+
+import org.apache.camel.ProducerTemplate;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.spring.boot.CamelAutoConfiguration;
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.test.annotation.DirtiesContext;
+import org.springframework.test.context.junit4.SpringRunner;
+
+@DirtiesContext
+@RunWith(SpringRunner.class)
+@SpringBootApplication
+@SpringBootTest(
+    classes = {
+        CamelAutoConfiguration.class,
+        CamelCloudAutoConfiguration.class,
+        CamelCloudServiceCallRibbonTest.TestConfiguration.class
+    },
+    properties = {
+        "ribbon.eureka.enabled=false",
+        "ribbon.listOfServers=localhost:9090,localhost:9091",
+        "ribbon.ServerListRefreshInterval=15000",
+        "debug=false"
+    }
+)
+public class CamelCloudServiceCallRibbonTest {
+    @Autowired
+    private ProducerTemplate template;
+
+    @Test
+    public void testServiceCall() throws Exception {
+        Assert.assertEquals("9090", template.requestBody("direct:start", null, String.class));
+        Assert.assertEquals("9091", template.requestBody("direct:start", null, String.class));
+    }
+
+    // **************************
+    // Configuration
+    // **************************
+
+    @Configuration
+    public static class TestConfiguration {
+        @Bean
+        public RouteBuilder myRouteBuilder() {
+            return new RouteBuilder() {
+                @Override
+                public void configure() throws Exception {
+                    from("direct:start")
+                        .serviceCall()
+                           .name("service-call");
+
+                    from("jetty:http://localhost:9090")
+                        .transform().constant("9090");
+                    from("jetty:http://localhost:9091")
+                        .transform().constant("9091");
+                }
+            };
+        }
+    }
+
+}
+

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/components/camel-spring-cloud/src/test/java/org/apache/camel/spring/cloud/CamelCloudServiceCallTest.java
----------------------------------------------------------------------
diff --git a/components/camel-spring-cloud/src/test/java/org/apache/camel/spring/cloud/CamelCloudServiceCallTest.java b/components/camel-spring-cloud/src/test/java/org/apache/camel/spring/cloud/CamelCloudServiceCallTest.java
new file mode 100644
index 0000000..5e26e74
--- /dev/null
+++ b/components/camel-spring-cloud/src/test/java/org/apache/camel/spring/cloud/CamelCloudServiceCallTest.java
@@ -0,0 +1,86 @@
+/**
+ * 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.spring.cloud;
+
+import org.apache.camel.ProducerTemplate;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.spring.boot.CamelAutoConfiguration;
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.test.annotation.DirtiesContext;
+import org.springframework.test.context.junit4.SpringRunner;
+
+@DirtiesContext
+@RunWith(SpringRunner.class)
+@SpringBootApplication
+@SpringBootTest(
+    classes = {
+        CamelAutoConfiguration.class,
+        CamelCloudAutoConfiguration.class,
+        CamelCloudServiceCallTest.TestConfiguration.class
+    },
+    properties = {
+        "camel.cloud.servicecall.load-balancer.enabled=false",
+        "camel.cloud.servicecall.service-discovery.services[custom-svc-list]=localhost:9090,localhost:9091",
+        "ribbon.enabled=false",
+        "debug=false"
+    }
+)
+public class CamelCloudServiceCallTest {
+    @Autowired
+    private ProducerTemplate template;
+
+    @Test
+    public void testServiceCall() throws Exception {
+        Assert.assertEquals("9090", template.requestBody("direct:start", null, String.class));
+        Assert.assertEquals("9091", template.requestBody("direct:start", null, String.class));
+    }
+
+    // **************************
+    // Configuration
+    // **************************
+
+    @Configuration
+    public static class TestConfiguration {
+        @Bean
+        public RouteBuilder myRouteBuilder() {
+            return new RouteBuilder() {
+                @Override
+                public void configure() throws Exception {
+                    from("direct:start")
+                        .serviceCall()
+                            .name("custom-svc-list/hello");
+                    from("jetty:http://localhost:9090/hello")
+                        .transform()
+                        .constant("9090");
+                    from("jetty:http://localhost:9091/hello")
+                        .transform()
+                        .constant("9091");
+                }
+            };
+        }
+    }
+
+}
+

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/components/camel-spring-cloud/src/test/java/org/apache/camel/spring/cloud/processor/remote/CamelCloudDiscoveryClient.java
----------------------------------------------------------------------
diff --git a/components/camel-spring-cloud/src/test/java/org/apache/camel/spring/cloud/processor/remote/CamelCloudDiscoveryClient.java b/components/camel-spring-cloud/src/test/java/org/apache/camel/spring/cloud/processor/remote/CamelCloudDiscoveryClient.java
deleted file mode 100644
index 136ba62..0000000
--- a/components/camel-spring-cloud/src/test/java/org/apache/camel/spring/cloud/processor/remote/CamelCloudDiscoveryClient.java
+++ /dev/null
@@ -1,71 +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.spring.cloud.processor.remote;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.LinkedHashMap;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-
-import org.springframework.cloud.client.DefaultServiceInstance;
-import org.springframework.cloud.client.ServiceInstance;
-import org.springframework.cloud.client.discovery.DiscoveryClient;
-
-public class CamelCloudDiscoveryClient implements DiscoveryClient {
-    private final String description;
-    private final Map<String, List<ServiceInstance>> services;
-
-    public CamelCloudDiscoveryClient(String description) {
-        this(description, Collections.emptyMap());
-    }
-
-    public CamelCloudDiscoveryClient(String description, Map<String, List<ServiceInstance>> services) {
-        this.description = description;
-        this.services = new LinkedHashMap<>(services);
-    }
-
-    @Override
-    public String description() {
-        return description;
-    }
-
-    @Override
-    public ServiceInstance getLocalServiceInstance() {
-        return null;
-    }
-
-    @Override
-    public List<ServiceInstance> getInstances(String serviceId) {
-        return services.get(serviceId);
-    }
-
-    @Override
-    public List<String> getServices() {
-        return new ArrayList<>(services.keySet());
-    }
-
-    public CamelCloudDiscoveryClient addServiceInstance(String serviceId, ServiceInstance instance) {
-        services.computeIfAbsent(serviceId, key -> new LinkedList<>()).add(instance);
-        return this;
-    }
-
-    public CamelCloudDiscoveryClient addServiceInstance(String serviceId, String host, int port) {
-        return addServiceInstance(serviceId, new DefaultServiceInstance(serviceId, host, port, false));
-    }
-}

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/components/camel-spring-cloud/src/test/java/org/apache/camel/spring/cloud/processor/remote/CamelCloudServiceCallConfigurationTest.java
----------------------------------------------------------------------
diff --git a/components/camel-spring-cloud/src/test/java/org/apache/camel/spring/cloud/processor/remote/CamelCloudServiceCallConfigurationTest.java b/components/camel-spring-cloud/src/test/java/org/apache/camel/spring/cloud/processor/remote/CamelCloudServiceCallConfigurationTest.java
deleted file mode 100644
index 6952c29..0000000
--- a/components/camel-spring-cloud/src/test/java/org/apache/camel/spring/cloud/processor/remote/CamelCloudServiceCallConfigurationTest.java
+++ /dev/null
@@ -1,69 +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.spring.cloud.processor.remote;
-
-import org.apache.camel.spi.ServiceCallLoadBalancer;
-import org.apache.camel.spi.ServiceCallServerListStrategy;
-import org.apache.camel.spring.boot.CamelAutoConfiguration;
-import org.apache.camel.spring.cloud.CamelCloudAutoConfiguration;
-import org.apache.camel.spring.cloud.servicecall.CamelCloudServiceCallAutoConfiguration;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.boot.autoconfigure.SpringBootApplication;
-import org.springframework.boot.test.context.SpringBootTest;
-import org.springframework.context.ApplicationContext;
-import org.springframework.core.env.Environment;
-import org.springframework.test.annotation.DirtiesContext;
-import org.springframework.test.context.junit4.SpringRunner;
-
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-
-@DirtiesContext
-@RunWith(SpringRunner.class)
-@SpringBootApplication
-@SpringBootTest(
-    classes = {
-        CamelAutoConfiguration.class,
-        CamelCloudAutoConfiguration.class,
-        CamelCloudServiceCallAutoConfiguration.class
-    },
-    properties = {
-        "camel.cloud.servicecall.enabled=false",
-        "camel.cloud.servicecall.load-balancer.enabled=true",
-        "camel.cloud.servicecall.server-list-strategy.enabled=false"
-    }
-)
-public class CamelCloudServiceCallConfigurationTest {
-    @Autowired
-    private ApplicationContext ctx;
-
-    @Test
-    public void doTest() throws Exception {
-        Environment env = ctx.getEnvironment();
-
-        assertFalse(env.getProperty("camel.cloud.servicecall.enabled", Boolean.class));
-        assertTrue(env.getProperty("camel.cloud.servicecall.load-balancer.enabled", Boolean.class));
-        assertFalse(env.getProperty("camel.cloud.servicecall.server-list-strategy.enabled", Boolean.class));
-
-        assertFalse(ctx.getBeansOfType(ServiceCallLoadBalancer.class).isEmpty());
-        assertTrue(ctx.getBeansOfType(ServiceCallServerListStrategy.class).isEmpty());
-    }
-}
-

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/components/camel-spring-cloud/src/test/java/org/apache/camel/spring/cloud/processor/remote/CamelCloudServiceCallRibbonTest.java
----------------------------------------------------------------------
diff --git a/components/camel-spring-cloud/src/test/java/org/apache/camel/spring/cloud/processor/remote/CamelCloudServiceCallRibbonTest.java b/components/camel-spring-cloud/src/test/java/org/apache/camel/spring/cloud/processor/remote/CamelCloudServiceCallRibbonTest.java
deleted file mode 100644
index 42f3565..0000000
--- a/components/camel-spring-cloud/src/test/java/org/apache/camel/spring/cloud/processor/remote/CamelCloudServiceCallRibbonTest.java
+++ /dev/null
@@ -1,83 +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.spring.cloud.processor.remote;
-
-import org.apache.camel.ProducerTemplate;
-import org.apache.camel.builder.RouteBuilder;
-import org.apache.camel.spring.boot.CamelAutoConfiguration;
-import org.junit.Assert;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.boot.autoconfigure.SpringBootApplication;
-import org.springframework.boot.test.context.SpringBootTest;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-import org.springframework.test.annotation.DirtiesContext;
-import org.springframework.test.context.junit4.SpringRunner;
-
-@DirtiesContext
-@RunWith(SpringRunner.class)
-@SpringBootApplication
-@SpringBootTest(
-    classes = {
-        CamelAutoConfiguration.class,
-        CamelCloudServiceCallRibbonTest.TestConfiguration.class
-    },
-    properties = {
-        "ribbon.eureka.enabled=false",
-        "ribbon.listOfServers=localhost:9090,localhost:9091",
-        "ribbon.ServerListRefreshInterval=15000"
-    }
-)
-public class CamelCloudServiceCallRibbonTest {
-    @Autowired
-    private ProducerTemplate template;
-
-    @Test
-    public void testServiceCall() throws Exception {
-        Assert.assertEquals("9090", template.requestBody("direct:start", null, String.class));
-        Assert.assertEquals("9091", template.requestBody("direct:start", null, String.class));
-    }
-
-    // **************************
-    // Configuration
-    // **************************
-
-    @Configuration
-    public static class TestConfiguration {
-        @Bean
-        public RouteBuilder myRouteBuilder() {
-            return new RouteBuilder() {
-                @Override
-                public void configure() throws Exception {
-                    from("direct:start")
-                        .serviceCall()
-                            .name("service-call");
-
-                    from("jetty:http://localhost:9090")
-                        .transform().constant("9090");
-                    from("jetty:http://localhost:9091")
-                        .transform().constant("9091");
-                }
-            };
-        }
-    }
-
-}
-

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/components/camel-spring-cloud/src/test/java/org/apache/camel/spring/cloud/processor/remote/CamelCloudServiceCallTest.java
----------------------------------------------------------------------
diff --git a/components/camel-spring-cloud/src/test/java/org/apache/camel/spring/cloud/processor/remote/CamelCloudServiceCallTest.java b/components/camel-spring-cloud/src/test/java/org/apache/camel/spring/cloud/processor/remote/CamelCloudServiceCallTest.java
deleted file mode 100644
index 37e9f2f..0000000
--- a/components/camel-spring-cloud/src/test/java/org/apache/camel/spring/cloud/processor/remote/CamelCloudServiceCallTest.java
+++ /dev/null
@@ -1,99 +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.spring.cloud.processor.remote;
-
-import org.apache.camel.ProducerTemplate;
-import org.apache.camel.builder.RouteBuilder;
-import org.apache.camel.spring.boot.CamelAutoConfiguration;
-import org.junit.Assert;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.boot.autoconfigure.SpringBootApplication;
-import org.springframework.boot.test.context.SpringBootTest;
-import org.springframework.cloud.client.discovery.DiscoveryClient;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-import org.springframework.test.annotation.DirtiesContext;
-import org.springframework.test.context.junit4.SpringRunner;
-
-@DirtiesContext
-@RunWith(SpringRunner.class)
-@SpringBootApplication
-@SpringBootTest(
-    classes = {
-        CamelAutoConfiguration.class,
-        CamelCloudServiceCallTest.TestConfiguration.class
-    },
-    properties = {
-        "ribbon.enabled=false"
-    }
-)
-public class CamelCloudServiceCallTest {
-    private static final int[] PORTS = new int[] {
-        9090, 9091, 9092, 9093
-    };
-
-    @Autowired
-    private ProducerTemplate template;
-
-    @Test
-    public void testServiceCall() throws Exception {
-        for (int port : PORTS) {
-            Assert.assertEquals(Integer.toString(port), template.requestBody("direct:start", null, String.class));
-        }
-    }
-
-    // **************************
-    // Configuration
-    // **************************
-
-    @Configuration
-    public static class TestConfiguration {
-        @Bean
-        public DiscoveryClient myDiscoveryClient1() {
-            CamelCloudDiscoveryClient client = new CamelCloudDiscoveryClient("myDiscoveryClient1");
-            for (int port : PORTS) {
-                client.addServiceInstance("custom-server-list", "localhost", port);
-            }
-
-            return client;
-        }
-
-        @Bean
-        public RouteBuilder myRouteBuilder() {
-            return new RouteBuilder() {
-                @Override
-                public void configure() throws Exception {
-                    from("direct:start")
-                        .serviceCall()
-                            .name("custom-server-list/hello")
-                            .loadBalancer("random-load-balancer");
-
-                    for (int port : PORTS) {
-                        fromF("jetty:http://localhost:%d/hello", port)
-                            .transform()
-                                .constant(Integer.toString(port));
-                    }
-                }
-            };
-        }
-    }
-
-}
-

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/components/camel-spring-dm/src/main/java/org/apache/camel/osgi/CamelNamespaceHandler.java
----------------------------------------------------------------------
diff --git a/components/camel-spring-dm/src/main/java/org/apache/camel/osgi/CamelNamespaceHandler.java b/components/camel-spring-dm/src/main/java/org/apache/camel/osgi/CamelNamespaceHandler.java
index 41fcf6c..35d3511 100644
--- a/components/camel-spring-dm/src/main/java/org/apache/camel/osgi/CamelNamespaceHandler.java
+++ b/components/camel-spring-dm/src/main/java/org/apache/camel/osgi/CamelNamespaceHandler.java
@@ -38,6 +38,7 @@ public class CamelNamespaceHandler extends org.apache.camel.spring.handler.Camel
         classes.add(org.apache.camel.model.language.ExpressionDefinition.class);
         classes.add(org.apache.camel.model.loadbalancer.RoundRobinLoadBalancerDefinition.class);        
         classes.add(org.apache.camel.model.rest.RestDefinition.class);
+        classes.add(org.apache.camel.model.cloud.ServiceCallDefinition.class);
         return classes;
     }
 

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/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 9e11f6c..215206f 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
@@ -37,6 +37,7 @@ import org.apache.camel.builder.RouteBuilder;
 import org.apache.camel.component.properties.PropertiesComponent;
 import org.apache.camel.component.properties.PropertiesLocation;
 import org.apache.camel.core.xml.AbstractCamelContextFactoryBean;
+import org.apache.camel.core.xml.AbstractCamelFactoryBean;
 import org.apache.camel.core.xml.CamelJMXAgentDefinition;
 import org.apache.camel.core.xml.CamelPropertyPlaceholderDefinition;
 import org.apache.camel.core.xml.CamelProxyFactoryDefinition;
@@ -56,12 +57,8 @@ import org.apache.camel.model.RouteBuilderDefinition;
 import org.apache.camel.model.RouteContextRefDefinition;
 import org.apache.camel.model.RouteDefinition;
 import org.apache.camel.model.ThreadPoolProfileDefinition;
+import org.apache.camel.model.cloud.ServiceCallConfigurationDefinition;
 import org.apache.camel.model.dataformat.DataFormatsDefinition;
-import org.apache.camel.model.remote.ConsulConfigurationDefinition;
-import org.apache.camel.model.remote.DnsConfigurationDefinition;
-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;
 import org.apache.camel.model.rest.RestDefinition;
 import org.apache.camel.model.transformer.TransformersDefinition;
@@ -156,18 +153,16 @@ public class CamelContextFactoryBean extends AbstractCamelContextFactoryBean<Spr
     @XmlElement(name = "jmxAgent", type = CamelJMXAgentDefinition.class)
     private CamelJMXAgentDefinition camelJMXAgent;
     @XmlElements({
-            @XmlElement(name = "hystrixConfiguration", type = HystrixConfigurationDefinition.class),
-            @XmlElement(name = "consulConfiguration", type = ConsulConfigurationDefinition.class),
-            @XmlElement(name = "dnsConfiguration", type = DnsConfigurationDefinition.class),
-            @XmlElement(name = "etcdConfiguration", type = EtcdConfigurationDefinition.class),
-            @XmlElement(name = "kubernetesConfiguration", type = KubernetesConfigurationDefinition.class),
-            @XmlElement(name = "ribbonConfiguration", type = RibbonConfigurationDefinition.class),
             @XmlElement(name = "template", type = CamelProducerTemplateFactoryBean.class),
             @XmlElement(name = "fluentTemplate", type = CamelFluentProducerTemplateFactoryBean.class),
             @XmlElement(name = "consumerTemplate", type = CamelConsumerTemplateFactoryBean.class),
             @XmlElement(name = "proxy", type = CamelProxyFactoryDefinition.class),
             @XmlElement(name = "export", type = CamelServiceExporterDefinition.class),
             @XmlElement(name = "errorHandler", type = ErrorHandlerDefinition.class)})
+    private List<AbstractCamelFactoryBean<?>> beansFactory;
+    @XmlElements({
+        @XmlElement(name = "serviceCallConfiguration", type = ServiceCallConfigurationDefinition.class),
+        @XmlElement(name = "hystrixConfiguration", type = HystrixConfigurationDefinition.class)})
     private List<?> beans;
     @XmlElement(name = "routeBuilder")
     private List<RouteBuilderDefinition> builderRefs = new ArrayList<RouteBuilderDefinition>();
@@ -895,13 +890,22 @@ public class CamelContextFactoryBean extends AbstractCamelContextFactoryBean<Spr
         this.redeliveryPolicies = redeliveryPolicies;
     }
 
-    public List<?> getBeans() {
-        return beans;
+    public List<AbstractCamelFactoryBean<?>> getBeansFactory() {
+        return beansFactory;
     }
 
     /**
      * Miscellaneous configurations
      */
+    public void setBeansFactory(List<AbstractCamelFactoryBean<?>> beansFactory) {
+        this.beansFactory = beansFactory;
+    }
+
+    @Override
+    public List<?> getBeans() {
+        return beans;
+    }
+
     public void setBeans(List<?> beans) {
         this.beans = beans;
     }
@@ -990,5 +994,4 @@ public class CamelContextFactoryBean extends AbstractCamelContextFactoryBean<Spr
     public void setImplicitId(boolean flag) {
         implicitId = flag;
     }
-
 }

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/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 68ae70d..12cc996 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
@@ -39,11 +39,6 @@ import org.apache.camel.impl.DefaultCamelContextNameStrategy;
 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.DnsConfigurationDefinition;
-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;
 import org.apache.camel.spi.NamespaceAware;
 import org.apache.camel.spring.CamelBeanPostProcessor;
@@ -154,11 +149,6 @@ public class CamelNamespaceHandler extends NamespaceHandlerSupport {
         addBeanDefinitionParser("streamCaching", CamelStreamCachingStrategyDefinition.class, false, false);
         addBeanDefinitionParser("propertyPlaceholder", CamelPropertyPlaceholderDefinition.class, false, false);
         addBeanDefinitionParser("hystrixConfiguration", HystrixConfigurationDefinition.class, false, false);
-        addBeanDefinitionParser("consulConfiguration", ConsulConfigurationDefinition.class, false, false);
-        addBeanDefinitionParser("dnsConfiguration", DnsConfigurationDefinition.class, false, false);
-        addBeanDefinitionParser("etcdConfiguration", EtcdConfigurationDefinition.class, false, false);
-        addBeanDefinitionParser("kubernetesConfiguration", KubernetesConfigurationDefinition.class, false, false);
-        addBeanDefinitionParser("ribbonConfiguration", RibbonConfigurationDefinition.class, false, false);
 
         // errorhandler could be the sub element of camelContext or defined outside camelContext
         BeanDefinitionParser errorHandlerParser = new ErrorHandlerDefinitionParser();
@@ -409,6 +399,8 @@ public class CamelNamespaceHandler extends NamespaceHandlerSupport {
                 builder.addPropertyValue("camelJMXAgent", factoryBean.getCamelJMXAgent());
                 builder.addPropertyValue("camelStreamCachingStrategy", factoryBean.getCamelStreamCachingStrategy());
                 builder.addPropertyValue("threadPoolProfiles", factoryBean.getThreadPoolProfiles());
+                builder.addPropertyValue("beansFactory", factoryBean.getBeansFactory());
+                builder.addPropertyValue("beans", factoryBean.getBeans());
                 // add any depends-on
                 addDependsOn(factoryBean, builder);
             }

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/components/camel-spring/src/test/java/org/apache/camel/spring/cloud/ServiceCallConfigurationTest.java
----------------------------------------------------------------------
diff --git a/components/camel-spring/src/test/java/org/apache/camel/spring/cloud/ServiceCallConfigurationTest.java b/components/camel-spring/src/test/java/org/apache/camel/spring/cloud/ServiceCallConfigurationTest.java
new file mode 100644
index 0000000..fe3371e
--- /dev/null
+++ b/components/camel-spring/src/test/java/org/apache/camel/spring/cloud/ServiceCallConfigurationTest.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.spring.cloud;
+
+import org.apache.camel.model.cloud.ServiceCallConfigurationDefinition;
+import org.apache.camel.model.cloud.StaticServiceCallServiceDiscoveryConfiguration;
+import org.apache.camel.spring.SpringCamelContext;
+import org.junit.Test;
+import org.springframework.context.support.ClassPathXmlApplicationContext;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+public class ServiceCallConfigurationTest {
+    @Test
+    public void testServiceDiscoveryConfiguration() {
+        SpringCamelContext context = createContext("org/apache/camel/spring/cloud/ServiceCallConfigurationTest.xml");
+
+        ServiceCallConfigurationDefinition conf1 = context.getServiceCallConfiguration("conf1");
+        assertNotNull("No ServiceCallConfiguration (1)", conf1);
+        assertNotNull("No ServiceDiscoveryConfiguration (1)", conf1.getServiceDiscoveryConfiguration());
+
+        StaticServiceCallServiceDiscoveryConfiguration discovery1 = (StaticServiceCallServiceDiscoveryConfiguration)conf1.getServiceDiscoveryConfiguration();
+        assertEquals(1, discovery1.getServers().size());
+        assertEquals("localhost:9091", discovery1.getServers().get(0));
+
+        ServiceCallConfigurationDefinition conf2 = context.getServiceCallConfiguration("conf2");
+        assertNotNull("No ServiceCallConfiguration (2)", conf2);
+        assertNotNull("No ServiceDiscoveryConfiguration (2)", conf2.getServiceDiscoveryConfiguration());
+
+        StaticServiceCallServiceDiscoveryConfiguration discovery2 = (StaticServiceCallServiceDiscoveryConfiguration)conf2.getServiceDiscoveryConfiguration();
+        assertEquals(2, discovery2.getServers().size());
+        assertEquals("localhost:9092", discovery2.getServers().get(0));
+        assertEquals("localhost:9093,localhost:9094", discovery2.getServers().get(1));
+    }
+
+    protected SpringCamelContext createContext(String classpathConfigFile) {
+        ClassPathXmlApplicationContext appContext = new ClassPathXmlApplicationContext(classpathConfigFile);
+
+        SpringCamelContext camelContext = appContext.getBean(SpringCamelContext.class);
+        assertNotNull("No Camel Context in file: " + classpathConfigFile, camelContext);
+
+        return camelContext;
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/components/camel-spring/src/test/resources/org/apache/camel/spring/cloud/ServiceCallConfigurationTest.xml
----------------------------------------------------------------------
diff --git a/components/camel-spring/src/test/resources/org/apache/camel/spring/cloud/ServiceCallConfigurationTest.xml b/components/camel-spring/src/test/resources/org/apache/camel/spring/cloud/ServiceCallConfigurationTest.xml
new file mode 100644
index 0000000..efc7711
--- /dev/null
+++ b/components/camel-spring/src/test/resources/org/apache/camel/spring/cloud/ServiceCallConfigurationTest.xml
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ 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.
+  -->
+<beans xmlns="http://www.springframework.org/schema/beans"
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xsi:schemaLocation="
+         http://www.springframework.org/schema/beans
+         http://www.springframework.org/schema/beans/spring-beans.xsd
+         http://camel.apache.org/schema/spring
+         http://camel.apache.org/schema/spring/camel-spring.xsd">
+
+  <camelContext xmlns="http://camel.apache.org/schema/spring">
+
+    <serviceCallConfiguration id="conf1">
+      <staticServiceDiscovery>
+        <servers>localhost:9091</servers>
+      </staticServiceDiscovery>
+    </serviceCallConfiguration>
+
+    <serviceCallConfiguration id="conf2">
+      <staticServiceDiscovery>
+        <servers>localhost:9092</servers>
+        <servers>localhost:9093,localhost:9094</servers>
+      </staticServiceDiscovery>
+    </serviceCallConfiguration>
+
+    <route id="test1">
+      <from uri="direct:start1"/>
+      <serviceCall name="test" configurationRef="conf1"/>
+    </route>
+    <route id="test2">
+      <from uri="direct:start2"/>
+      <serviceCall name="test" configurationRef="conf2"/>
+    </route>
+  </camelContext>
+
+</beans>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/components/camel-test-blueprint/src/test/java/org/apache/camel/test/blueprint/cloud/ServiceCallConfigurationTest.java
----------------------------------------------------------------------
diff --git a/components/camel-test-blueprint/src/test/java/org/apache/camel/test/blueprint/cloud/ServiceCallConfigurationTest.java b/components/camel-test-blueprint/src/test/java/org/apache/camel/test/blueprint/cloud/ServiceCallConfigurationTest.java
new file mode 100644
index 0000000..a577f88
--- /dev/null
+++ b/components/camel-test-blueprint/src/test/java/org/apache/camel/test/blueprint/cloud/ServiceCallConfigurationTest.java
@@ -0,0 +1,50 @@
+/**
+ * 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.test.blueprint.cloud;
+
+import org.apache.camel.model.cloud.ServiceCallConfigurationDefinition;
+import org.apache.camel.model.cloud.StaticServiceCallServiceDiscoveryConfiguration;
+import org.apache.camel.test.blueprint.CamelBlueprintTestSupport;
+import org.junit.Test;
+
+public class ServiceCallConfigurationTest extends CamelBlueprintTestSupport {
+    @Override
+    protected String getBlueprintDescriptor() {
+        return "org/apache/camel/test/blueprint/cloud/ServiceCallConfigurationTest.xml";
+    }
+
+    @Test
+    public void testServiceDiscoveryConfiguration() {
+        ServiceCallConfigurationDefinition conf1 = context.getServiceCallConfiguration("conf1");
+        assertNotNull("No ServiceCallConfiguration (1)", conf1);
+        assertNotNull("No ServiceDiscoveryConfiguration (1)", conf1.getServiceDiscoveryConfiguration());
+
+        StaticServiceCallServiceDiscoveryConfiguration discovery1 = (StaticServiceCallServiceDiscoveryConfiguration)conf1.getServiceDiscoveryConfiguration();
+        assertEquals(1, discovery1.getServers().size());
+        assertEquals("localhost:9091", discovery1.getServers().get(0));
+
+        ServiceCallConfigurationDefinition conf2 = context.getServiceCallConfiguration("conf2");
+        assertNotNull("No ServiceCallConfiguration (2)", conf2);
+        assertNotNull("No ServiceDiscoveryConfiguration (2)", conf2.getServiceDiscoveryConfiguration());
+
+        StaticServiceCallServiceDiscoveryConfiguration discovery2 = (StaticServiceCallServiceDiscoveryConfiguration)conf2.getServiceDiscoveryConfiguration();
+        assertEquals(2, discovery2.getServers().size());
+        assertEquals("localhost:9092", discovery2.getServers().get(0));
+        assertEquals("localhost:9093,localhost:9094", discovery2.getServers().get(1));
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/components/camel-test-blueprint/src/test/resources/org/apache/camel/test/blueprint/cloud/ServiceCallConfigurationTest.xml
----------------------------------------------------------------------
diff --git a/components/camel-test-blueprint/src/test/resources/org/apache/camel/test/blueprint/cloud/ServiceCallConfigurationTest.xml b/components/camel-test-blueprint/src/test/resources/org/apache/camel/test/blueprint/cloud/ServiceCallConfigurationTest.xml
new file mode 100644
index 0000000..27bdc6e
--- /dev/null
+++ b/components/camel-test-blueprint/src/test/resources/org/apache/camel/test/blueprint/cloud/ServiceCallConfigurationTest.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ 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.
+  -->
+<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
+           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+           xsi:schemaLocation="
+             http://www.osgi.org/xmlns/blueprint/v1.0.0
+             https://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd">
+
+  <camelContext xmlns="http://camel.apache.org/schema/blueprint">
+
+    <serviceCallConfiguration id="conf1">
+      <staticServiceDiscovery>
+        <servers>localhost:9091</servers>
+      </staticServiceDiscovery>
+    </serviceCallConfiguration>
+
+    <serviceCallConfiguration id="conf2">
+      <staticServiceDiscovery>
+        <servers>localhost:9092</servers>
+        <servers>localhost:9093,localhost:9094</servers>
+      </staticServiceDiscovery>
+    </serviceCallConfiguration>
+
+    <route id="test1">
+      <from uri="direct:start1"/>
+      <serviceCall name="test" configurationRef="conf1"/>
+    </route>
+    <route id="test2">
+      <from uri="direct:start2"/>
+      <serviceCall name="test" configurationRef="conf2"/>
+    </route>
+  </camelContext>
+
+</blueprint>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/components/pom.xml
----------------------------------------------------------------------
diff --git a/components/pom.xml b/components/pom.xml
index 0ba98f0..9852969 100644
--- a/components/pom.xml
+++ b/components/pom.xml
@@ -58,6 +58,9 @@
     <module>camel-cxf-transport</module>
     <module>camel-jms</module>
 
+    <!-- build it first so it can be used by other component to test i.e. ServiceCall EIP -->
+    <module>camel-ribbon</module>
+
     <!-- regular modules in alphabetic order -->
     <module>camel-ahc</module>
     <module>camel-ahc-ws</module>
@@ -213,7 +216,6 @@
     <module>camel-quickfix</module>
     <module>camel-rabbitmq</module>
     <module>camel-restlet</module>
-    <module>camel-ribbon</module>
     <module>camel-rmi</module>
     <module>camel-routebox</module>
     <module>camel-rss</module>


[02/10] camel git commit: CAMEL-10638: Refactor ServiceCall EIP

Posted by lb...@apache.org.
http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/components/camel-ribbon/src/test/java/org/apache/camel/component/ribbon/cloud/SpringDslRibbonServiceCallRouteTest.java
----------------------------------------------------------------------
diff --git a/components/camel-ribbon/src/test/java/org/apache/camel/component/ribbon/cloud/SpringDslRibbonServiceCallRouteTest.java b/components/camel-ribbon/src/test/java/org/apache/camel/component/ribbon/cloud/SpringDslRibbonServiceCallRouteTest.java
new file mode 100644
index 0000000..34269b3
--- /dev/null
+++ b/components/camel-ribbon/src/test/java/org/apache/camel/component/ribbon/cloud/SpringDslRibbonServiceCallRouteTest.java
@@ -0,0 +1,31 @@
+/**
+ * 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.ribbon.cloud;
+
+import org.springframework.context.support.AbstractApplicationContext;
+import org.springframework.context.support.ClassPathXmlApplicationContext;
+import org.springframework.test.annotation.DirtiesContext;
+
+@DirtiesContext
+public class SpringDslRibbonServiceCallRouteTest extends SpringRibbonServiceCallRouteTest {
+    @Override
+    protected AbstractApplicationContext createApplicationContext() {
+        return new ClassPathXmlApplicationContext("org/apache/camel/component/ribbon/cloud/SpringDslRibbonServiceCallRouteTest.xml");
+    }
+}
+

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/components/camel-ribbon/src/test/java/org/apache/camel/component/ribbon/cloud/SpringRibbonServiceCallRouteTest.java
----------------------------------------------------------------------
diff --git a/components/camel-ribbon/src/test/java/org/apache/camel/component/ribbon/cloud/SpringRibbonServiceCallRouteTest.java b/components/camel-ribbon/src/test/java/org/apache/camel/component/ribbon/cloud/SpringRibbonServiceCallRouteTest.java
new file mode 100644
index 0000000..3c9e8b2
--- /dev/null
+++ b/components/camel-ribbon/src/test/java/org/apache/camel/component/ribbon/cloud/SpringRibbonServiceCallRouteTest.java
@@ -0,0 +1,40 @@
+/**
+ * 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.ribbon.cloud;
+
+import org.apache.camel.test.spring.CamelSpringTestSupport;
+import org.junit.Test;
+import org.springframework.test.annotation.DirtiesContext;
+
+@DirtiesContext
+public abstract class SpringRibbonServiceCallRouteTest extends CamelSpringTestSupport {
+    @Test
+    public void testServiceCall() throws Exception {
+        getMockEndpoint("mock:9090").expectedMessageCount(1);
+        getMockEndpoint("mock:9091").expectedMessageCount(1);
+        getMockEndpoint("mock:result").expectedMessageCount(2);
+
+        String out = template.requestBody("direct:start", null, String.class);
+        String out2 = template.requestBody("direct:start", null, String.class);
+        assertEquals("9091", out);
+        assertEquals("9090", out2);
+
+        assertMockEndpointsSatisfied();
+    }
+}
+

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/components/camel-ribbon/src/test/java/org/apache/camel/component/ribbon/processor/RibbonServerListTest.java
----------------------------------------------------------------------
diff --git a/components/camel-ribbon/src/test/java/org/apache/camel/component/ribbon/processor/RibbonServerListTest.java b/components/camel-ribbon/src/test/java/org/apache/camel/component/ribbon/processor/RibbonServerListTest.java
deleted file mode 100644
index 4671709..0000000
--- a/components/camel-ribbon/src/test/java/org/apache/camel/component/ribbon/processor/RibbonServerListTest.java
+++ /dev/null
@@ -1,53 +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.ribbon.processor;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import junit.framework.TestCase;
-
-import com.netflix.loadbalancer.LoadBalancerBuilder;
-import com.netflix.loadbalancer.RoundRobinRule;
-import com.netflix.loadbalancer.Server;
-import com.netflix.loadbalancer.ServerList;
-import com.netflix.loadbalancer.ZoneAwareLoadBalancer;
-import org.junit.Test;
-
-public class RibbonServerListTest extends TestCase {
-
-    @Test
-    public void testFixedServerList() throws Exception {
-        List<RibbonServer> servers = new ArrayList<>();
-        servers.add(new RibbonServer("localhost", 9090));
-        servers.add(new RibbonServer("localhost", 9091));
-
-        ServerList<RibbonServer> list = new RibbonServiceCallStaticServerListStrategy(servers);
-
-        ZoneAwareLoadBalancer<RibbonServer> lb = LoadBalancerBuilder.<RibbonServer>newBuilder()
-            .withDynamicServerList(list)
-            .withRule(new RoundRobinRule()).buildDynamicServerListLoadBalancer();
-
-        Server server = lb.chooseServer();
-        assertEquals("localhost", server.getHost());
-        assertEquals(9091, server.getPort());
-
-        server = lb.chooseServer();
-        assertEquals("localhost", server.getHost());
-        assertEquals(9090, server.getPort());
-    }
-}

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/components/camel-ribbon/src/test/java/org/apache/camel/component/ribbon/processor/RibbonServiceCallRegistryRouteTest.java
----------------------------------------------------------------------
diff --git a/components/camel-ribbon/src/test/java/org/apache/camel/component/ribbon/processor/RibbonServiceCallRegistryRouteTest.java b/components/camel-ribbon/src/test/java/org/apache/camel/component/ribbon/processor/RibbonServiceCallRegistryRouteTest.java
deleted file mode 100644
index b1c7d4d..0000000
--- a/components/camel-ribbon/src/test/java/org/apache/camel/component/ribbon/processor/RibbonServiceCallRegistryRouteTest.java
+++ /dev/null
@@ -1,57 +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.ribbon.processor;
-
-import org.apache.camel.RoutesBuilder;
-import org.apache.camel.builder.RouteBuilder;
-import org.apache.camel.model.remote.RibbonConfigurationDefinition;
-
-public class RibbonServiceCallRegistryRouteTest extends RibbonServiceCallRouteTest {
-
-    @Override
-    protected RoutesBuilder createRouteBuilder() throws Exception {
-        return new RouteBuilder() {
-            @Override
-            public void configure() throws Exception {
-                // setup a static ribbon server list with these 2 servers to start with
-                RibbonServiceCallStaticServerListStrategy servers = new RibbonServiceCallStaticServerListStrategy();
-                servers.addServer("localhost", 9090);
-                servers.addServer("localhost", 9091);
-
-                // configure camel service call
-                RibbonConfigurationDefinition config = new RibbonConfigurationDefinition();
-                config.setServerListStrategy(servers);
-
-                // register configuration
-                context.setServiceCallConfiguration(config);
-
-                from("direct:start")
-                        .serviceCall("myService")
-                        .to("mock:result");
-
-                from("jetty:http://localhost:9090")
-                    .to("mock:9090")
-                    .transform().constant("9090");
-
-                from("jetty:http://localhost:9091")
-                    .to("mock:9091")
-                    .transform().constant("9091");
-            }
-        };
-    }
-}
-

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/components/camel-ribbon/src/test/java/org/apache/camel/component/ribbon/processor/RibbonServiceCallRouteTest.java
----------------------------------------------------------------------
diff --git a/components/camel-ribbon/src/test/java/org/apache/camel/component/ribbon/processor/RibbonServiceCallRouteTest.java b/components/camel-ribbon/src/test/java/org/apache/camel/component/ribbon/processor/RibbonServiceCallRouteTest.java
deleted file mode 100644
index a3abc29..0000000
--- a/components/camel-ribbon/src/test/java/org/apache/camel/component/ribbon/processor/RibbonServiceCallRouteTest.java
+++ /dev/null
@@ -1,65 +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.ribbon.processor;
-
-import org.apache.camel.RoutesBuilder;
-import org.apache.camel.builder.RouteBuilder;
-import org.apache.camel.test.junit4.CamelTestSupport;
-import org.junit.Test;
-
-public class RibbonServiceCallRouteTest extends CamelTestSupport {
-
-    @Test
-    public void testServiceCall() throws Exception {
-        getMockEndpoint("mock:9090").expectedMessageCount(1);
-        getMockEndpoint("mock:9091").expectedMessageCount(1);
-        getMockEndpoint("mock:result").expectedMessageCount(2);
-
-        String out = template.requestBody("direct:start", null, String.class);
-        String out2 = template.requestBody("direct:start", null, String.class);
-        assertEquals("9091", out);
-        assertEquals("9090", out2);
-
-        assertMockEndpointsSatisfied();
-    }
-
-    @Override
-    protected RoutesBuilder createRouteBuilder() throws Exception {
-        return new RouteBuilder() {
-            @Override
-            public void configure() throws Exception {
-                // setup a static ribbon server list with these 2 servers to start with
-                RibbonServiceCallStaticServerListStrategy servers = new RibbonServiceCallStaticServerListStrategy();
-                servers.addServer("localhost", 9090);
-                servers.addServer("localhost", 9091);
-
-                from("direct:start")
-                        .serviceCall().name("myService").ribbonConfiguration().serverListStrategy(servers).end()
-                        .to("mock:result");
-
-                from("jetty:http://localhost:9090")
-                    .to("mock:9090")
-                    .transform().constant("9090");
-
-                from("jetty:http://localhost:9091")
-                    .to("mock:9091")
-                    .transform().constant("9091");
-            }
-        };
-    }
-}
-

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/components/camel-ribbon/src/test/java/org/apache/camel/component/ribbon/processor/RibbonServiceCallUpdateRouteTest.java
----------------------------------------------------------------------
diff --git a/components/camel-ribbon/src/test/java/org/apache/camel/component/ribbon/processor/RibbonServiceCallUpdateRouteTest.java b/components/camel-ribbon/src/test/java/org/apache/camel/component/ribbon/processor/RibbonServiceCallUpdateRouteTest.java
deleted file mode 100644
index a37f5bc..0000000
--- a/components/camel-ribbon/src/test/java/org/apache/camel/component/ribbon/processor/RibbonServiceCallUpdateRouteTest.java
+++ /dev/null
@@ -1,90 +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.ribbon.processor;
-
-import org.apache.camel.RoutesBuilder;
-import org.apache.camel.builder.RouteBuilder;
-import org.apache.camel.test.junit4.CamelTestSupport;
-import org.junit.Test;
-
-public class RibbonServiceCallUpdateRouteTest extends CamelTestSupport {
-
-    private final RibbonServiceCallStaticServerListStrategy servers = new RibbonServiceCallStaticServerListStrategy();
-
-    @Override
-    public void setUp() throws Exception {
-        // setup a static ribbon server list with these 2 servers to start with
-        servers.addServer("localhost", 9090);
-        servers.addServer("localhost", 9091);
-
-        super.setUp();
-    }
-
-    @Test
-    public void testServiceCall() throws Exception {
-        getMockEndpoint("mock:9090").expectedMessageCount(1);
-        getMockEndpoint("mock:9091").expectedMessageCount(1);
-        getMockEndpoint("mock:result").expectedMessageCount(2);
-
-        String out = template.requestBody("direct:start", null, String.class);
-        String out2 = template.requestBody("direct:start", null, String.class);
-        assertEquals("9091", out);
-        assertEquals("9090", out2);
-
-        assertMockEndpointsSatisfied();
-
-        // stop the first server and remove it from the known list of servers
-        context.stopRoute("9090");
-        servers.removeServer("localhost", 9090);
-
-        // call the other active server
-        String out3 = template.requestBody("direct:start", null, String.class);
-        assertEquals("9091", out3);
-
-        // sleep a bit to make the server updated run and detect that a server is no longer in the list
-        log.debug("Sleeping to all the server list updated to run");
-        Thread.sleep(1000);
-        log.debug("Calling the service now");
-
-        // call again and it should call 9091 as its the only active server
-        String out4 = template.requestBody("direct:start", null, String.class);
-        assertEquals("9091", out4);
-    }
-
-    @Override
-    protected RoutesBuilder createRouteBuilder() throws Exception {
-        return new RouteBuilder() {
-            @Override
-            public void configure() throws Exception {
-                from("direct:start")
-                        .serviceCall().name("myService")
-                            // lets update quick so we do not have to sleep so much in the tests
-                            .ribbonConfiguration().serverListStrategy(servers).clientProperty("ServerListRefreshInterval", "250").end()
-                        .to("mock:result");
-
-                from("jetty:http://localhost:9090").routeId("9090")
-                    .to("mock:9090")
-                    .transform().constant("9090");
-
-                from("jetty:http://localhost:9091").routeId("9091")
-                    .to("mock:9091")
-                    .transform().constant("9091");
-            }
-        };
-    }
-}
-

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/components/camel-ribbon/src/test/java/org/apache/camel/component/ribbon/processor/SpringRibbonServiceCallRouteTest.java
----------------------------------------------------------------------
diff --git a/components/camel-ribbon/src/test/java/org/apache/camel/component/ribbon/processor/SpringRibbonServiceCallRouteTest.java b/components/camel-ribbon/src/test/java/org/apache/camel/component/ribbon/processor/SpringRibbonServiceCallRouteTest.java
deleted file mode 100644
index 6b35b75..0000000
--- a/components/camel-ribbon/src/test/java/org/apache/camel/component/ribbon/processor/SpringRibbonServiceCallRouteTest.java
+++ /dev/null
@@ -1,46 +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.ribbon.processor;
-
-import org.apache.camel.test.spring.CamelSpringTestSupport;
-import org.junit.Test;
-import org.springframework.context.support.AbstractApplicationContext;
-import org.springframework.context.support.ClassPathXmlApplicationContext;
-
-public class SpringRibbonServiceCallRouteTest extends CamelSpringTestSupport {
-
-    @Override
-    protected AbstractApplicationContext createApplicationContext() {
-        return new ClassPathXmlApplicationContext("org/apache/camel/component/ribbon/processor/SpringRibbonServiceCallRouteTest.xml");
-    }
-
-    @Test
-    public void testServiceCall() throws Exception {
-        getMockEndpoint("mock:9090").expectedMessageCount(1);
-        getMockEndpoint("mock:9091").expectedMessageCount(1);
-        getMockEndpoint("mock:result").expectedMessageCount(2);
-
-        String out = template.requestBody("direct:start", null, String.class);
-        String out2 = template.requestBody("direct:start", null, String.class);
-        assertEquals("9091", out);
-        assertEquals("9090", out2);
-
-        assertMockEndpointsSatisfied();
-    }
-
-}
-

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/components/camel-ribbon/src/test/resources/org/apache/camel/component/ribbon/cloud/SpringBeanRibbonServiceCallRouteTest.xml
----------------------------------------------------------------------
diff --git a/components/camel-ribbon/src/test/resources/org/apache/camel/component/ribbon/cloud/SpringBeanRibbonServiceCallRouteTest.xml b/components/camel-ribbon/src/test/resources/org/apache/camel/component/ribbon/cloud/SpringBeanRibbonServiceCallRouteTest.xml
new file mode 100644
index 0000000..01e59d9
--- /dev/null
+++ b/components/camel-ribbon/src/test/resources/org/apache/camel/component/ribbon/cloud/SpringBeanRibbonServiceCallRouteTest.xml
@@ -0,0 +1,65 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+    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.
+-->
+<beans xmlns="http://www.springframework.org/schema/beans"
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xsi:schemaLocation="
+         http://www.springframework.org/schema/beans
+         http://www.springframework.org/schema/beans/spring-beans.xsd
+         http://camel.apache.org/schema/spring
+         http://camel.apache.org/schema/spring/camel-spring.xsd">
+
+  <!-- setup a static ribbon server list with these 2 servers to start with -->
+  <bean id="discovery" class="org.apache.camel.impl.cloud.StaticServiceDiscovery">
+    <property name="servers" value="localhost:9090,localhost:9091"/>
+  </bean>
+
+  <bean id="balancer" class="org.apache.camel.component.ribbon.cloud.RibbonLoadBalancer">
+    <constructor-arg index="0">
+      <bean class="org.apache.camel.component.ribbon.RibbonConfiguration"/>
+    </constructor-arg>
+  </bean>
+
+  <camelContext xmlns="http://camel.apache.org/schema/spring">
+
+    <!-- service call configuration to use ribbon -->
+    <serviceCallConfiguration id="ribbon" loadBalancerRef="balancer" serviceDiscoveryRef="discovery"/>
+
+    <route>
+      <from uri="direct:start"/>
+      <serviceCall name="myService"/>
+      <to uri="mock:result"/>
+    </route>
+
+    <route>
+      <from uri="jetty:http://localhost:9090"/>
+      <to uri="mock:9090"/>
+      <transform>
+        <constant>9090</constant>
+      </transform>
+    </route>
+
+    <route>
+      <from uri="jetty:http://localhost:9091"/>
+      <to uri="mock:9091"/>
+      <transform>
+        <constant>9091</constant>
+      </transform>
+    </route>
+  </camelContext>
+
+</beans>

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/components/camel-ribbon/src/test/resources/org/apache/camel/component/ribbon/cloud/SpringDslRibbonServiceCallRouteTest.xml
----------------------------------------------------------------------
diff --git a/components/camel-ribbon/src/test/resources/org/apache/camel/component/ribbon/cloud/SpringDslRibbonServiceCallRouteTest.xml b/components/camel-ribbon/src/test/resources/org/apache/camel/component/ribbon/cloud/SpringDslRibbonServiceCallRouteTest.xml
new file mode 100644
index 0000000..48ce72a
--- /dev/null
+++ b/components/camel-ribbon/src/test/resources/org/apache/camel/component/ribbon/cloud/SpringDslRibbonServiceCallRouteTest.xml
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ 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.
+  -->
+<beans xmlns="http://www.springframework.org/schema/beans"
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xsi:schemaLocation="
+         http://www.springframework.org/schema/beans
+         http://www.springframework.org/schema/beans/spring-beans.xsd
+         http://camel.apache.org/schema/spring
+         http://camel.apache.org/schema/spring/camel-spring.xsd">
+
+  <camelContext xmlns="http://camel.apache.org/schema/spring">
+    <route>
+      <from uri="direct:start"/>
+      <serviceCall name="myService">
+        <!-- static list of servers -->
+        <staticServiceDiscovery>
+          <servers>localhost:9090,localhost:9091</servers>
+        </staticServiceDiscovery>
+
+        <!-- enable ribbon load balancer -->
+        <ribbonLoadBalancer clientName="myClient"/>
+      </serviceCall>
+      <to uri="mock:result"/>
+    </route>
+
+    <route>
+      <from uri="jetty:http://localhost:9090"/>
+      <to uri="mock:9090"/>
+      <transform>
+        <constant>9090</constant>
+      </transform>
+    </route>
+
+    <route>
+      <from uri="jetty:http://localhost:9091"/>
+      <to uri="mock:9091"/>
+      <transform>
+        <constant>9091</constant>
+      </transform>
+    </route>
+  </camelContext>
+
+</beans>

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/components/camel-ribbon/src/test/resources/org/apache/camel/component/ribbon/processor/SpringRibbonServiceCallRouteTest.xml
----------------------------------------------------------------------
diff --git a/components/camel-ribbon/src/test/resources/org/apache/camel/component/ribbon/processor/SpringRibbonServiceCallRouteTest.xml b/components/camel-ribbon/src/test/resources/org/apache/camel/component/ribbon/processor/SpringRibbonServiceCallRouteTest.xml
deleted file mode 100644
index 6b2df8d..0000000
--- a/components/camel-ribbon/src/test/resources/org/apache/camel/component/ribbon/processor/SpringRibbonServiceCallRouteTest.xml
+++ /dev/null
@@ -1,60 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-    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.
--->
-<beans xmlns="http://www.springframework.org/schema/beans"
-       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-       xsi:schemaLocation="
-       http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
-       http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd
-    ">
-
-  <!-- setup a static ribbon server list with these 2 servers to start with -->
-  <!-- call the build method with the argument below -->
-  <bean id="servers" class="org.apache.camel.component.ribbon.processor.RibbonServiceCallStaticServerListStrategy"
-        factory-method="build">
-    <constructor-arg index="0" value="localhost:9090,localhost:9091"/>
-  </bean>
-
-  <camelContext xmlns="http://camel.apache.org/schema/spring">
-
-    <!-- service call configuration to use ribbon -->
-    <ribbonConfiguration id="ribbon" serverListStrategyRef="servers"/>
-
-    <route>
-      <from uri="direct:start"/>
-      <serviceCall name="myService"/>
-      <to uri="mock:result"/>
-    </route>
-
-    <route>
-      <from uri="jetty:http://localhost:9090"/>
-      <to uri="mock:9090"/>
-      <transform>
-        <constant>9090</constant>
-      </transform>
-    </route>
-
-    <route>
-      <from uri="jetty:http://localhost:9091"/>
-      <to uri="mock:9091"/>
-      <transform>
-        <constant>9091</constant>
-      </transform>
-    </route>
-  </camelContext>
-
-</beans>

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/components/camel-spring-cloud/src/main/java/org/apache/camel/spring/cloud/CamelCloudDiscoveryClient.java
----------------------------------------------------------------------
diff --git a/components/camel-spring-cloud/src/main/java/org/apache/camel/spring/cloud/CamelCloudDiscoveryClient.java b/components/camel-spring-cloud/src/main/java/org/apache/camel/spring/cloud/CamelCloudDiscoveryClient.java
new file mode 100644
index 0000000..194f518
--- /dev/null
+++ b/components/camel-spring-cloud/src/main/java/org/apache/camel/spring/cloud/CamelCloudDiscoveryClient.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.spring.cloud;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.LinkedHashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+import org.springframework.cloud.client.DefaultServiceInstance;
+import org.springframework.cloud.client.ServiceInstance;
+import org.springframework.cloud.client.discovery.DiscoveryClient;
+
+public class CamelCloudDiscoveryClient implements DiscoveryClient {
+    private final String description;
+    private final Map<String, List<ServiceInstance>> services;
+    private ServiceInstance localInstance;
+
+    public CamelCloudDiscoveryClient(String description) {
+        this(description, Collections.emptyMap());
+    }
+
+    public CamelCloudDiscoveryClient(String description, Map<String, List<ServiceInstance>> services) {
+        this.description = description;
+        this.services = new LinkedHashMap<>(services);
+        this.localInstance = null;
+    }
+
+    @Override
+    public String description() {
+        return description;
+    }
+
+    @Override
+    public ServiceInstance getLocalServiceInstance() {
+        return this.localInstance;
+    }
+
+    @Override
+    public List<ServiceInstance> getInstances(String serviceId) {
+        return services.get(serviceId);
+    }
+
+    @Override
+    public List<String> getServices() {
+        return new ArrayList<>(services.keySet());
+    }
+
+    public CamelCloudDiscoveryClient addServiceInstance(ServiceInstance instance) {
+        services.computeIfAbsent(instance.getServiceId(), key -> new LinkedList<>()).add(instance);
+        return this;
+    }
+
+    public CamelCloudDiscoveryClient addServiceInstance(String serviceId, String host, int port) {
+        return addServiceInstance(new DefaultServiceInstance(serviceId, host, port, false));
+    }
+
+    public CamelCloudDiscoveryClient setLocalServiceInstance(ServiceInstance instance) {
+        this.localInstance = instance;
+        return this;
+    }
+
+    public CamelCloudDiscoveryClient setLocalServiceInstance(String serviceId, String host, int port) {
+        return setLocalServiceInstance(new DefaultServiceInstance(serviceId, host, port, false));
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/components/camel-spring-cloud/src/main/java/org/apache/camel/spring/cloud/CamelCloudLoadBalancer.java
----------------------------------------------------------------------
diff --git a/components/camel-spring-cloud/src/main/java/org/apache/camel/spring/cloud/CamelCloudLoadBalancer.java b/components/camel-spring-cloud/src/main/java/org/apache/camel/spring/cloud/CamelCloudLoadBalancer.java
new file mode 100644
index 0000000..08a73b8
--- /dev/null
+++ b/components/camel-spring-cloud/src/main/java/org/apache/camel/spring/cloud/CamelCloudLoadBalancer.java
@@ -0,0 +1,71 @@
+/**
+ * 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.spring.cloud;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.CamelContextAware;
+import org.apache.camel.cloud.LoadBalancer;
+import org.apache.camel.cloud.LoadBalancerFunction;
+import org.apache.camel.impl.cloud.DefaultServiceDefinition;
+import org.apache.camel.support.ServiceSupport;
+import org.apache.camel.util.ObjectHelper;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
+
+public class CamelCloudLoadBalancer extends ServiceSupport implements CamelContextAware, LoadBalancer {
+    private static final Logger LOGGER = LoggerFactory.getLogger(CamelCloudLoadBalancer.class);
+
+    private final LoadBalancerClient loadBalancerClient;
+    private CamelContext camelContext;
+
+    public CamelCloudLoadBalancer(LoadBalancerClient loadBalancerClient) {
+        this.loadBalancerClient = loadBalancerClient;
+    }
+
+    @Override
+    public CamelContext getCamelContext() {
+        return camelContext;
+    }
+
+    @Override
+    public void setCamelContext(CamelContext camelContext) {
+        this.camelContext = camelContext;
+    }
+
+    @Override
+    protected void doStart() throws Exception {
+        ObjectHelper.notNull(camelContext, "camelContext");
+        ObjectHelper.notNull(loadBalancerClient, "loadBalancerClient");
+
+        LOGGER.info("ServiceCall is using cloud load balancer of type: {}",
+            loadBalancerClient.getClass());
+    }
+
+    @Override
+    protected void doStop() throws Exception {
+    }
+
+    @Override
+    public <T> T process(String serviceName, LoadBalancerFunction<T> function) throws Exception {
+        return loadBalancerClient.execute(
+            serviceName,
+            i -> function.apply(new DefaultServiceDefinition(i.getServiceId(), i.getHost(), i.getPort(), i.getMetadata()))
+        );
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/components/camel-spring-cloud/src/main/java/org/apache/camel/spring/cloud/CamelCloudServiceDiscovery.java
----------------------------------------------------------------------
diff --git a/components/camel-spring-cloud/src/main/java/org/apache/camel/spring/cloud/CamelCloudServiceDiscovery.java b/components/camel-spring-cloud/src/main/java/org/apache/camel/spring/cloud/CamelCloudServiceDiscovery.java
new file mode 100644
index 0000000..3896494
--- /dev/null
+++ b/components/camel-spring-cloud/src/main/java/org/apache/camel/spring/cloud/CamelCloudServiceDiscovery.java
@@ -0,0 +1,52 @@
+/**
+ * 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.spring.cloud;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.stream.Collectors;
+
+import org.apache.camel.cloud.ServiceDefinition;
+import org.apache.camel.impl.cloud.DefaultServiceDefinition;
+import org.apache.camel.impl.cloud.DefaultServiceDiscovery;
+import org.springframework.cloud.client.discovery.DiscoveryClient;
+
+public class CamelCloudServiceDiscovery extends DefaultServiceDiscovery {
+    private final List<DiscoveryClient> clients;
+
+    public CamelCloudServiceDiscovery(List<DiscoveryClient> clients) {
+        this.clients = new ArrayList<>(clients);
+    }
+
+    @Override
+    public List<ServiceDefinition> getInitialListOfServices(String name) {
+        return getServers(name);
+    }
+
+    @Override
+    public List<ServiceDefinition> getUpdatedListOfServices(String name) {
+        return getServers(name);
+    }
+
+    private List<ServiceDefinition> getServers(String name) {
+        return clients.stream()
+            .flatMap(c -> c.getInstances(name).stream())
+            .map(s -> new DefaultServiceDefinition(s.getServiceId(), s.getHost(), s.getPort(), s.getMetadata()))
+            .collect(Collectors.toList());
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/components/camel-spring-cloud/src/main/java/org/apache/camel/spring/cloud/ServiceCallConfigurationProperties.java
----------------------------------------------------------------------
diff --git a/components/camel-spring-cloud/src/main/java/org/apache/camel/spring/cloud/ServiceCallConfigurationProperties.java b/components/camel-spring-cloud/src/main/java/org/apache/camel/spring/cloud/ServiceCallConfigurationProperties.java
new file mode 100644
index 0000000..dd1124e
--- /dev/null
+++ b/components/camel-spring-cloud/src/main/java/org/apache/camel/spring/cloud/ServiceCallConfigurationProperties.java
@@ -0,0 +1,113 @@
+/**
+ * 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.spring.cloud;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.springframework.boot.context.properties.ConfigurationProperties;
+
+@ConfigurationProperties(prefix = "camel.cloud.servicecall")
+public class ServiceCallConfigurationProperties {
+    private boolean enabled = true;
+    private LoadBalancer loadBalancer = new LoadBalancer();
+    private ServiceDiscovery serviceDiscovery = new ServiceDiscovery();
+    private ServiceFilter serviceFilter = new ServiceFilter();
+    private ServiceChooser serviceChooser = new ServiceChooser();
+
+    public boolean isEnabled() {
+        return enabled;
+    }
+
+    public void setEnabled(boolean enabled) {
+        this.enabled = enabled;
+    }
+
+    public LoadBalancer getLoadBalancer() {
+        return loadBalancer;
+    }
+
+    public ServiceDiscovery getServiceDiscovery() {
+        return serviceDiscovery;
+    }
+
+    public ServiceFilter getServiceFilter() {
+        return serviceFilter;
+    }
+
+    public ServiceChooser getServiceChooser() {
+        return serviceChooser;
+    }
+
+    // *****************************************
+    // Nested configurations
+    // *****************************************
+
+    public static class LoadBalancer {
+        private boolean enabled = true;
+
+        public boolean isEnabled() {
+            return enabled;
+        }
+
+        public void setEnabled(boolean enabled) {
+            this.enabled = enabled;
+        }
+    }
+
+    public static class ServiceDiscovery {
+        private boolean enabled = true;
+        private Map<String, String> services = new HashMap<>();
+
+        public boolean isEnabled() {
+            return enabled;
+        }
+
+        public void setEnabled(boolean enabled) {
+            this.enabled = enabled;
+        }
+
+        public Map<String, String> getServices() {
+            return services;
+        }
+    }
+
+    public static class ServiceFilter {
+        private boolean enabled = true;
+
+        public boolean isEnabled() {
+            return enabled;
+        }
+
+        public void setEnabled(boolean enabled) {
+            this.enabled = enabled;
+        }
+    }
+
+    public static class ServiceChooser {
+        private boolean enabled = true;
+
+        public boolean isEnabled() {
+            return enabled;
+        }
+
+        public void setEnabled(boolean enabled) {
+            this.enabled = enabled;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/components/camel-spring-cloud/src/main/java/org/apache/camel/spring/cloud/ServiceCallLoadBalancerAutoConfiguration.java
----------------------------------------------------------------------
diff --git a/components/camel-spring-cloud/src/main/java/org/apache/camel/spring/cloud/ServiceCallLoadBalancerAutoConfiguration.java b/components/camel-spring-cloud/src/main/java/org/apache/camel/spring/cloud/ServiceCallLoadBalancerAutoConfiguration.java
new file mode 100644
index 0000000..32b66d2
--- /dev/null
+++ b/components/camel-spring-cloud/src/main/java/org/apache/camel/spring/cloud/ServiceCallLoadBalancerAutoConfiguration.java
@@ -0,0 +1,54 @@
+/**
+ * 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.spring.cloud;
+
+import org.apache.camel.cloud.LoadBalancer;
+import org.apache.camel.spring.boot.util.GroupCondition;
+import org.springframework.boot.autoconfigure.AutoConfigureAfter;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.cloud.client.loadbalancer.LoadBalancerAutoConfiguration;
+import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Conditional;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Lazy;
+import org.springframework.context.annotation.Scope;
+
+@Configuration
+@ConditionalOnBean({ CamelCloudAutoConfiguration.class, LoadBalancerClient.class })
+@AutoConfigureAfter(LoadBalancerAutoConfiguration.class)
+@EnableConfigurationProperties(ServiceCallConfigurationProperties.class)
+public class ServiceCallLoadBalancerAutoConfiguration {
+    @Lazy
+    @Scope("prototype")
+    @Bean(name = "cloud-load-balancer")
+    @Conditional(ServiceCallLoadBalancerAutoConfiguration.LoadBalancerCondition.class)
+    public LoadBalancer cloudLoadBalancer(LoadBalancerClient loadBalancerClient) {
+        return new CamelCloudLoadBalancer(loadBalancerClient);
+    }
+
+    public static class LoadBalancerCondition extends GroupCondition {
+        public LoadBalancerCondition() {
+            super(
+                "camel.cloud.servicecall",
+                "camel.cloud.servicecall.load-balancer"
+            );
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/components/camel-spring-cloud/src/main/java/org/apache/camel/spring/cloud/ServiceCallServiceChooserAutoConfiguration.java
----------------------------------------------------------------------
diff --git a/components/camel-spring-cloud/src/main/java/org/apache/camel/spring/cloud/ServiceCallServiceChooserAutoConfiguration.java b/components/camel-spring-cloud/src/main/java/org/apache/camel/spring/cloud/ServiceCallServiceChooserAutoConfiguration.java
new file mode 100644
index 0000000..dae38a0
--- /dev/null
+++ b/components/camel-spring-cloud/src/main/java/org/apache/camel/spring/cloud/ServiceCallServiceChooserAutoConfiguration.java
@@ -0,0 +1,64 @@
+/**
+ * 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.spring.cloud;
+
+import org.apache.camel.cloud.ServiceChooser;
+import org.apache.camel.impl.cloud.RandomServiceChooser;
+import org.apache.camel.impl.cloud.RoundRobinServiceChooser;
+import org.apache.camel.spring.boot.util.GroupCondition;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Conditional;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Lazy;
+import org.springframework.context.annotation.Scope;
+import org.springframework.core.annotation.Order;
+
+@Configuration
+@ConditionalOnBean(CamelCloudAutoConfiguration.class)
+@EnableConfigurationProperties(ServiceCallConfigurationProperties.class)
+public class ServiceCallServiceChooserAutoConfiguration {
+
+    @Lazy
+    @Scope("prototype")
+    @Order(1)
+    @Bean(name = "round-robin-service-chooser")
+    @Conditional(ServiceCallServiceChooserAutoConfiguration.ServiceChooserCondition.class)
+    public ServiceChooser roundRobinLoadBalancer() {
+        return new RoundRobinServiceChooser();
+    }
+
+    @Lazy
+    @Scope("prototype")
+    @Order(2)
+    @Bean(name = "random-service-chooser")
+    @Conditional(ServiceCallServiceChooserAutoConfiguration.ServiceChooserCondition.class)
+    public ServiceChooser randomLoadBalancer() {
+        return new RandomServiceChooser();
+    }
+
+    public static class ServiceChooserCondition extends GroupCondition {
+        public ServiceChooserCondition() {
+            super(
+                "camel.cloud.servicecall",
+                "camel.cloud.servicecall.service-chooser"
+            );
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/components/camel-spring-cloud/src/main/java/org/apache/camel/spring/cloud/ServiceCallServiceDiscoveryAutoConfiguration.java
----------------------------------------------------------------------
diff --git a/components/camel-spring-cloud/src/main/java/org/apache/camel/spring/cloud/ServiceCallServiceDiscoveryAutoConfiguration.java b/components/camel-spring-cloud/src/main/java/org/apache/camel/spring/cloud/ServiceCallServiceDiscoveryAutoConfiguration.java
new file mode 100644
index 0000000..4934465
--- /dev/null
+++ b/components/camel-spring-cloud/src/main/java/org/apache/camel/spring/cloud/ServiceCallServiceDiscoveryAutoConfiguration.java
@@ -0,0 +1,75 @@
+/**
+ * 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.spring.cloud;
+
+import java.util.List;
+import java.util.Map;
+
+import org.apache.camel.cloud.ServiceDiscovery;
+import org.apache.camel.spring.boot.util.GroupCondition;
+import org.apache.camel.util.StringHelper;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.cloud.client.discovery.DiscoveryClient;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Conditional;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Lazy;
+import org.springframework.context.annotation.Scope;
+
+@Configuration
+@EnableConfigurationProperties(ServiceCallConfigurationProperties.class)
+public class ServiceCallServiceDiscoveryAutoConfiguration {
+    @Lazy
+    @Scope("prototype")
+    @Bean(name = "service-discovery-client")
+    @Conditional(ServiceCallServiceDiscoveryAutoConfiguration.ServiceDiscoveryCondition.class)
+    public DiscoveryClient serviceDiscoveryClient(ServiceCallConfigurationProperties properties) {
+        CamelCloudDiscoveryClient client = new CamelCloudDiscoveryClient("service-discovery-client");
+
+        Map<String, String> services = properties.getServiceDiscovery().getServices();
+        for (Map.Entry<String, String> entry : services.entrySet()) {
+
+            String[] parts = entry.getValue().split(",");
+            for (String part : parts) {
+                String host = StringHelper.before(part, ":");
+                String port = StringHelper.after(part, ":");
+
+                client.addServiceInstance(entry.getKey(), host, Integer.parseInt(port));
+            }
+        }
+
+        return client;
+    }
+
+    @Lazy
+    @Scope("prototype")
+    @Bean(name = "service-discovery")
+    @Conditional(ServiceCallServiceDiscoveryAutoConfiguration.ServiceDiscoveryCondition.class)
+    public ServiceDiscovery serviceDiscovery(List<DiscoveryClient> clients) {
+        return new CamelCloudServiceDiscovery(clients);
+    }
+
+    public static class ServiceDiscoveryCondition extends GroupCondition {
+        public ServiceDiscoveryCondition() {
+            super(
+                "camel.cloud.servicecall",
+                "camel.cloud.servicecall.service-discovery"
+            );
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/components/camel-spring-cloud/src/main/java/org/apache/camel/spring/cloud/ServiceCallServiceFilterAutoConfiguration.java
----------------------------------------------------------------------
diff --git a/components/camel-spring-cloud/src/main/java/org/apache/camel/spring/cloud/ServiceCallServiceFilterAutoConfiguration.java b/components/camel-spring-cloud/src/main/java/org/apache/camel/spring/cloud/ServiceCallServiceFilterAutoConfiguration.java
new file mode 100644
index 0000000..d97c7d1
--- /dev/null
+++ b/components/camel-spring-cloud/src/main/java/org/apache/camel/spring/cloud/ServiceCallServiceFilterAutoConfiguration.java
@@ -0,0 +1,58 @@
+/**
+ * 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.spring.cloud;
+
+import org.apache.camel.cloud.ServiceFilter;
+import org.apache.camel.impl.cloud.AllServiceFilter;
+import org.apache.camel.impl.cloud.HealthyServiceFilter;
+import org.apache.camel.spring.boot.util.GroupCondition;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Conditional;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Lazy;
+import org.springframework.context.annotation.Scope;
+
+@Configuration
+@EnableConfigurationProperties(ServiceCallConfigurationProperties.class)
+public class ServiceCallServiceFilterAutoConfiguration {
+    @Lazy
+    @Scope("prototype")
+    @Bean(name = "service-filter-healthy")
+    @Conditional(ServiceCallServiceFilterAutoConfiguration.ServiceFilterCondition.class)
+    public ServiceFilter healthyServiceFilter() {
+        return new HealthyServiceFilter();
+    }
+
+    @Lazy
+    @Scope("prototype")
+    @Bean(name = "service-filter-all")
+    @Conditional(ServiceCallServiceFilterAutoConfiguration.ServiceFilterCondition.class)
+    public ServiceFilter allServiceFilter() {
+        return new AllServiceFilter();
+    }
+
+    public static class ServiceFilterCondition extends GroupCondition {
+        public ServiceFilterCondition() {
+            super(
+                "camel.cloud.servicecall",
+                "camel.cloud.servicecall.service-filter"
+            );
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/components/camel-spring-cloud/src/main/java/org/apache/camel/spring/cloud/servicecall/CamelCloudServiceCallAutoConfiguration.java
----------------------------------------------------------------------
diff --git a/components/camel-spring-cloud/src/main/java/org/apache/camel/spring/cloud/servicecall/CamelCloudServiceCallAutoConfiguration.java b/components/camel-spring-cloud/src/main/java/org/apache/camel/spring/cloud/servicecall/CamelCloudServiceCallAutoConfiguration.java
deleted file mode 100644
index 4f382e7..0000000
--- a/components/camel-spring-cloud/src/main/java/org/apache/camel/spring/cloud/servicecall/CamelCloudServiceCallAutoConfiguration.java
+++ /dev/null
@@ -1,95 +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.spring.cloud.servicecall;
-
-import java.util.List;
-
-import org.apache.camel.impl.remote.RoundRobinServiceCallLoadBalancer;
-import org.apache.camel.spi.ServiceCallLoadBalancer;
-import org.apache.camel.spi.ServiceCallServer;
-import org.apache.camel.spi.ServiceCallServerListStrategy;
-import org.apache.camel.spring.boot.CamelAutoConfiguration;
-import org.apache.camel.spring.boot.util.GroupCondition;
-import org.apache.camel.spring.cloud.CamelCloudAutoConfiguration;
-import org.springframework.boot.autoconfigure.AutoConfigureAfter;
-import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
-import org.springframework.cloud.client.discovery.DiscoveryClient;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Conditional;
-import org.springframework.context.annotation.Configuration;
-import org.springframework.context.annotation.Lazy;
-import org.springframework.context.annotation.Scope;
-import org.springframework.core.annotation.Order;
-
-@Configuration
-@ConditionalOnBean(CamelCloudAutoConfiguration.class)
-public class CamelCloudServiceCallAutoConfiguration {
-
-    // ******************************************
-    // ServiceCall - ServerListStrategy
-    // ******************************************
-
-    @Lazy
-    @Scope("prototype")
-    @Bean(name = "server-list-strategy")
-    @ConditionalOnBean(DiscoveryClient.class)
-    @Conditional(CamelCloudServiceCallAutoConfiguration.ServerListStrategyCondition.class)
-    public ServiceCallServerListStrategy serverListStrategy(List<DiscoveryClient> clients) {
-        return new CamelCloudServiceCallServerListStrategy(clients);
-    }
-
-    public static class ServerListStrategyCondition extends GroupCondition {
-        public ServerListStrategyCondition() {
-            super(
-                "camel.cloud.servicecall",
-                "camel.cloud.servicecall.server-list-strategy"
-            );
-        }
-    }
-
-    // ******************************************
-    // ServiceCall - Load Balancer
-    // ******************************************
-
-    @Lazy
-    @Scope("prototype")
-    @Order(1)
-    @Bean(name = "round-robin-load-balancer")
-    @Conditional(CamelCloudServiceCallAutoConfiguration.LoadBalancerCondition.class)
-    public ServiceCallLoadBalancer<ServiceCallServer> roundRobinLoadBalancer() {
-        return new RoundRobinServiceCallLoadBalancer<>();
-    }
-
-    @Lazy
-    @Scope("prototype")
-    @Order(2)
-    @Bean(name = "random-load-balancer")
-    @Conditional(CamelCloudServiceCallAutoConfiguration.LoadBalancerCondition.class)
-    public ServiceCallLoadBalancer<ServiceCallServer> randomLoadBalancer() {
-        return new RoundRobinServiceCallLoadBalancer<>();
-    }
-
-    public static class LoadBalancerCondition extends GroupCondition {
-        public LoadBalancerCondition() {
-            super(
-                "camel.cloud.servicecall",
-                "camel.cloud.servicecall.load-balancer"
-            );
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/components/camel-spring-cloud/src/main/java/org/apache/camel/spring/cloud/servicecall/CamelCloudServiceCallConfigurationProperties.java
----------------------------------------------------------------------
diff --git a/components/camel-spring-cloud/src/main/java/org/apache/camel/spring/cloud/servicecall/CamelCloudServiceCallConfigurationProperties.java b/components/camel-spring-cloud/src/main/java/org/apache/camel/spring/cloud/servicecall/CamelCloudServiceCallConfigurationProperties.java
deleted file mode 100644
index 548bcd7..0000000
--- a/components/camel-spring-cloud/src/main/java/org/apache/camel/spring/cloud/servicecall/CamelCloudServiceCallConfigurationProperties.java
+++ /dev/null
@@ -1,79 +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.spring.cloud.servicecall;
-
-import org.springframework.boot.context.properties.ConfigurationProperties;
-
-@ConfigurationProperties(prefix = "camel.cloud.servicecall")
-public class CamelCloudServiceCallConfigurationProperties {
-    private boolean enabled = true;
-    private LoadBalancer loadBalancer;
-    private ServerListStrategy serverListStrategy;
-
-    public boolean isEnabled() {
-        return enabled;
-    }
-
-    public void setEnabled(boolean enabled) {
-        this.enabled = enabled;
-    }
-
-    public LoadBalancer getLoadBalancer() {
-        return loadBalancer;
-    }
-
-    public void setLoadBalancer(LoadBalancer loadBalancer) {
-        this.loadBalancer = loadBalancer;
-    }
-
-    public ServerListStrategy getServerListStrategy() {
-        return serverListStrategy;
-    }
-
-    public void setServerListStrategy(ServerListStrategy serverListStrategy) {
-        this.serverListStrategy = serverListStrategy;
-    }
-
-    // *****************************************
-    // Nested configurations
-    // *****************************************
-
-    public static class LoadBalancer {
-        private boolean enabled = true;
-
-        public boolean isEnabled() {
-            return enabled;
-        }
-
-        public void setEnabled(boolean enabled) {
-            this.enabled = enabled;
-        }
-    }
-
-    public static class ServerListStrategy {
-        private boolean enabled = true;
-
-        public boolean isEnabled() {
-            return enabled;
-        }
-
-        public void setEnabled(boolean enabled) {
-            this.enabled = enabled;
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/components/camel-spring-cloud/src/main/java/org/apache/camel/spring/cloud/servicecall/CamelCloudServiceCallProcessor.java
----------------------------------------------------------------------
diff --git a/components/camel-spring-cloud/src/main/java/org/apache/camel/spring/cloud/servicecall/CamelCloudServiceCallProcessor.java b/components/camel-spring-cloud/src/main/java/org/apache/camel/spring/cloud/servicecall/CamelCloudServiceCallProcessor.java
deleted file mode 100644
index bb965ab..0000000
--- a/components/camel-spring-cloud/src/main/java/org/apache/camel/spring/cloud/servicecall/CamelCloudServiceCallProcessor.java
+++ /dev/null
@@ -1,200 +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.spring.cloud.servicecall;
-
-import java.io.IOException;
-
-import org.apache.camel.AsyncCallback;
-import org.apache.camel.AsyncProcessor;
-import org.apache.camel.CamelContext;
-import org.apache.camel.CamelContextAware;
-import org.apache.camel.Exchange;
-import org.apache.camel.ExchangePattern;
-import org.apache.camel.Expression;
-import org.apache.camel.RuntimeCamelException;
-import org.apache.camel.Traceable;
-import org.apache.camel.impl.remote.DefaultServiceCallExpression;
-import org.apache.camel.impl.remote.ServiceCallConstants;
-import org.apache.camel.processor.SendDynamicProcessor;
-import org.apache.camel.spi.IdAware;
-import org.apache.camel.support.ServiceSupport;
-import org.apache.camel.util.AsyncProcessorHelper;
-import org.apache.camel.util.ObjectHelper;
-import org.apache.camel.util.ServiceHelper;
-import org.apache.camel.util.StringHelper;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
-
-public class CamelCloudServiceCallProcessor extends ServiceSupport implements AsyncProcessor, CamelContextAware, Traceable, IdAware {
-    private static final Logger LOG = LoggerFactory.getLogger(CamelCloudServiceCallProcessor.class);
-
-    private final ExchangePattern exchangePattern;
-    private final String name;
-    private final String scheme;
-    private final String uri;
-    private final String contextPath;
-    private final LoadBalancerClient loadBalancerClient;
-    private CamelContext camelContext;
-    private String id;
-    private Expression serviceCallExpression;
-    private SendDynamicProcessor processor;
-
-    public CamelCloudServiceCallProcessor(String name, String scheme, String uri, ExchangePattern exchangePattern, LoadBalancerClient loadBalancerClient) {
-        this.uri = uri;
-        this.exchangePattern = exchangePattern;
-        this.loadBalancerClient = loadBalancerClient;
-
-        // setup from the provided name which can contain scheme and context-path information as well
-        String serviceName;
-        if (name.contains("/")) {
-            serviceName = StringHelper.before(name, "/");
-            this.contextPath = StringHelper.after(name, "/");
-        } else if (name.contains("?")) {
-            serviceName = StringHelper.before(name, "?");
-            this.contextPath = StringHelper.after(name, "?");
-        } else {
-            serviceName = name;
-            this.contextPath = null;
-        }
-        if (serviceName.contains(":")) {
-            this.scheme = StringHelper.before(serviceName, ":");
-            this.name = StringHelper.after(serviceName, ":");
-        } else {
-            this.scheme = scheme;
-            this.name = serviceName;
-        }
-
-        this.serviceCallExpression = new DefaultServiceCallExpression(
-            this.name,
-            this.scheme,
-            this.contextPath,
-            this.uri);
-    }
-
-    @Override
-    public CamelContext getCamelContext() {
-        return camelContext;
-    }
-
-    @Override
-    public void setCamelContext(CamelContext camelContext) {
-        this.camelContext = camelContext;
-    }
-
-    @Override
-    public String getId() {
-        return id;
-    }
-
-    @Override
-    public void setId(String id) {
-        this.id = id;
-    }
-
-    @Override
-    public String getTraceLabel() {
-        return id;
-    }
-
-    public String getName() {
-        return name;
-    }
-
-    public String getScheme() {
-        return scheme;
-    }
-
-    public String getContextPath() {
-        return contextPath;
-    }
-
-    public String getUri() {
-        return uri;
-    }
-
-    public ExchangePattern getExchangePattern() {
-        return exchangePattern;
-    }
-
-    public void setServiceCallExpression(Expression serviceCallExpression) {
-        this.serviceCallExpression = serviceCallExpression;
-    }
-
-    public Expression getServiceCallExpression() {
-        return serviceCallExpression;
-    }
-
-    public CamelCloudServiceCallProcessor serviceCallExpression(Expression serviceCallExpression) {
-        setServiceCallExpression(serviceCallExpression);
-        return this;
-    }
-
-    public AsyncProcessor getProcessor() {
-        return processor;
-    }
-
-    @Override
-    protected void doStart() throws Exception {
-        StringHelper.notEmpty(getName(), "name", "serviceName");
-        ObjectHelper.notNull(camelContext, "camelContext");
-        ObjectHelper.notNull(serviceCallExpression, "serviceCallExpression");
-        ObjectHelper.notNull(loadBalancerClient, "loadBalancerClient");
-
-        LOG.info("ServiceCall with service name: {}", name);
-
-        processor = new SendDynamicProcessor(uri, serviceCallExpression);
-        processor.setCamelContext(getCamelContext());
-        if (exchangePattern != null) {
-            processor.setPattern(exchangePattern);
-        }
-
-        ServiceHelper.startServices(processor);
-    }
-
-    @Override
-    protected void doStop() throws Exception {
-    }
-
-    @Override
-    public void process(Exchange exchange) throws Exception {
-        AsyncProcessorHelper.process(this, exchange);
-    }
-
-    @Override
-    public boolean process(final Exchange exchange, final AsyncCallback callback) {
-        if (exchange.getException() != null) {
-            callback.done(true);
-            return true;
-        }
-
-        try {
-            return loadBalancerClient.execute(
-                exchange.getIn().getHeader(ServiceCallConstants.SERVICE_NAME, name, String.class),
-                instance -> {
-                    exchange.getIn().setHeader(ServiceCallConstants.SERVER_IP, instance.getHost());
-                    exchange.getIn().setHeader(ServiceCallConstants.SERVER_PORT, instance.getPort());
-                    exchange.getIn().setHeader(ServiceCallConstants.SERVICE_NAME, instance.getServiceId());
-                    return processor.process(exchange, callback);
-                }
-            );
-        } catch (IOException e) {
-            throw new RuntimeCamelException(e);
-        }
-    }
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/components/camel-spring-cloud/src/main/java/org/apache/camel/spring/cloud/servicecall/CamelCloudServiceCallProcessorFactory.java
----------------------------------------------------------------------
diff --git a/components/camel-spring-cloud/src/main/java/org/apache/camel/spring/cloud/servicecall/CamelCloudServiceCallProcessorFactory.java b/components/camel-spring-cloud/src/main/java/org/apache/camel/spring/cloud/servicecall/CamelCloudServiceCallProcessorFactory.java
deleted file mode 100644
index 2db3ffe..0000000
--- a/components/camel-spring-cloud/src/main/java/org/apache/camel/spring/cloud/servicecall/CamelCloudServiceCallProcessorFactory.java
+++ /dev/null
@@ -1,201 +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.spring.cloud.servicecall;
-
-import java.util.Set;
-import java.util.function.Supplier;
-
-import org.apache.camel.CamelContext;
-import org.apache.camel.ExchangePattern;
-import org.apache.camel.Processor;
-import org.apache.camel.impl.remote.AbstractServiceCallProcessorFactory;
-import org.apache.camel.impl.remote.DefaultServiceCallProcessor;
-import org.apache.camel.model.remote.ServiceCallConfigurationDefinition;
-import org.apache.camel.model.remote.ServiceCallDefinition;
-import org.apache.camel.spi.RouteContext;
-import org.apache.camel.spi.ServiceCallLoadBalancer;
-import org.apache.camel.spi.ServiceCallServer;
-import org.apache.camel.spi.ServiceCallServerListStrategy;
-import org.apache.camel.util.CamelContextHelper;
-import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
-
-public class CamelCloudServiceCallProcessorFactory extends AbstractServiceCallProcessorFactory {
-    @Override
-    protected Processor createProcessor(RouteContext routeContext, ServiceCallDefinition definition) throws Exception {
-        String name = definition.getName();
-        String uri = definition.getUri();
-        ExchangePattern mep = definition.getPattern();
-        CamelContext camelContext = routeContext.getCamelContext();
-
-        ServiceCallConfigurationDefinition config = definition.getServiceCallConfiguration();
-        ServiceCallConfigurationDefinition configRef = null;
-        if (definition.getServiceCallConfigurationRef() != null) {
-            // lookup in registry first
-            configRef = CamelContextHelper.lookup(camelContext, definition.getServiceCallConfigurationRef(), ServiceCallConfigurationDefinition.class);
-            if (configRef == null) {
-                // and fallback as service configuration
-                camelContext.getServiceCallConfiguration(definition.getServiceCallConfigurationRef(), ServiceCallConfigurationDefinition.class);
-            }
-        }
-
-        // if no configuration explicit configured then use default
-        if (config == null && configRef == null) {
-            config = camelContext.getServiceCallConfiguration(null, ServiceCallConfigurationDefinition.class);
-        }
-        if (config == null) {
-            // if no default then try to find if there configuration in the registry of the given type
-            Set<ServiceCallConfigurationDefinition> set = camelContext.getRegistry().findByType(ServiceCallConfigurationDefinition.class);
-            if (set.size() == 1) {
-                config = set.iterator().next();
-            }
-        }
-
-
-        //if (config == null && configRef == null) {
-        //    throw new IllegalStateException("The ServiceCall: " + definition + " must be configured before it can be used.");
-        //}
-
-        String component = definition.getComponent();
-        if (component == null) {
-            component = config != null ? config.getComponent() : null;
-            if (component == null && configRef != null) {
-                component = configRef.getComponent();
-            }
-        }
-
-        // lookup the load balancer to use (configured on EIP takes precedence vs configured on configuration)
-        Object lb = retrieveLoadBalancer(camelContext, definition, config, configRef);
-        if (lb == null) {
-            throw new IllegalArgumentException("Load balancer must be provided");
-        }
-
-        if (lb instanceof LoadBalancerClient) {
-            return new CamelCloudServiceCallProcessor(name, uri, component, mep, (LoadBalancerClient) lb);
-        } else if (lb instanceof ServiceCallLoadBalancer) {
-
-            ServiceCallServerListStrategy<ServiceCallServer> sl = retrieveServerListStrategy(camelContext, definition, config, configRef);
-            if (lb == null) {
-                throw new IllegalArgumentException("Server list strategy must be provided");
-            }
-
-            DefaultServiceCallProcessor<ServiceCallServer> processor = new DefaultServiceCallProcessor<>(name, component, uri, mep);
-            processor.setLoadBalancer((ServiceCallLoadBalancer<ServiceCallServer>)lb);
-            processor.setServerListStrategy(sl);
-
-            return processor;
-        } else {
-            throw new IllegalStateException(
-                "Unable to configure ServiceCall: LoadBalancer should be an instance of LoadBalancerClient or ServiceCallLoadBalancer, got " + lb.getClass().getName()
-            );
-        }
-    }
-
-    // *************************************************************************
-    // Load Balancer
-    // *************************************************************************
-
-    private Object retrieveLoadBalancer(
-        CamelContext camelContext, ServiceCallDefinition definition, ServiceCallConfigurationDefinition config, ServiceCallConfigurationDefinition configRef) {
-
-        // lookup the load balancer to use (configured on EIP takes precedence vs configured on configuration)
-        Object lb = retrieveLoadBalancer(camelContext, definition::getLoadBalancer, definition::getLoadBalancerRef);
-        if (lb == null && config != null) {
-            lb = retrieveLoadBalancer(camelContext, config::getLoadBalancer, config::getLoadBalancerRef);
-        }
-        if (lb == null && configRef != null) {
-            lb = retrieveLoadBalancer(camelContext, configRef::getLoadBalancer, configRef::getLoadBalancerRef);
-        }
-
-        if (lb == null) {
-            Set<LoadBalancerClient> set = camelContext.getRegistry().findByType(LoadBalancerClient.class);
-            if (set.size() == 1) {
-                lb = set.iterator().next();
-            }
-        }
-
-        return lb;
-    }
-
-    private Object retrieveLoadBalancer(
-        CamelContext camelContext, Supplier<Object> loadBalancerSupplier, Supplier<String> loadBalancerRefSupplier) {
-
-        Object lb = null;
-
-        if (loadBalancerSupplier != null) {
-            lb = loadBalancerSupplier.get();
-        }
-
-        if (lb == null && loadBalancerRefSupplier != null) {
-            String ref = loadBalancerRefSupplier.get();
-            if (ref != null) {
-                lb = CamelContextHelper.lookup(camelContext, ref, LoadBalancerClient.class);
-            }
-            if (ref != null && lb == null) {
-                lb = CamelContextHelper.lookup(camelContext, ref, ServiceCallLoadBalancer.class);
-            }
-        }
-
-        return lb;
-    }
-
-    // *************************************************************************
-    // Server List
-    // *************************************************************************
-
-
-    private ServiceCallServerListStrategy retrieveServerListStrategy(
-        CamelContext camelContext, ServiceCallDefinition definition, ServiceCallConfigurationDefinition config, ServiceCallConfigurationDefinition configRef) {
-
-        // lookup the server list strategy to use (configured on EIP takes precedence vs configured on configuration)
-        ServiceCallServerListStrategy sl = retrieveServerListStrategy(camelContext, definition::getServerListStrategy, definition::getServerListStrategyRef);
-        if (sl == null && config != null) {
-            sl = retrieveServerListStrategy(camelContext, config::getServerListStrategy, config::getServerListStrategyRef);
-        }
-        if (sl == null && configRef != null) {
-            sl = retrieveServerListStrategy(camelContext, configRef::getServerListStrategy, configRef::getServerListStrategyRef);
-        }
-
-        if (sl == null) {
-            Set<ServiceCallServerListStrategy> set = camelContext.getRegistry().findByType(ServiceCallServerListStrategy.class);
-            if (set.size() == 1) {
-                sl = set.iterator().next();
-            }
-        }
-
-        return sl;
-    }
-
-    private ServiceCallServerListStrategy retrieveServerListStrategy(
-        CamelContext camelContext, Supplier<ServiceCallServerListStrategy> serverListSupplier, Supplier<String> serverListSupplierRef) {
-
-        ServiceCallServerListStrategy sl = null;
-
-        if (serverListSupplier != null) {
-            sl = serverListSupplier.get();
-        }
-
-        if (sl == null && serverListSupplierRef != null) {
-            String ref = serverListSupplierRef.get();
-            if (ref != null) {
-                sl = CamelContextHelper.lookup(camelContext, ref, ServiceCallServerListStrategy.class);
-            }
-        }
-
-        return sl;
-    }
-}

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/components/camel-spring-cloud/src/main/java/org/apache/camel/spring/cloud/servicecall/CamelCloudServiceCallServerListStrategy.java
----------------------------------------------------------------------
diff --git a/components/camel-spring-cloud/src/main/java/org/apache/camel/spring/cloud/servicecall/CamelCloudServiceCallServerListStrategy.java b/components/camel-spring-cloud/src/main/java/org/apache/camel/spring/cloud/servicecall/CamelCloudServiceCallServerListStrategy.java
deleted file mode 100644
index 3f30b6c..0000000
--- a/components/camel-spring-cloud/src/main/java/org/apache/camel/spring/cloud/servicecall/CamelCloudServiceCallServerListStrategy.java
+++ /dev/null
@@ -1,52 +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.spring.cloud.servicecall;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.stream.Collectors;
-
-import org.apache.camel.impl.remote.DefaultServiceCallServer;
-import org.apache.camel.impl.remote.DefaultServiceCallServerListStrategy;
-import org.apache.camel.spi.ServiceCallServer;
-import org.springframework.cloud.client.discovery.DiscoveryClient;
-
-public class CamelCloudServiceCallServerListStrategy extends DefaultServiceCallServerListStrategy<ServiceCallServer> {
-    private final List<DiscoveryClient> clients;
-
-    public CamelCloudServiceCallServerListStrategy(List<DiscoveryClient> clients) {
-        this.clients = new ArrayList<>(clients);
-    }
-
-    @Override
-    public List<ServiceCallServer> getInitialListOfServers(String name) {
-        return getServers(name);
-    }
-
-    @Override
-    public List<ServiceCallServer> getUpdatedListOfServers(String name) {
-        return getServers(name);
-    }
-
-    private List<ServiceCallServer> getServers(String name) {
-        return clients.stream()
-            .flatMap(c -> c.getInstances(name).stream())
-            .map(s -> new DefaultServiceCallServer(s.getHost(), s.getPort(), s.getMetadata()))
-            .collect(Collectors.toList());
-    }
-}

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/components/camel-spring-cloud/src/main/resources/META-INF/services/org/apache/camel/model/ServiceCallDefinition
----------------------------------------------------------------------
diff --git a/components/camel-spring-cloud/src/main/resources/META-INF/services/org/apache/camel/model/ServiceCallDefinition b/components/camel-spring-cloud/src/main/resources/META-INF/services/org/apache/camel/model/ServiceCallDefinition
deleted file mode 100644
index c5f036b..0000000
--- a/components/camel-spring-cloud/src/main/resources/META-INF/services/org/apache/camel/model/ServiceCallDefinition
+++ /dev/null
@@ -1,18 +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.
-#
-
-class=org.apache.camel.spring.cloud.servicecall.CamelCloudServiceCallProcessorFactory

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/components/camel-spring-cloud/src/main/resources/META-INF/spring.factories
----------------------------------------------------------------------
diff --git a/components/camel-spring-cloud/src/main/resources/META-INF/spring.factories b/components/camel-spring-cloud/src/main/resources/META-INF/spring.factories
index 429fa52..d925094 100644
--- a/components/camel-spring-cloud/src/main/resources/META-INF/spring.factories
+++ b/components/camel-spring-cloud/src/main/resources/META-INF/spring.factories
@@ -17,4 +17,6 @@
 
 org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
 org.apache.camel.spring.cloud.CamelCloudAutoConfiguration,\
-org.apache.camel.spring.cloud.servicecall.CamelCloudServiceCallAutoConfiguration
+org.apache.camel.spring.cloud.ServiceCallServiceChooserAutoConfiguration,\
+org.apache.camel.spring.cloud.ServiceCallServiceDiscoveryAutoConfiguration,\
+org.apache.camel.spring.cloud.ServiceCallLoadBalancerAutoConfiguration


[06/10] camel git commit: CAMEL-10638: Refactor ServiceCall EIP

Posted by lb...@apache.org.
http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/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 41da245..6d94f9f 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
@@ -39,6 +39,7 @@ import org.apache.camel.core.osgi.OsgiCamelContextPublisher;
 import org.apache.camel.core.osgi.OsgiEventAdminNotifier;
 import org.apache.camel.core.osgi.utils.BundleDelegatingClassLoader;
 import org.apache.camel.core.xml.AbstractCamelContextFactoryBean;
+import org.apache.camel.core.xml.AbstractCamelFactoryBean;
 import org.apache.camel.core.xml.CamelJMXAgentDefinition;
 import org.apache.camel.core.xml.CamelPropertyPlaceholderDefinition;
 import org.apache.camel.core.xml.CamelServiceExporterDefinition;
@@ -57,12 +58,8 @@ import org.apache.camel.model.RouteBuilderDefinition;
 import org.apache.camel.model.RouteContextRefDefinition;
 import org.apache.camel.model.RouteDefinition;
 import org.apache.camel.model.ThreadPoolProfileDefinition;
+import org.apache.camel.model.cloud.ServiceCallConfigurationDefinition;
 import org.apache.camel.model.dataformat.DataFormatsDefinition;
-import org.apache.camel.model.remote.ConsulConfigurationDefinition;
-import org.apache.camel.model.remote.DnsConfigurationDefinition;
-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;
 import org.apache.camel.model.rest.RestDefinition;
 import org.apache.camel.model.transformer.TransformersDefinition;
@@ -147,18 +144,16 @@ public class CamelContextFactoryBean extends AbstractCamelContextFactoryBean<Blu
     @XmlElement(name = "streamCaching", type = CamelStreamCachingStrategyDefinition.class)
     private CamelStreamCachingStrategyDefinition camelStreamCachingStrategy;
     @XmlElements({
-        @XmlElement(name = "hystrixConfiguration", type = HystrixConfigurationDefinition.class),
-        @XmlElement(name = "kubernetesConfiguration", type = KubernetesConfigurationDefinition.class),
-        @XmlElement(name = "ribbonConfiguration", type = RibbonConfigurationDefinition.class),
-        @XmlElement(name = "consulConfiguration", type = ConsulConfigurationDefinition.class),
-        @XmlElement(name = "dnsConfiguration", type = DnsConfigurationDefinition.class),
-        @XmlElement(name = "etcdConfiguration", type = EtcdConfigurationDefinition.class),
         @XmlElement(name = "template", type = CamelProducerTemplateFactoryBean.class),
         @XmlElement(name = "fluentTemplate", type = CamelFluentProducerTemplateFactoryBean.class),
         @XmlElement(name = "consumerTemplate", type = CamelConsumerTemplateFactoryBean.class),
         @XmlElement(name = "proxy", type = CamelProxyFactoryBean.class),
         @XmlElement(name = "export", type = CamelServiceExporterDefinition.class),
         @XmlElement(name = "errorHandler", type = CamelErrorHandlerFactoryBean.class)})
+    private List<AbstractCamelFactoryBean<?>> beansFactory;
+    @XmlElements({
+        @XmlElement(name = "serviceCallConfiguration", type = ServiceCallConfigurationDefinition.class),
+        @XmlElement(name = "hystrixConfiguration", type = HystrixConfigurationDefinition.class)})
     private List<?> beans;
     @XmlElement(name = "routeBuilder")
     private List<RouteBuilderDefinition> builderRefs = new ArrayList<RouteBuilderDefinition>();
@@ -616,6 +611,15 @@ public class CamelContextFactoryBean extends AbstractCamelContextFactoryBean<Blu
         this.camelStreamCachingStrategy = camelStreamCachingStrategy;
     }
 
+    public List<AbstractCamelFactoryBean<?>> getBeansFactory() {
+        return beansFactory;
+    }
+
+    public void setBeansFactory(List<AbstractCamelFactoryBean<?>> beansFactory) {
+        this.beansFactory = beansFactory;
+    }
+
+    @Override
     public List<?> getBeans() {
         return beans;
     }

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/components/camel-blueprint/src/main/java/org/apache/camel/blueprint/handler/CamelNamespaceHandler.java
----------------------------------------------------------------------
diff --git a/components/camel-blueprint/src/main/java/org/apache/camel/blueprint/handler/CamelNamespaceHandler.java b/components/camel-blueprint/src/main/java/org/apache/camel/blueprint/handler/CamelNamespaceHandler.java
index e95f5e1..a4801f1 100644
--- a/components/camel-blueprint/src/main/java/org/apache/camel/blueprint/handler/CamelNamespaceHandler.java
+++ b/components/camel-blueprint/src/main/java/org/apache/camel/blueprint/handler/CamelNamespaceHandler.java
@@ -282,7 +282,7 @@ public class CamelNamespaceHandler implements NamespaceHandler {
         registerBeans(context, contextId, ccfb.getThreadPools());
         registerBeans(context, contextId, ccfb.getEndpoints());
         registerBeans(context, contextId, ccfb.getRedeliveryPolicies());
-        registerBeans(context, contextId, ccfb.getBeans());
+        registerBeans(context, contextId, ccfb.getBeansFactory());
 
         // Register processors
         MutablePassThroughMetadata beanProcessorFactory = context.createMetadata(MutablePassThroughMetadata.class);

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/components/camel-cdi/src/main/java/org/apache/camel/cdi/XmlCdiBeanFactory.java
----------------------------------------------------------------------
diff --git a/components/camel-cdi/src/main/java/org/apache/camel/cdi/XmlCdiBeanFactory.java b/components/camel-cdi/src/main/java/org/apache/camel/cdi/XmlCdiBeanFactory.java
index a9aaf05..53d7a6b 100644
--- a/components/camel-cdi/src/main/java/org/apache/camel/cdi/XmlCdiBeanFactory.java
+++ b/components/camel-cdi/src/main/java/org/apache/camel/cdi/XmlCdiBeanFactory.java
@@ -193,8 +193,8 @@ final class XmlCdiBeanFactory {
         Set<SyntheticBean<?>> beans = new HashSet<>();
 
         // TODO: WARN log if the definition doesn't have an id
-        if (factory.getBeans() != null) {
-            factory.getBeans().stream()
+        if (factory.getBeansFactory() != null) {
+            factory.getBeansFactory().stream()
                 .filter(XmlCdiBeanFactory::hasId)
                 .map(bean -> camelContextBean(context, bean, url))
                 .forEach(beans::add);

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/components/camel-cdi/src/main/java/org/apache/camel/cdi/xml/CamelContextFactoryBean.java
----------------------------------------------------------------------
diff --git a/components/camel-cdi/src/main/java/org/apache/camel/cdi/xml/CamelContextFactoryBean.java b/components/camel-cdi/src/main/java/org/apache/camel/cdi/xml/CamelContextFactoryBean.java
index 9299424..e5135f6 100644
--- a/components/camel-cdi/src/main/java/org/apache/camel/cdi/xml/CamelContextFactoryBean.java
+++ b/components/camel-cdi/src/main/java/org/apache/camel/cdi/xml/CamelContextFactoryBean.java
@@ -45,6 +45,7 @@ import org.apache.camel.core.xml.CamelServiceExporterDefinition;
 import org.apache.camel.core.xml.CamelStreamCachingStrategyDefinition;
 import org.apache.camel.impl.DefaultCamelContext;
 import org.apache.camel.model.ContextScanDefinition;
+import org.apache.camel.model.HystrixConfigurationDefinition;
 import org.apache.camel.model.InterceptDefinition;
 import org.apache.camel.model.InterceptFromDefinition;
 import org.apache.camel.model.InterceptSendToEndpointDefinition;
@@ -57,6 +58,7 @@ import org.apache.camel.model.RouteBuilderDefinition;
 import org.apache.camel.model.RouteContextRefDefinition;
 import org.apache.camel.model.RouteDefinition;
 import org.apache.camel.model.ThreadPoolProfileDefinition;
+import org.apache.camel.model.cloud.ServiceCallConfigurationDefinition;
 import org.apache.camel.model.dataformat.DataFormatsDefinition;
 import org.apache.camel.model.rest.RestConfigurationDefinition;
 import org.apache.camel.model.rest.RestDefinition;
@@ -159,9 +161,14 @@ public class CamelContextFactoryBean extends AbstractCamelContextFactoryBean<Def
         @XmlElement(name = "consumerTemplate", type = ConsumerTemplateFactoryBean.class),
         @XmlElement(name = "redeliveryPolicyProfile", type = RedeliveryPolicyFactoryBean.class),
         @XmlElement(name = "template", type = ProducerTemplateFactoryBean.class),
-        @XmlElement(name = "threadPool", type = ThreadPoolFactoryBean.class)
+        @XmlElement(name = "threadPool", type = ThreadPoolFactoryBean.class),
     })
-    private List<AbstractCamelFactoryBean<?>> beans;
+    private List<AbstractCamelFactoryBean<?>> beansFactory;
+
+    @XmlElements({
+        @XmlElement(name = "serviceCallConfiguration", type = ServiceCallConfigurationDefinition.class),
+        @XmlElement(name = "hystrixConfiguration", type = HystrixConfigurationDefinition.class)})
+    private List<?> beans;
 
     @XmlElement(name = "errorHandler", type = ErrorHandlerDefinition.class)
     private List<ErrorHandlerDefinition> errorHandlers;
@@ -303,11 +310,20 @@ public class CamelContextFactoryBean extends AbstractCamelContextFactoryBean<Def
         return context;
     }
 
-    public List<AbstractCamelFactoryBean<?>> getBeans() {
+    public List<AbstractCamelFactoryBean<?>> getBeansFactory() {
+        return beansFactory;
+    }
+
+    public void setBeansFactory(List<AbstractCamelFactoryBean<?>> beansFactory) {
+        this.beansFactory = beansFactory;
+    }
+
+    @Override
+    public List<?> getBeans() {
         return beans;
     }
 
-    public void setBeans(List<AbstractCamelFactoryBean<?>> beans) {
+    public void setBeans(List<?> beans) {
         this.beans = beans;
     }
 

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/components/camel-cdi/src/test/java/org/apache/camel/cdi/test/XmlServiceCallConfigurationTest.java
----------------------------------------------------------------------
diff --git a/components/camel-cdi/src/test/java/org/apache/camel/cdi/test/XmlServiceCallConfigurationTest.java b/components/camel-cdi/src/test/java/org/apache/camel/cdi/test/XmlServiceCallConfigurationTest.java
new file mode 100644
index 0000000..23e0b14
--- /dev/null
+++ b/components/camel-cdi/src/test/java/org/apache/camel/cdi/test/XmlServiceCallConfigurationTest.java
@@ -0,0 +1,79 @@
+/**
+ * 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.cdi.test;
+
+import java.nio.file.Paths;
+import javax.inject.Inject;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.cdi.CdiCamelExtension;
+import org.apache.camel.cdi.ImportResource;
+import org.apache.camel.model.cloud.ServiceCallConfigurationDefinition;
+import org.apache.camel.model.cloud.StaticServiceCallServiceDiscoveryConfiguration;
+import org.jboss.arquillian.container.test.api.Deployment;
+import org.jboss.arquillian.junit.Arquillian;
+import org.jboss.shrinkwrap.api.Archive;
+import org.jboss.shrinkwrap.api.ShrinkWrap;
+import org.jboss.shrinkwrap.api.asset.EmptyAsset;
+import org.jboss.shrinkwrap.api.spec.JavaArchive;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+@RunWith(Arquillian.class)
+@ImportResource("imported-context.xml")
+public class XmlServiceCallConfigurationTest {
+
+    @Inject
+    private CamelContext context;
+
+    @Deployment
+    public static Archive<?> deployment() {
+        return ShrinkWrap.create(JavaArchive.class)
+            // Camel CDI
+            .addPackage(CdiCamelExtension.class.getPackage())
+            // Test Camel XML
+            .addAsResource(
+                Paths.get("src/test/resources/camel-context-service-call-configuration.xml").toFile(),
+                "imported-context.xml")
+            // Bean archive deployment descriptor
+            .addAsManifestResource(EmptyAsset.INSTANCE, "beans.xml");
+    }
+
+    @Test
+    public void testServiceDiscoveryConfiguration() {
+        ServiceCallConfigurationDefinition conf1 = context.getServiceCallConfiguration("conf1");
+        assertNotNull("No ServiceCallConfiguration (1)", conf1);
+        assertNotNull("No ServiceDiscoveryConfiguration (1)", conf1.getServiceDiscoveryConfiguration());
+
+        StaticServiceCallServiceDiscoveryConfiguration discovery1 = (StaticServiceCallServiceDiscoveryConfiguration)conf1.getServiceDiscoveryConfiguration();
+        assertEquals(1, discovery1.getServers().size());
+        assertEquals("localhost:9091", discovery1.getServers().get(0));
+
+        ServiceCallConfigurationDefinition conf2 = context.getServiceCallConfiguration("conf2");
+        assertNotNull("No ServiceCallConfiguration (2)", conf2);
+        assertNotNull("No ServiceDiscoveryConfiguration (2)", conf2.getServiceDiscoveryConfiguration());
+
+        StaticServiceCallServiceDiscoveryConfiguration discovery2 = (StaticServiceCallServiceDiscoveryConfiguration)conf2.getServiceDiscoveryConfiguration();
+        assertEquals(2, discovery2.getServers().size());
+        assertEquals("localhost:9092", discovery2.getServers().get(0));
+        assertEquals("localhost:9093,localhost:9094", discovery2.getServers().get(1));
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/components/camel-cdi/src/test/resources/camel-context-service-call-configuration.xml
----------------------------------------------------------------------
diff --git a/components/camel-cdi/src/test/resources/camel-context-service-call-configuration.xml b/components/camel-cdi/src/test/resources/camel-context-service-call-configuration.xml
new file mode 100644
index 0000000..cb18c8b
--- /dev/null
+++ b/components/camel-cdi/src/test/resources/camel-context-service-call-configuration.xml
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ 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.
+  -->
+<beans xmlns="http://www.springframework.org/schema/beans"
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xsi:schemaLocation="
+        http://www.springframework.org/schema/beans
+        http://www.springframework.org/schema/beans/spring-beans.xsd
+        http://camel.apache.org/schema/spring
+        http://camel.apache.org/schema/spring/camel-spring.xsd">
+
+    <camelContext id="test" xmlns="http://camel.apache.org/schema/spring">
+
+        <serviceCallConfiguration id="conf1">
+            <staticServiceDiscovery>
+                <servers>localhost:9091</servers>
+            </staticServiceDiscovery>
+        </serviceCallConfiguration>
+
+        <serviceCallConfiguration id="conf2">
+            <staticServiceDiscovery>
+                <servers>localhost:9092</servers>
+                <servers>localhost:9093,localhost:9094</servers>
+            </staticServiceDiscovery>
+        </serviceCallConfiguration>
+
+        <route id="test1">
+            <from uri="direct:start1"/>
+            <serviceCall name="test" configurationRef="conf1"/>
+        </route>
+        <route id="test2">
+            <from uri="direct:start2"/>
+            <serviceCall name="test" configurationRef="conf2"/>
+        </route>
+
+    </camelContext>
+
+</beans>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/components/camel-consul/pom.xml
----------------------------------------------------------------------
diff --git a/components/camel-consul/pom.xml b/components/camel-consul/pom.xml
index f660bf5..133d2ff 100644
--- a/components/camel-consul/pom.xml
+++ b/components/camel-consul/pom.xml
@@ -73,6 +73,11 @@
       <scope>test</scope>
     </dependency>
     <dependency>
+      <groupId>org.apache.camel</groupId>
+      <artifactId>camel-ribbon</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
       <groupId>org.apache.logging.log4j</groupId>
       <artifactId>log4j-api</artifactId>
       <scope>test</scope>

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/components/camel-consul/src/main/java/org/apache/camel/component/consul/ConsulConfiguration.java
----------------------------------------------------------------------
diff --git a/components/camel-consul/src/main/java/org/apache/camel/component/consul/ConsulConfiguration.java b/components/camel-consul/src/main/java/org/apache/camel/component/consul/ConsulConfiguration.java
index e64cd77..dbf1466 100644
--- a/components/camel-consul/src/main/java/org/apache/camel/component/consul/ConsulConfiguration.java
+++ b/components/camel-consul/src/main/java/org/apache/camel/component/consul/ConsulConfiguration.java
@@ -70,6 +70,10 @@ public class ConsulConfiguration {
 
     private final CamelContext context;
 
+    public ConsulConfiguration() {
+        this.context = null;
+    }
+
     public ConsulConfiguration(CamelContext context) {
         this.context = context;
     }

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/components/camel-consul/src/main/java/org/apache/camel/component/consul/cloud/ConsulServiceDiscovery.java
----------------------------------------------------------------------
diff --git a/components/camel-consul/src/main/java/org/apache/camel/component/consul/cloud/ConsulServiceDiscovery.java b/components/camel-consul/src/main/java/org/apache/camel/component/consul/cloud/ConsulServiceDiscovery.java
new file mode 100644
index 0000000..104f65a
--- /dev/null
+++ b/components/camel-consul/src/main/java/org/apache/camel/component/consul/cloud/ConsulServiceDiscovery.java
@@ -0,0 +1,104 @@
+/**
+ * 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.consul.cloud;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+import com.orbitz.consul.Consul;
+import com.orbitz.consul.model.catalog.CatalogService;
+import com.orbitz.consul.model.health.ServiceHealth;
+import com.orbitz.consul.option.CatalogOptions;
+import com.orbitz.consul.option.ImmutableCatalogOptions;
+import org.apache.camel.cloud.ServiceDefinition;
+import org.apache.camel.component.consul.ConsulConfiguration;
+import org.apache.camel.impl.cloud.DefaultServiceDefinition;
+import org.apache.camel.impl.cloud.DefaultServiceDiscovery;
+import org.apache.camel.impl.cloud.DefaultServiceHealth;
+import org.apache.camel.util.ObjectHelper;
+
+public final class ConsulServiceDiscovery extends DefaultServiceDiscovery {
+    private final Consul client;
+    private final CatalogOptions catalogOptions;
+
+    public ConsulServiceDiscovery(ConsulConfiguration configuration) throws Exception {
+        this.client = configuration.createConsulClient();
+
+        ImmutableCatalogOptions.Builder builder = ImmutableCatalogOptions.builder();
+        if (ObjectHelper.isNotEmpty(configuration.getDc())) {
+            builder.datacenter(configuration.getDc());
+        }
+        if (ObjectHelper.isNotEmpty(configuration.getTags())) {
+            configuration.getTags().forEach(builder::tag);
+        }
+
+        catalogOptions = builder.build();
+    }
+
+    @Override
+    public List<ServiceDefinition> getUpdatedListOfServices(String name) {
+        List<CatalogService> services = client.catalogClient()
+            .getService(name, catalogOptions)
+            .getResponse();
+        List<ServiceHealth> healths = client.healthClient()
+            .getAllServiceInstances(name, catalogOptions)
+            .getResponse();
+
+        return services.stream()
+            .map(service -> newService(name, service, healths))
+            .collect(Collectors.toList());
+    }
+
+    // *************************
+    // Helpers
+    // *************************
+
+    private boolean isHealthy(ServiceHealth serviceHealth) {
+        return serviceHealth.getChecks().stream().allMatch(
+            check -> ObjectHelper.equal(check.getStatus(), "passing", true)
+        );
+    }
+
+    private ServiceDefinition newService(String serviceName, CatalogService service, List<ServiceHealth> serviceHealthList) {
+        Map<String, String> meta = new HashMap<>();
+        ObjectHelper.ifNotEmpty(service.getServiceId(), val -> meta.put("service_id", val));
+        ObjectHelper.ifNotEmpty(service.getNode(), val -> meta.put("node", val));
+        ObjectHelper.ifNotEmpty(service.getServiceName(), val -> meta.put("service_name", val));
+
+        List<String> tags = service.getServiceTags();
+        if (tags != null) {
+            for (String tag : service.getServiceTags()) {
+                String[] items = tag.split("=");
+                if (items.length == 1) {
+                    meta.put(items[0], items[0]);
+                } else if (items.length == 2) {
+                    meta.put(items[0], items[1]);
+                }
+            }
+        }
+
+        return new DefaultServiceDefinition(
+            serviceName,
+            service.getServiceAddress(),
+            service.getServicePort(),
+            meta,
+            new DefaultServiceHealth(serviceHealthList.stream().allMatch(this::isHealthy))
+        );
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/components/camel-consul/src/main/java/org/apache/camel/component/consul/cloud/ConsulServiceDiscoveryFactory.java
----------------------------------------------------------------------
diff --git a/components/camel-consul/src/main/java/org/apache/camel/component/consul/cloud/ConsulServiceDiscoveryFactory.java b/components/camel-consul/src/main/java/org/apache/camel/component/consul/cloud/ConsulServiceDiscoveryFactory.java
new file mode 100644
index 0000000..9207d3e
--- /dev/null
+++ b/components/camel-consul/src/main/java/org/apache/camel/component/consul/cloud/ConsulServiceDiscoveryFactory.java
@@ -0,0 +1,124 @@
+/**
+ * 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.consul.cloud;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.cloud.ServiceDiscovery;
+import org.apache.camel.cloud.ServiceDiscoveryFactory;
+import org.apache.camel.component.consul.ConsulConfiguration;
+import org.apache.camel.util.jsse.SSLContextParameters;
+
+public class ConsulServiceDiscoveryFactory implements ServiceDiscoveryFactory {
+    private final ConsulConfiguration configuration;
+
+    public ConsulServiceDiscoveryFactory() {
+        this.configuration = new ConsulConfiguration();
+    }
+
+    // *************************************************************************
+    // Properties
+    // *************************************************************************
+
+    public String getUrl() {
+        return configuration.getUrl();
+    }
+
+    public void setUrl(String url) {
+        configuration.setUrl(url);
+    }
+
+    public String getDc() {
+        return configuration.getDc();
+    }
+
+    public void setDc(String dc) {
+        configuration.setDc(dc);
+    }
+
+    public SSLContextParameters getSslContextParameters() {
+        return configuration.getSslContextParameters();
+    }
+
+    public void setSslContextParameters(SSLContextParameters sslContextParameters) {
+        configuration.setSslContextParameters(sslContextParameters);
+    }
+
+    public String getAclToken() {
+        return configuration.getAclToken();
+    }
+
+    public void setAclToken(String aclToken) {
+        configuration.setAclToken(aclToken);
+    }
+
+    public String getUserName() {
+        return configuration.getUserName();
+    }
+
+    public void setUserName(String userName) {
+        configuration.setUserName(userName);
+    }
+
+    public String getPassword() {
+        return configuration.getPassword();
+    }
+
+    public void setPassword(String password) {
+        configuration.setPassword(password);
+    }
+
+    public Long getConnectTimeoutMillis() {
+        return configuration.getConnectTimeoutMillis();
+    }
+
+    public void setConnectTimeoutMillis(Long connectTimeoutMillis) {
+        configuration.setConnectTimeoutMillis(connectTimeoutMillis);
+    }
+
+    public Long getReadTimeoutMillis() {
+        return configuration.getReadTimeoutMillis();
+    }
+
+    public void setReadTimeoutMillis(Long readTimeoutMillis) {
+        configuration.setReadTimeoutMillis(readTimeoutMillis);
+    }
+
+    public Long getWriteTimeoutMillis() {
+        return configuration.getWriteTimeoutMillis();
+    }
+
+    public void setWriteTimeoutMillis(Long writeTimeoutMillis) {
+        configuration.setWriteTimeoutMillis(writeTimeoutMillis);
+    }
+
+    public Integer getBlockSeconds() {
+        return configuration.getBlockSeconds();
+    }
+
+    public void setBlockSeconds(Integer blockSeconds) {
+        configuration.setBlockSeconds(blockSeconds);
+    }
+
+    // *************************************************************************
+    // Factory
+    // *************************************************************************
+
+    @Override
+    public ServiceDiscovery newInstance(CamelContext camelContext) throws Exception {
+        return new ConsulServiceDiscovery(configuration);
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/components/camel-consul/src/main/java/org/apache/camel/component/consul/processor/remote/ConsulServiceCallProcessor.java
----------------------------------------------------------------------
diff --git a/components/camel-consul/src/main/java/org/apache/camel/component/consul/processor/remote/ConsulServiceCallProcessor.java b/components/camel-consul/src/main/java/org/apache/camel/component/consul/processor/remote/ConsulServiceCallProcessor.java
deleted file mode 100644
index 7d98a8e..0000000
--- a/components/camel-consul/src/main/java/org/apache/camel/component/consul/processor/remote/ConsulServiceCallProcessor.java
+++ /dev/null
@@ -1,43 +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.consul.processor.remote;
-
-import org.apache.camel.ExchangePattern;
-import org.apache.camel.component.consul.ConsulConfiguration;
-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 Consul implementation of the ServiceCall EIP.
- */
-public class ConsulServiceCallProcessor extends DefaultServiceCallProcessor<ServiceCallServer> {
-    public ConsulServiceCallProcessor(String name, String scheme, String uri, ExchangePattern exchangePattern, ConsulConfiguration conf) {
-        super(name, scheme, uri, exchangePattern);
-    }
-
-    @Override
-    public void setServerListStrategy(ServiceCallServerListStrategy<ServiceCallServer> serverListStrategy) {
-        if (!(serverListStrategy instanceof ConsulServiceCallServerListStrategy)) {
-            throw new IllegalArgumentException("ServerListStrategy is not an instance of ConsulServiceCallServerListStrategy");
-        }
-
-        super.setServerListStrategy(serverListStrategy);
-    }
-}

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/components/camel-consul/src/main/java/org/apache/camel/component/consul/processor/remote/ConsulServiceCallProcessorFactory.java
----------------------------------------------------------------------
diff --git a/components/camel-consul/src/main/java/org/apache/camel/component/consul/processor/remote/ConsulServiceCallProcessorFactory.java b/components/camel-consul/src/main/java/org/apache/camel/component/consul/processor/remote/ConsulServiceCallProcessorFactory.java
deleted file mode 100644
index 064fac2..0000000
--- a/components/camel-consul/src/main/java/org/apache/camel/component/consul/processor/remote/ConsulServiceCallProcessorFactory.java
+++ /dev/null
@@ -1,67 +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.consul.processor.remote;
-
-import java.util.Map;
-import java.util.Optional;
-
-import org.apache.camel.ExchangePattern;
-import org.apache.camel.component.consul.ConsulConfiguration;
-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 Consul implementation of the ServiceCall EIP.
- */
-public class ConsulServiceCallProcessorFactory extends DefaultServiceCallProcessorFactory<ConsulConfiguration, ServiceCallServer> {
-    @Override
-    protected ConsulConfiguration createConfiguration(RouteContext routeContext) throws Exception {
-        return new ConsulConfiguration(routeContext.getCamelContext());
-    }
-
-    @Override
-    protected DefaultServiceCallProcessor createProcessor(
-            String name,
-            String component,
-            String uri,
-            ExchangePattern mep,
-            ConsulConfiguration conf,
-            Map<String, String> properties) throws Exception {
-
-        return new ConsulServiceCallProcessor(name, component, uri, mep, conf);
-    }
-
-    @Override
-    protected Optional<ServiceCallServerListStrategy> builtInServerListStrategy(ConsulConfiguration conf, String name) throws Exception {
-        ServiceCallServerListStrategy strategy = null;
-        if (ObjectHelper.equal("ondemand", name, true)) {
-            strategy = new ConsulServiceCallServerListStrategies.OnDemand(conf);
-        }
-
-        return Optional.ofNullable(strategy);
-    }
-
-    @Override
-    protected ServiceCallServerListStrategy<ServiceCallServer> createDefaultServerListStrategy(ConsulConfiguration conf) throws Exception {
-        return new ConsulServiceCallServerListStrategies.OnDemand(conf);
-    }
-}

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/components/camel-consul/src/main/java/org/apache/camel/component/consul/processor/remote/ConsulServiceCallServerListStrategies.java
----------------------------------------------------------------------
diff --git a/components/camel-consul/src/main/java/org/apache/camel/component/consul/processor/remote/ConsulServiceCallServerListStrategies.java b/components/camel-consul/src/main/java/org/apache/camel/component/consul/processor/remote/ConsulServiceCallServerListStrategies.java
deleted file mode 100644
index 81f95ff..0000000
--- a/components/camel-consul/src/main/java/org/apache/camel/component/consul/processor/remote/ConsulServiceCallServerListStrategies.java
+++ /dev/null
@@ -1,65 +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.consul.processor.remote;
-
-import java.util.List;
-import java.util.stream.Collectors;
-
-import com.orbitz.consul.model.catalog.CatalogService;
-import com.orbitz.consul.model.health.ServiceHealth;
-import org.apache.camel.component.consul.ConsulConfiguration;
-import org.apache.camel.spi.ServiceCallServer;
-
-public final class ConsulServiceCallServerListStrategies {
-    private ConsulServiceCallServerListStrategies() {
-    }
-
-    public static final class OnDemand extends ConsulServiceCallServerListStrategy {
-        public OnDemand(ConsulConfiguration configuration) throws Exception {
-            super(configuration);
-        }
-
-        @Override
-        public List<ServiceCallServer> getUpdatedListOfServers(String name) {
-            List<CatalogService> services = getCatalogClient()
-                .getService(name, getCatalogOptions())
-                .getResponse();
-
-            List<ServiceHealth> healths = getHealthClient()
-                .getAllServiceInstances(name, getCatalogOptions())
-                .getResponse();
-
-            return services.stream()
-                .filter(service -> !hasFailingChecks(service, healths))
-                .map(this::newServer)
-                .collect(Collectors.toList());
-        }
-
-        @Override
-        public String toString() {
-            return "OnDemand";
-        }
-    }
-
-    // *************************************************************************
-    // Helpers
-    // *************************************************************************
-
-    public static ConsulServiceCallServerListStrategy onDemand(ConsulConfiguration configuration) throws Exception {
-        return new OnDemand(configuration);
-    }
-}

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/components/camel-consul/src/main/java/org/apache/camel/component/consul/processor/remote/ConsulServiceCallServerListStrategy.java
----------------------------------------------------------------------
diff --git a/components/camel-consul/src/main/java/org/apache/camel/component/consul/processor/remote/ConsulServiceCallServerListStrategy.java b/components/camel-consul/src/main/java/org/apache/camel/component/consul/processor/remote/ConsulServiceCallServerListStrategy.java
deleted file mode 100644
index 116b2fc..0000000
--- a/components/camel-consul/src/main/java/org/apache/camel/component/consul/processor/remote/ConsulServiceCallServerListStrategy.java
+++ /dev/null
@@ -1,128 +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.consul.processor.remote;
-
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import com.orbitz.consul.CatalogClient;
-import com.orbitz.consul.Consul;
-import com.orbitz.consul.HealthClient;
-import com.orbitz.consul.model.catalog.CatalogService;
-import com.orbitz.consul.model.health.HealthCheck;
-import com.orbitz.consul.model.health.ServiceHealth;
-import com.orbitz.consul.option.CatalogOptions;
-import com.orbitz.consul.option.ImmutableCatalogOptions;
-import org.apache.camel.component.consul.ConsulConfiguration;
-import org.apache.camel.impl.remote.DefaultServiceCallServer;
-import org.apache.camel.impl.remote.DefaultServiceCallServerListStrategy;
-import org.apache.camel.spi.ServiceCallServer;
-import org.apache.camel.util.ObjectHelper;
-
-import static org.apache.camel.util.ObjectHelper.ifNotEmpty;
-
-
-abstract class ConsulServiceCallServerListStrategy extends DefaultServiceCallServerListStrategy<ServiceCallServer> {
-    private final Consul client;
-    private final CatalogOptions catalogOptions;
-
-    ConsulServiceCallServerListStrategy(ConsulConfiguration configuration) throws Exception {
-        this.client = configuration.createConsulClient();
-
-        ImmutableCatalogOptions.Builder builder = ImmutableCatalogOptions.builder();
-        if (ObjectHelper.isNotEmpty(configuration.getDc())) {
-            builder.datacenter(configuration.getDc());
-        }
-        if (ObjectHelper.isNotEmpty(configuration.getTags())) {
-            configuration.getTags().forEach(builder::tag);
-        }
-
-        catalogOptions = builder.build();
-    }
-
-    @Override
-    public String toString() {
-        return "ConsulServiceCallServerListStrategy";
-    }
-
-    // *************************
-    // Getter
-    // *************************
-
-    protected Consul getClient() {
-        return client;
-    }
-
-    protected CatalogClient getCatalogClient() {
-        return client.catalogClient();
-    }
-
-    protected HealthClient getHealthClient() {
-        return client.healthClient();
-    }
-
-    protected CatalogOptions getCatalogOptions() {
-        return catalogOptions;
-    }
-
-    // *************************
-    // Helpers
-    // *************************
-
-    protected boolean isNotHealthy(HealthCheck check) {
-        final String status = check.getStatus();
-        return status != null && !status.equalsIgnoreCase("passing");
-    }
-
-    protected boolean isNotHealthy(ServiceHealth health) {
-        return health.getChecks().stream().anyMatch(this::isNotHealthy);
-    }
-
-    protected boolean isCheckOnService(ServiceHealth check, CatalogService service) {
-        return check.getService().getService().equalsIgnoreCase(service.getServiceName());
-    }
-
-    protected boolean hasFailingChecks(CatalogService service, List<ServiceHealth> healths) {
-        return healths.stream().anyMatch(health -> isCheckOnService(health, service) && isNotHealthy(health));
-    }
-
-    protected ServiceCallServer newServer(CatalogService service) {
-        Map<String, String> meta = new HashMap<>();
-        ifNotEmpty(service.getServiceId(), val -> meta.put("service_id", val));
-        ifNotEmpty(service.getNode(), val -> meta.put("node", val));
-        ifNotEmpty(service.getServiceName(), val -> meta.put("service_name", val));
-
-        List<String> tags = service.getServiceTags();
-        if (tags != null) {
-            for (String tag : service.getServiceTags()) {
-                String[] items = tag.split("=");
-                if (items.length == 1) {
-                    meta.put(items[0], items[0]);
-                } else if (items.length == 2) {
-                    meta.put(items[0], items[1]);
-                }
-            }
-        }
-
-        return new DefaultServiceCallServer(
-            service.getServiceAddress(),
-            service.getServicePort(),
-            meta
-        );
-    }
-}

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/components/camel-consul/src/main/resources/META-INF/services/org/apache/camel/cloud/consul-service-discovery
----------------------------------------------------------------------
diff --git a/components/camel-consul/src/main/resources/META-INF/services/org/apache/camel/cloud/consul-service-discovery b/components/camel-consul/src/main/resources/META-INF/services/org/apache/camel/cloud/consul-service-discovery
new file mode 100644
index 0000000..b8019a2
--- /dev/null
+++ b/components/camel-consul/src/main/resources/META-INF/services/org/apache/camel/cloud/consul-service-discovery
@@ -0,0 +1,17 @@
+#
+# 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.consul.cloud.ConsulServiceDiscoveryFactory

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/components/camel-consul/src/main/resources/META-INF/services/org/apache/camel/model/ServiceCallDefinition
----------------------------------------------------------------------
diff --git a/components/camel-consul/src/main/resources/META-INF/services/org/apache/camel/model/ServiceCallDefinition b/components/camel-consul/src/main/resources/META-INF/services/org/apache/camel/model/ServiceCallDefinition
deleted file mode 100644
index 3082d38..0000000
--- a/components/camel-consul/src/main/resources/META-INF/services/org/apache/camel/model/ServiceCallDefinition
+++ /dev/null
@@ -1,18 +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.
-#
-
-class=org.apache.camel.component.consul.processor.remote.ConsulServiceCallProcessorFactory

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/components/camel-consul/src/test/java/org/apache/camel/component/consul/cloud/ConsulServiceCallRouteTest.java
----------------------------------------------------------------------
diff --git a/components/camel-consul/src/test/java/org/apache/camel/component/consul/cloud/ConsulServiceCallRouteTest.java b/components/camel-consul/src/test/java/org/apache/camel/component/consul/cloud/ConsulServiceCallRouteTest.java
new file mode 100644
index 0000000..c32ec3e
--- /dev/null
+++ b/components/camel-consul/src/test/java/org/apache/camel/component/consul/cloud/ConsulServiceCallRouteTest.java
@@ -0,0 +1,118 @@
+/**
+ * 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.consul.cloud;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import com.orbitz.consul.AgentClient;
+import com.orbitz.consul.model.agent.ImmutableRegistration;
+import com.orbitz.consul.model.agent.Registration;
+import org.apache.camel.RoutesBuilder;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.cloud.ServiceDiscovery;
+import org.apache.camel.component.consul.ConsulConfiguration;
+import org.apache.camel.component.consul.ConsulTestSupport;
+import org.junit.Test;
+
+public class ConsulServiceCallRouteTest extends ConsulTestSupport {
+    private static final String SERVICE_NAME = "http-service";
+    private static final int SERVICE_COUNT = 5;
+    private static final int SERVICE_PORT_BASE = 8080;
+
+    private AgentClient client;
+    private List<Registration> registrations;
+    private List<String> expectedBodies;
+
+    // *************************************************************************
+    // Setup / tear down
+    // *************************************************************************
+
+    @Override
+    protected void doPreSetup() throws Exception {
+        client = getConsul().agentClient();
+
+        registrations = new ArrayList<>(SERVICE_COUNT);
+        expectedBodies = new ArrayList<>(SERVICE_COUNT);
+
+        for (int i = 0; i < SERVICE_COUNT; i++) {
+            Registration r = ImmutableRegistration.builder()
+                .id("service-" + i)
+                .name(SERVICE_NAME)
+                .address("127.0.0.1")
+                .port(SERVICE_PORT_BASE + i)
+                .build();
+
+            client.register(r);
+
+            registrations.add(r);
+            expectedBodies.add("ping on " + r.getPort().get());
+        }
+    }
+
+    @Override
+    public void tearDown() throws Exception {
+        super.tearDown();
+
+
+        registrations.forEach(r -> client.deregister(r.getId()));
+    }
+
+    // *************************************************************************
+    // Test
+    // *************************************************************************
+
+    @Test
+    public void testServiceCall() throws Exception {
+        getMockEndpoint("mock:result").expectedMessageCount(SERVICE_COUNT);
+        getMockEndpoint("mock:result").expectedBodiesReceivedInAnyOrder(expectedBodies);
+
+        registrations.forEach(r -> template.sendBody("direct:start", "ping"));
+
+        assertMockEndpointsSatisfied();
+    }
+
+    // *************************************************************************
+    // Route
+    // *************************************************************************
+
+    @Override
+    protected RoutesBuilder createRouteBuilder() throws Exception {
+        return new RouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                ConsulConfiguration configuration = new ConsulConfiguration(null);
+                ServiceDiscovery discovery = new ConsulServiceDiscovery(configuration);
+
+                from("direct:start")
+                    .serviceCall()
+                        .name(SERVICE_NAME)
+                        .component("http")
+                        .serviceDiscovery(discovery)
+                        .end()
+                    .to("log:org.apache.camel.component.consul.processor.service?level=INFO&showAll=true&multiline=true")
+                    .to("mock:result");
+
+                registrations.forEach(r ->
+                    fromF("jetty:http://%s:%d", r.getAddress().get(), r.getPort().get())
+                        .transform().simple("${in.body} on " + r.getPort().get())
+                );
+            }
+        };
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/components/camel-consul/src/test/java/org/apache/camel/component/consul/cloud/ConsulServiceDiscoveryTest.java
----------------------------------------------------------------------
diff --git a/components/camel-consul/src/test/java/org/apache/camel/component/consul/cloud/ConsulServiceDiscoveryTest.java b/components/camel-consul/src/test/java/org/apache/camel/component/consul/cloud/ConsulServiceDiscoveryTest.java
new file mode 100644
index 0000000..8046f1d
--- /dev/null
+++ b/components/camel-consul/src/test/java/org/apache/camel/component/consul/cloud/ConsulServiceDiscoveryTest.java
@@ -0,0 +1,90 @@
+/**
+ * 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.consul.cloud;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import com.orbitz.consul.AgentClient;
+import com.orbitz.consul.Consul;
+import com.orbitz.consul.model.agent.ImmutableRegistration;
+import com.orbitz.consul.model.agent.Registration;
+import org.apache.camel.cloud.ServiceDefinition;
+import org.apache.camel.cloud.ServiceDiscovery;
+import org.apache.camel.component.consul.ConsulConfiguration;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+public class ConsulServiceDiscoveryTest {
+    private AgentClient client;
+    private List<Registration> registrations;
+
+    @Before
+    public void setUp() throws Exception {
+        client = Consul.builder().build().agentClient();
+        registrations = new ArrayList<>(3);
+
+        for (int i = 0; i < 3; i++) {
+            Registration r = ImmutableRegistration.builder()
+                .id("service-" + i)
+                .name("my-service")
+                .address("127.0.0.1")
+                .addTags("a-tag")
+                .addTags("key1=value1")
+                .addTags("key2=value2")
+                .port(9000 + i)
+                .build();
+
+            client.register(r);
+            registrations.add(r);
+        }
+    }
+
+    @After
+    public void tearDown() throws Exception {
+        registrations.forEach(r -> client.deregister(r.getId()));
+    }
+
+    // *************************************************************************
+    // Test
+    // *************************************************************************
+
+    @Test
+    public void testServiceDiscovery() throws Exception {
+        ConsulConfiguration configuration = new ConsulConfiguration(null);
+        ServiceDiscovery discovery = new ConsulServiceDiscovery(configuration);
+
+        List<ServiceDefinition> services = discovery.getUpdatedListOfServices("my-service");
+        assertNotNull(services);
+        assertEquals(3, services.size());
+
+        for (ServiceDefinition service : services) {
+            assertFalse(service.getMetadata().isEmpty());
+            assertTrue(service.getMetadata().containsKey("service_name"));
+            assertTrue(service.getMetadata().containsKey("service_id"));
+            assertTrue(service.getMetadata().containsKey("a-tag"));
+            assertTrue(service.getMetadata().containsKey("key1"));
+            assertTrue(service.getMetadata().containsKey("key2"));
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/components/camel-consul/src/test/java/org/apache/camel/component/consul/cloud/SpringConsulDefaultServiceCallRouteTest.java
----------------------------------------------------------------------
diff --git a/components/camel-consul/src/test/java/org/apache/camel/component/consul/cloud/SpringConsulDefaultServiceCallRouteTest.java b/components/camel-consul/src/test/java/org/apache/camel/component/consul/cloud/SpringConsulDefaultServiceCallRouteTest.java
new file mode 100644
index 0000000..05b28d7
--- /dev/null
+++ b/components/camel-consul/src/test/java/org/apache/camel/component/consul/cloud/SpringConsulDefaultServiceCallRouteTest.java
@@ -0,0 +1,28 @@
+/**
+ * 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.consul.cloud;
+
+import org.springframework.context.support.AbstractApplicationContext;
+import org.springframework.context.support.ClassPathXmlApplicationContext;
+
+public class SpringConsulDefaultServiceCallRouteTest extends SpringConsulServiceCallRouteTest {
+    @Override
+    protected AbstractApplicationContext createApplicationContext() {
+        return new ClassPathXmlApplicationContext("org/apache/camel/component/consul/cloud/SpringConsulDefaultServiceCallRouteTest.xml");
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/components/camel-consul/src/test/java/org/apache/camel/component/consul/cloud/SpringConsulRibbonServiceCallRouteTest.java
----------------------------------------------------------------------
diff --git a/components/camel-consul/src/test/java/org/apache/camel/component/consul/cloud/SpringConsulRibbonServiceCallRouteTest.java b/components/camel-consul/src/test/java/org/apache/camel/component/consul/cloud/SpringConsulRibbonServiceCallRouteTest.java
new file mode 100644
index 0000000..70eebfb
--- /dev/null
+++ b/components/camel-consul/src/test/java/org/apache/camel/component/consul/cloud/SpringConsulRibbonServiceCallRouteTest.java
@@ -0,0 +1,28 @@
+/**
+ * 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.consul.cloud;
+
+import org.springframework.context.support.AbstractApplicationContext;
+import org.springframework.context.support.ClassPathXmlApplicationContext;
+
+public class SpringConsulRibbonServiceCallRouteTest extends SpringConsulServiceCallRouteTest {
+    @Override
+    protected AbstractApplicationContext createApplicationContext() {
+        return new ClassPathXmlApplicationContext("org/apache/camel/component/consul/cloud/SpringConsulRibbonServiceCallRouteTest.xml");
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/components/camel-consul/src/test/java/org/apache/camel/component/consul/cloud/SpringConsulServiceCallRouteTest.java
----------------------------------------------------------------------
diff --git a/components/camel-consul/src/test/java/org/apache/camel/component/consul/cloud/SpringConsulServiceCallRouteTest.java b/components/camel-consul/src/test/java/org/apache/camel/component/consul/cloud/SpringConsulServiceCallRouteTest.java
new file mode 100644
index 0000000..81517be
--- /dev/null
+++ b/components/camel-consul/src/test/java/org/apache/camel/component/consul/cloud/SpringConsulServiceCallRouteTest.java
@@ -0,0 +1,96 @@
+/**
+ * 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.consul.cloud;
+
+import java.util.Arrays;
+import java.util.List;
+
+import com.orbitz.consul.AgentClient;
+import com.orbitz.consul.Consul;
+import com.orbitz.consul.model.agent.ImmutableRegistration;
+import com.orbitz.consul.model.agent.Registration;
+import org.apache.camel.test.spring.CamelSpringTestSupport;
+import org.junit.Test;
+
+public abstract class SpringConsulServiceCallRouteTest extends CamelSpringTestSupport {
+    private AgentClient client;
+    private List<Registration> registrations;
+
+    // *************************************************************************
+    // Setup / tear down
+    // *************************************************************************
+
+    @Override
+    public void doPreSetup() throws Exception {
+        this.client = Consul.builder().build().agentClient();
+        this.registrations = Arrays.asList(
+            ImmutableRegistration.builder()
+                .id("service-1")
+                .name("http-service-1")
+                .address("127.0.0.1")
+                .port(9091)
+                .build(),
+            ImmutableRegistration.builder()
+                .id("service-2")
+                .name("http-service-1")
+                .address("127.0.0.1")
+                .port(9092)
+                .build(),
+            ImmutableRegistration.builder()
+                .id("service-3")
+                .name("http-service-2")
+                .address("127.0.0.1")
+                .port(9093)
+                .build(),
+            ImmutableRegistration.builder()
+                .id("service-4")
+                .name("http-service-2")
+                .address("127.0.0.1")
+                .port(9094)
+                .build()
+        );
+
+        this.registrations.forEach(client::register);
+        super.doPreSetup();
+    }
+
+    @Override
+    public void tearDown() throws Exception {
+        super.tearDown();
+        registrations.forEach(r -> client.deregister(r.getId()));
+    }
+
+    // *************************************************************************
+    // Test
+    // *************************************************************************
+
+    @Test
+    public void testServiceCall() throws Exception {
+        getMockEndpoint("mock:result-1").expectedMessageCount(2);
+        getMockEndpoint("mock:result-1").expectedBodiesReceivedInAnyOrder("service-1 9091", "service-1 9092");
+        getMockEndpoint("mock:result-2").expectedMessageCount(2);
+        getMockEndpoint("mock:result-2").expectedBodiesReceivedInAnyOrder("service-2 9093", "service-2 9094");
+
+        template.sendBody("direct:start", "service-1");
+        template.sendBody("direct:start", "service-1");
+        template.sendBody("direct:start", "service-2");
+        template.sendBody("direct:start", "service-2");
+
+        assertMockEndpointsSatisfied();
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/components/camel-consul/src/test/java/org/apache/camel/component/consul/policy/ConsulRoutePolicyMain.java
----------------------------------------------------------------------
diff --git a/components/camel-consul/src/test/java/org/apache/camel/component/consul/policy/ConsulRoutePolicyMain.java b/components/camel-consul/src/test/java/org/apache/camel/component/consul/policy/ConsulRoutePolicyMain.java
index d5831c1..447f5b3 100644
--- a/components/camel-consul/src/test/java/org/apache/camel/component/consul/policy/ConsulRoutePolicyMain.java
+++ b/components/camel-consul/src/test/java/org/apache/camel/component/consul/policy/ConsulRoutePolicyMain.java
@@ -14,7 +14,6 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-
 package org.apache.camel.component.consul.policy;
 
 import org.apache.camel.builder.RouteBuilder;

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/components/camel-consul/src/test/java/org/apache/camel/component/consul/processor/remote/ConsulServiceCallRouteTest.java
----------------------------------------------------------------------
diff --git a/components/camel-consul/src/test/java/org/apache/camel/component/consul/processor/remote/ConsulServiceCallRouteTest.java b/components/camel-consul/src/test/java/org/apache/camel/component/consul/processor/remote/ConsulServiceCallRouteTest.java
deleted file mode 100644
index a76580b..0000000
--- a/components/camel-consul/src/test/java/org/apache/camel/component/consul/processor/remote/ConsulServiceCallRouteTest.java
+++ /dev/null
@@ -1,114 +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.consul.processor.remote;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import com.orbitz.consul.AgentClient;
-import com.orbitz.consul.model.agent.ImmutableRegistration;
-import com.orbitz.consul.model.agent.Registration;
-import org.apache.camel.RoutesBuilder;
-import org.apache.camel.builder.RouteBuilder;
-import org.apache.camel.component.consul.ConsulTestSupport;
-import org.junit.Ignore;
-import org.junit.Test;
-
-@Ignore("A consul server is needed for this test ")
-public class ConsulServiceCallRouteTest extends ConsulTestSupport {
-    private static final String SERVICE_NAME = "http-service";
-    private static final int SERVICE_COUNT = 5;
-    private static final int SERVICE_PORT_BASE = 8080;
-
-    private AgentClient client;
-    private List<Registration> registrations;
-    private List<String> expectedBodies;
-
-    // *************************************************************************
-    // Setup / tear down
-    // *************************************************************************
-
-    @Override
-    protected void doPreSetup() throws Exception {
-        client = getConsul().agentClient();
-
-        registrations = new ArrayList<>(SERVICE_COUNT);
-        expectedBodies = new ArrayList<>(SERVICE_COUNT);
-
-        for (int i = 0; i < SERVICE_COUNT; i++) {
-            Registration r = ImmutableRegistration.builder()
-                .id("service-" + i)
-                .name(SERVICE_NAME)
-                .address("127.0.0.1")
-                .port(SERVICE_PORT_BASE + i)
-                .build();
-
-            client.register(r);
-
-            registrations.add(r);
-            expectedBodies.add("ping on " + r.getPort().get());
-        }
-    }
-
-    @Override
-    public void tearDown() throws Exception {
-        super.tearDown();
-        registrations.forEach(r -> client.deregister(r.getId()));
-    }
-
-    // *************************************************************************
-    // Test
-    // *************************************************************************
-
-    @Test
-    public void testServiceCall() throws Exception {
-        getMockEndpoint("mock:result").expectedMessageCount(SERVICE_COUNT);
-        getMockEndpoint("mock:result").expectedBodiesReceivedInAnyOrder(expectedBodies);
-
-        registrations.forEach(r -> 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)
-                        .consulConfiguration()
-                            .component("http")
-                            .loadBalancer("roundrobin")
-                            .serverListStrategy("ondemand")
-                        .end()
-                    .to("log:org.apache.camel.component.consul.processor.service?level=INFO&showAll=true&multiline=true")
-                    .to("mock:result");
-
-                registrations.forEach(r ->
-                    fromF("jetty:http://%s:%d", r.getAddress().get(), r.getPort().get())
-                        .transform().simple("${in.body} on " + r.getPort().get())
-                );
-            }
-        };
-    }
-}

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/components/camel-consul/src/test/java/org/apache/camel/component/consul/processor/remote/ConsulServiceCallServerListStrategiesTest.java
----------------------------------------------------------------------
diff --git a/components/camel-consul/src/test/java/org/apache/camel/component/consul/processor/remote/ConsulServiceCallServerListStrategiesTest.java b/components/camel-consul/src/test/java/org/apache/camel/component/consul/processor/remote/ConsulServiceCallServerListStrategiesTest.java
deleted file mode 100644
index 65738e0..0000000
--- a/components/camel-consul/src/test/java/org/apache/camel/component/consul/processor/remote/ConsulServiceCallServerListStrategiesTest.java
+++ /dev/null
@@ -1,92 +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.consul.processor.remote;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import com.orbitz.consul.AgentClient;
-import com.orbitz.consul.Consul;
-import com.orbitz.consul.model.agent.ImmutableRegistration;
-import com.orbitz.consul.model.agent.Registration;
-import org.apache.camel.component.consul.ConsulConfiguration;
-import org.apache.camel.spi.ServiceCallServer;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Ignore;
-import org.junit.Test;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-
-@Ignore("A consul server is needed for this test ")
-public class ConsulServiceCallServerListStrategiesTest {
-    private AgentClient client;
-    private List<Registration> registrations;
-
-    @Before
-    public void setUp() throws Exception {
-        client = Consul.builder().build().agentClient();
-        registrations = new ArrayList<>(3);
-
-        for (int i = 0; i < 3; i++) {
-            Registration r = ImmutableRegistration.builder()
-                .id("service-" + i)
-                .name("my-service")
-                .address("127.0.0.1")
-                .addTags("a-tag")
-                .addTags("key1=value1")
-                .addTags("key2=value2")
-                .port(9000 + i)
-                .build();
-
-            client.register(r);
-            registrations.add(r);
-        }
-    }
-
-    @After
-    public void tearDown() throws Exception {
-        registrations.forEach(r -> client.deregister(r.getId()));
-    }
-
-    // *************************************************************************
-    // Test
-    // *************************************************************************
-
-    @Test
-    public void testOnDemand() throws Exception {
-        ConsulConfiguration configuration = new ConsulConfiguration(null);
-        ConsulServiceCallServerListStrategy strategy = ConsulServiceCallServerListStrategies.onDemand(configuration);
-
-        List<ServiceCallServer> servers = strategy.getUpdatedListOfServers("my-service");
-        assertNotNull(servers);
-        assertEquals(3, servers.size());
-
-        for (ServiceCallServer server : servers) {
-            assertFalse(server.getMetadata().isEmpty());
-            assertTrue(server.getMetadata().containsKey("service_name"));
-            assertTrue(server.getMetadata().containsKey("service_id"));
-            assertTrue(server.getMetadata().containsKey("a-tag"));
-            assertTrue(server.getMetadata().containsKey("key1"));
-            assertTrue(server.getMetadata().containsKey("key2"));
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/components/camel-consul/src/test/resources/org/apache/camel/component/consul/cloud/SpringConsulDefaultServiceCallRouteTest.xml
----------------------------------------------------------------------
diff --git a/components/camel-consul/src/test/resources/org/apache/camel/component/consul/cloud/SpringConsulDefaultServiceCallRouteTest.xml b/components/camel-consul/src/test/resources/org/apache/camel/component/consul/cloud/SpringConsulDefaultServiceCallRouteTest.xml
new file mode 100644
index 0000000..c4d0950
--- /dev/null
+++ b/components/camel-consul/src/test/resources/org/apache/camel/component/consul/cloud/SpringConsulDefaultServiceCallRouteTest.xml
@@ -0,0 +1,87 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ 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.
+  -->
+<beans xmlns="http://www.springframework.org/schema/beans"
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xsi:schemaLocation="
+         http://www.springframework.org/schema/beans
+         http://www.springframework.org/schema/beans/spring-beans.xsd
+         http://camel.apache.org/schema/spring
+         http://camel.apache.org/schema/spring/camel-spring.xsd">
+
+  <camelContext xmlns="http://camel.apache.org/schema/spring">
+
+    <!-- shared config -->
+    <serviceCallConfiguration id="shared-config" serviceChooserRef="round-robin">
+      <consulServiceDiscovery readTimeoutMillis="1444" url="http://localhost:8500"/>
+    </serviceCallConfiguration>
+
+    <route>
+      <from uri="direct:start"/>
+      <choice>
+        <when>
+          <simple>${body} == 'service-1'</simple>
+          <serviceCall name="http-service-1">
+            <consulServiceDiscovery readTimeoutMillis="1222" url="http://localhost:8500"/>
+          </serviceCall>
+          <to uri="mock:result-1"/>
+        </when>
+        <when>
+          <simple>${body} == 'service-2'</simple>
+          <serviceCall name="http-service-2">
+            <consulServiceDiscovery readTimeoutMillis="1333" url="http://localhost:8500"/>
+          </serviceCall>
+          <to uri="mock:result-2"/>
+        </when>
+        <when>
+          <simple>${body} == 'service-3'</simple>
+          <serviceCall name="http-service-3" configurationRef="shared-config"/>
+          <to uri="mock:result-2"/>
+        </when>
+      </choice>
+    </route>
+
+    <route>
+      <from uri="jetty:http://localhost:9091"/>
+      <transform>
+        <simple>${body} 9091</simple>
+      </transform>
+    </route>
+
+    <route>
+      <from uri="jetty:http://localhost:9092"/>
+      <transform>
+        <simple>${body} 9092</simple>
+      </transform>
+    </route>
+
+    <route>
+      <from uri="jetty:http://localhost:9093"/>
+      <transform>
+        <simple>${body} 9093</simple>
+      </transform>
+    </route>
+
+    <route>
+      <from uri="jetty:http://localhost:9094"/>
+      <transform>
+        <simple>${body} 9094</simple>
+      </transform>
+    </route>
+  </camelContext>
+
+</beans>

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/components/camel-consul/src/test/resources/org/apache/camel/component/consul/cloud/SpringConsulRibbonServiceCallRouteTest.xml
----------------------------------------------------------------------
diff --git a/components/camel-consul/src/test/resources/org/apache/camel/component/consul/cloud/SpringConsulRibbonServiceCallRouteTest.xml b/components/camel-consul/src/test/resources/org/apache/camel/component/consul/cloud/SpringConsulRibbonServiceCallRouteTest.xml
new file mode 100644
index 0000000..ac1b642
--- /dev/null
+++ b/components/camel-consul/src/test/resources/org/apache/camel/component/consul/cloud/SpringConsulRibbonServiceCallRouteTest.xml
@@ -0,0 +1,84 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ 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.
+  -->
+<beans xmlns="http://www.springframework.org/schema/beans"
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xsi:schemaLocation="
+         http://www.springframework.org/schema/beans
+         http://www.springframework.org/schema/beans/spring-beans.xsd
+         http://camel.apache.org/schema/spring
+         http://camel.apache.org/schema/spring/camel-spring.xsd">
+
+  <camelContext xmlns="http://camel.apache.org/schema/spring">
+    <!--
+    <serviceCallConfiguration id="service-2">
+      <consulServiceDiscovery"/>
+    </serviceCallConfiguration>
+    -->
+
+    <route>
+      <from uri="direct:start"/>
+      <choice>
+        <when>
+          <simple>${body} == 'service-1'</simple>
+          <serviceCall name="http-service-1">
+            <consulServiceDiscovery readTimeoutMillis="1222" url="http://localhost:8500"/>
+            <ribbonLoadBalancer/>
+          </serviceCall>
+          <to uri="mock:result-1"/>
+        </when>
+        <when>
+          <simple>${body} == 'service-2'</simple>
+          <serviceCall name="http-service-2">
+            <consulServiceDiscovery readTimeoutMillis="1333" url="http://localhost:8500"/>
+            <ribbonLoadBalancer/>
+          </serviceCall>
+          <to uri="mock:result-2"/>
+        </when>
+      </choice>
+    </route>
+
+    <route>
+      <from uri="jetty:http://localhost:9091"/>
+      <transform>
+        <simple>${body} 9091</simple>
+      </transform>
+    </route>
+
+    <route>
+      <from uri="jetty:http://localhost:9092"/>
+      <transform>
+        <simple>${body} 9092</simple>
+      </transform>
+    </route>
+
+    <route>
+      <from uri="jetty:http://localhost:9093"/>
+      <transform>
+        <simple>${body} 9093</simple>
+      </transform>
+    </route>
+
+    <route>
+      <from uri="jetty:http://localhost:9094"/>
+      <transform>
+        <simple>${body} 9094</simple>
+      </transform>
+    </route>
+  </camelContext>
+
+</beans>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/components/camel-core-xml/src/main/java/org/apache/camel/core/xml/AbstractCamelContextFactoryBean.java
----------------------------------------------------------------------
diff --git a/components/camel-core-xml/src/main/java/org/apache/camel/core/xml/AbstractCamelContextFactoryBean.java b/components/camel-core-xml/src/main/java/org/apache/camel/core/xml/AbstractCamelContextFactoryBean.java
index a4bb342..a5ce3f7 100644
--- a/components/camel-core-xml/src/main/java/org/apache/camel/core/xml/AbstractCamelContextFactoryBean.java
+++ b/components/camel-core-xml/src/main/java/org/apache/camel/core/xml/AbstractCamelContextFactoryBean.java
@@ -66,6 +66,7 @@ import org.apache.camel.model.RouteContextRefDefinition;
 import org.apache.camel.model.RouteDefinition;
 import org.apache.camel.model.RouteDefinitionHelper;
 import org.apache.camel.model.ThreadPoolProfileDefinition;
+import org.apache.camel.model.cloud.ServiceCallConfigurationDefinition;
 import org.apache.camel.model.dataformat.DataFormatsDefinition;
 import org.apache.camel.model.rest.RestConfigurationDefinition;
 import org.apache.camel.model.rest.RestContainer;
@@ -775,6 +776,10 @@ public abstract class AbstractCamelContextFactoryBean<T extends ModelCamelContex
 
     public abstract String getDependsOn();
 
+    public abstract List<AbstractCamelFactoryBean<?>> getBeansFactory();
+
+    public abstract List<?> getBeans();
+
     // Implementation methods
     // -------------------------------------------------------------------------
 
@@ -851,6 +856,15 @@ public abstract class AbstractCamelContextFactoryBean<T extends ModelCamelContex
         if (getRestConfiguration() != null) {
             ctx.setRestConfiguration(getRestConfiguration().asRestConfiguration(ctx));
         }
+        if (getBeans() != null) {
+            for (Object bean : getBeans()) {
+                if (bean instanceof ServiceCallConfigurationDefinition) {
+                    @SuppressWarnings("unchecked")
+                    ServiceCallConfigurationDefinition configuration = (ServiceCallConfigurationDefinition)bean;
+                    ctx.addServiceCallConfiguration(configuration.getId(), configuration);
+                }
+            }
+        }
     }
 
     protected void initThreadPoolProfiles(T context) throws Exception {

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/components/camel-dns/src/main/java/org/apache/camel/component/dns/cloud/DnsServiceDiscovery.java
----------------------------------------------------------------------
diff --git a/components/camel-dns/src/main/java/org/apache/camel/component/dns/cloud/DnsServiceDiscovery.java b/components/camel-dns/src/main/java/org/apache/camel/component/dns/cloud/DnsServiceDiscovery.java
new file mode 100644
index 0000000..003fd8a
--- /dev/null
+++ b/components/camel-dns/src/main/java/org/apache/camel/component/dns/cloud/DnsServiceDiscovery.java
@@ -0,0 +1,102 @@
+/**
+ * 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.dns.cloud;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.stream.Collectors;
+
+import org.apache.camel.RuntimeCamelException;
+import org.apache.camel.cloud.ServiceDefinition;
+import org.apache.camel.component.dns.DnsConfiguration;
+import org.apache.camel.impl.cloud.DefaultServiceDefinition;
+import org.apache.camel.impl.cloud.DefaultServiceDiscovery;
+import org.apache.camel.util.ObjectHelper;
+import org.xbill.DNS.Lookup;
+import org.xbill.DNS.Record;
+import org.xbill.DNS.SRVRecord;
+import org.xbill.DNS.TextParseException;
+import org.xbill.DNS.Type;
+
+
+public final class DnsServiceDiscovery extends DefaultServiceDiscovery {
+    private static final Comparator<SRVRecord> COMPARATOR = comparator();
+    private final DnsConfiguration configuration;
+    private final ConcurrentHashMap<String, Lookup> cache;
+
+    public DnsServiceDiscovery(DnsConfiguration configuration) {
+        this.configuration = configuration;
+        this.cache = new ConcurrentHashMap<>();
+    }
+
+    @Override
+    public List<ServiceDefinition> getUpdatedListOfServices(String name) {
+        final Lookup lookup = cache.computeIfAbsent(name, this::createLookup);
+        final Record[] records = lookup.run();
+
+        List<ServiceDefinition> services;
+        if (Objects.nonNull(records) && lookup.getResult() == Lookup.SUCCESSFUL) {
+            services = Arrays.stream(records)
+                .filter(SRVRecord.class::isInstance)
+                .map(SRVRecord.class::cast)
+                .sorted(COMPARATOR)
+                .map(record -> asService(name, record))
+                .collect(Collectors.toList());
+        } else {
+            services = Collections.emptyList();
+        }
+
+        return services;
+    }
+
+    private Lookup createLookup(String name) {
+        try {
+            return new Lookup(
+                String.format("%s.%s.%s", name, configuration.getProto(), configuration.getDomain()),
+                Type.SRV);
+        } catch (TextParseException e) {
+            throw new RuntimeCamelException(e);
+        }
+    }
+
+    private static Comparator<SRVRecord> comparator() {
+        Comparator<SRVRecord> byPriority = (e1, e2) -> Integer.compare(e2.getPriority(), e1.getPriority());
+        Comparator<SRVRecord> byWeight = (e1, e2) -> Integer.compare(e2.getWeight(), e1.getWeight());
+
+        return byPriority.thenComparing(byWeight);
+    }
+
+    private static ServiceDefinition asService(String serviceName, SRVRecord record) {
+        Map<String, String> meta = new HashMap<>();
+        ObjectHelper.ifNotEmpty(record.getPriority(), val -> meta.put("priority", Integer.toString(val)));
+        ObjectHelper.ifNotEmpty(record.getWeight(), val -> meta.put("weight", Integer.toString(val)));
+
+        return new DefaultServiceDefinition(
+            serviceName,
+            record.getTarget().toString(true),
+            record.getPort(),
+            meta
+        );
+    }
+}


[07/10] camel git commit: CAMEL-10638: Refactor ServiceCall EIP

Posted by lb...@apache.org.
http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/camel-core/src/main/java/org/apache/camel/model/remote/ConsulConfigurationDefinition.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/model/remote/ConsulConfigurationDefinition.java b/camel-core/src/main/java/org/apache/camel/model/remote/ConsulConfigurationDefinition.java
deleted file mode 100644
index 9cb8a16..0000000
--- a/camel-core/src/main/java/org/apache/camel/model/remote/ConsulConfigurationDefinition.java
+++ /dev/null
@@ -1,232 +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.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 javax.xml.bind.annotation.XmlTransient;
-
-import org.apache.camel.spi.Metadata;
-import org.apache.camel.util.jsse.SSLContextParameters;
-
-/**
- * Consul remote service call configuration
- */
-@Metadata(label = "eip,routing,remote")
-@XmlRootElement(name = "consulConfiguration")
-@XmlAccessorType(XmlAccessType.FIELD)
-public class ConsulConfigurationDefinition extends ServiceCallConfigurationDefinition {
-
-    @XmlAttribute
-    private String url;
-    @XmlAttribute
-    private String dc;
-    @XmlAttribute @Metadata(label = "security")
-    private String aclToken;
-    @XmlAttribute @Metadata(label = "security")
-    private String userName;
-    @XmlAttribute @Metadata(label = "security")
-    private String password;
-    @XmlAttribute
-    private Long connectTimeoutMillis;
-    @XmlAttribute
-    private Long readTimeoutMillis;
-    @XmlAttribute
-    private Long writeTimeoutMillis;
-    @XmlAttribute @Metadata(defaultValue = "10")
-    private Integer blockSeconds = 10;
-    @XmlTransient
-    private SSLContextParameters sslContextParameters;
-
-    public ConsulConfigurationDefinition() {
-    }
-
-    public ConsulConfigurationDefinition(ServiceCallDefinition parent) {
-        super(parent);
-    }
-
-    // -------------------------------------------------------------------------
-    // Getter/Setter
-    // -------------------------------------------------------------------------
-
-    public String getUrl() {
-        return url;
-    }
-
-    public void setUrl(String url) {
-        this.url = url;
-    }
-
-    public String getDc() {
-        return dc;
-    }
-
-    public void setDc(String dc) {
-        this.dc = dc;
-    }
-
-    public String getAclToken() {
-        return aclToken;
-    }
-
-    public void setAclToken(String aclToken) {
-        this.aclToken = aclToken;
-    }
-
-    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 getConnectTimeoutMillis() {
-        return connectTimeoutMillis;
-    }
-
-    public void setConnectTimeoutMillis(Long connectTimeoutMillis) {
-        this.connectTimeoutMillis = connectTimeoutMillis;
-    }
-
-    public Long getReadTimeoutMillis() {
-        return readTimeoutMillis;
-    }
-
-    public void setReadTimeoutMillis(Long readTimeoutMillis) {
-        this.readTimeoutMillis = readTimeoutMillis;
-    }
-
-    public Long getWriteTimeoutMillis() {
-        return writeTimeoutMillis;
-    }
-
-    public void setWriteTimeoutMillis(Long writeTimeoutMillis) {
-        this.writeTimeoutMillis = writeTimeoutMillis;
-    }
-
-    public Integer getBlockSeconds() {
-        return blockSeconds;
-    }
-
-    public void setBlockSeconds(Integer blockSeconds) {
-        this.blockSeconds = blockSeconds;
-    }
-
-    public SSLContextParameters getSslContextParameters() {
-        return sslContextParameters;
-    }
-
-    public void setSslContextParameters(SSLContextParameters sslContextParameters) {
-        this.sslContextParameters = sslContextParameters;
-    }
-
-    // -------------------------------------------------------------------------
-    // Fluent API
-    // -------------------------------------------------------------------------
-
-    /**
-     * The Consul agent URL
-     */
-    public ConsulConfigurationDefinition url(String url) {
-        setUrl(url);
-        return this;
-    }
-
-    /**
-     * The data center
-     */
-    public ConsulConfigurationDefinition dc(String dc) {
-        setDc(dc);
-        return this;
-    }
-
-    /**
-     * Sets the ACL token to be used with Consul
-     */
-    public ConsulConfigurationDefinition aclToken(String aclToken) {
-        setAclToken(aclToken);
-        return this;
-    }
-
-    /**
-     * Sets the username to be used for basic authentication
-     */
-    public ConsulConfigurationDefinition userName(String userName) {
-        setUserName(userName);
-        return this;
-    }
-
-    /**
-     * Sets the password to be used for basic authentication
-     */
-    public ConsulConfigurationDefinition password(String password) {
-        setPassword(password);
-        return this;
-    }
-
-    /**
-     * Connect timeout for OkHttpClient
-     */
-    public ConsulConfigurationDefinition connectTimeoutMillis(Long connectTimeoutMillis) {
-        setConnectTimeoutMillis(connectTimeoutMillis);
-        return this;
-    }
-
-    /**
-     * Read timeout for OkHttpClient
-     */
-    public ConsulConfigurationDefinition readTimeoutMillis(Long readTimeoutMillis) {
-        setReadTimeoutMillis(readTimeoutMillis);
-        return this;
-    }
-
-    /**
-     * Write timeout for OkHttpClient
-     */
-    public ConsulConfigurationDefinition writeTimeoutMillis(Long writeTimeoutMillis) {
-        setWriteTimeoutMillis(writeTimeoutMillis);
-        return this;
-    }
-
-    /**
-     * The second to wait for a watch event, default 10 seconds
-     */
-    public ConsulConfigurationDefinition blockSeconds(Integer blockSeconds) {
-        setBlockSeconds(blockSeconds);
-        return this;
-    }
-
-    /**
-     * To configure security using SSLContextParameters.
-     */
-    public ConsulConfigurationDefinition sslContextParameters(SSLContextParameters sslContextParameters) {
-        setSslContextParameters(sslContextParameters);
-        return this;
-    }
-}

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/camel-core/src/main/java/org/apache/camel/model/remote/DnsConfigurationDefinition.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/model/remote/DnsConfigurationDefinition.java b/camel-core/src/main/java/org/apache/camel/model/remote/DnsConfigurationDefinition.java
deleted file mode 100644
index 7075ced..0000000
--- a/camel-core/src/main/java/org/apache/camel/model/remote/DnsConfigurationDefinition.java
+++ /dev/null
@@ -1,87 +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.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;
-
-/**
- * DNS remote service call configuration
- */
-@Metadata(label = "eip,routing,remote")
-@XmlRootElement(name = "dnsConfiguration")
-@XmlAccessorType(XmlAccessType.FIELD)
-public class DnsConfigurationDefinition extends ServiceCallConfigurationDefinition {
-
-    @XmlAttribute @Metadata(defaultValue = "_tcp")
-    String proto = "_tcp";
-
-    @XmlAttribute
-    String domain;
-
-    public DnsConfigurationDefinition() {
-    }
-
-    public DnsConfigurationDefinition(ServiceCallDefinition parent) {
-        super(parent);
-    }
-
-    // -------------------------------------------------------------------------
-    // Getter/Setter
-    // -------------------------------------------------------------------------
-
-    public String getProto() {
-        return proto;
-    }
-
-    public void setProto(String proto) {
-        this.proto = proto;
-    }
-
-    public String getDomain() {
-        return domain;
-    }
-
-    public void setDomain(String domain) {
-        this.domain = domain;
-    }
-
-    // -------------------------------------------------------------------------
-    // Fluent API
-    // -------------------------------------------------------------------------
- 
-    /**
-     * The transport protocol of the desired service.
-     */
-    public DnsConfigurationDefinition proto(String proto) {
-        setProto(proto);
-        return this;
-    }
-
-    /**
-     * The domain name;
-     */
-    public DnsConfigurationDefinition domain(String domain) {
-        setDomain(domain);
-        return this;
-    }
-}

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/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
deleted file mode 100644
index c1fdc9d..0000000
--- a/camel-core/src/main/java/org/apache/camel/model/remote/EtcdConfigurationDefinition.java
+++ /dev/null
@@ -1,159 +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.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 javax.xml.bind.annotation.XmlTransient;
-
-import org.apache.camel.spi.Metadata;
-import org.apache.camel.util.jsse.SSLContextParameters;
-
-/**
- * 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/";
-    @XmlTransient
-    private SSLContextParameters sslContextParameters;
-
-    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;
-    }
-
-    public SSLContextParameters getSslContextParameters() {
-        return sslContextParameters;
-    }
-
-    public void setSslContextParameters(SSLContextParameters sslContextParameters) {
-        this.sslContextParameters = sslContextParameters;
-    }
-
-    // -------------------------------------------------------------------------
-    // Fluent API
-    // -------------------------------------------------------------------------
-
-    /**
-     * The URIs the client can connect to.
-     */
-    public EtcdConfigurationDefinition uris(String uris) {
-        setUris(uris);
-        return this;
-    }
-
-    /**
-     * The user name to use for basic authentication.
-     */
-    public EtcdConfigurationDefinition userName(String userName) {
-        setUserName(userName);
-        return this;
-    }
-
-    /**
-     * The password to use for basic authentication.
-     */
-    public EtcdConfigurationDefinition password(String password) {
-        setPassword(password);
-        return this;
-    }
-
-    /**
-     * To set the maximum time an action could take to complete.
-     */
-    public EtcdConfigurationDefinition timeout(Long timeout) {
-        setTimeout(timeout);
-        return this;
-    }
-
-    /**
-     * The path to look for for service discovery
-     */
-    public EtcdConfigurationDefinition servicePath(String servicePath) {
-        setServicePath(servicePath);
-        return this;
-    }
-
-    /**
-     * To configure security using SSLContextParameters.
-     */
-    public EtcdConfigurationDefinition sslContextParameters(SSLContextParameters sslContextParameters) {
-        setSslContextParameters(sslContextParameters);
-        return this;
-    }
-}

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/camel-core/src/main/java/org/apache/camel/model/remote/KubernetesConfigurationDefinition.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/model/remote/KubernetesConfigurationDefinition.java b/camel-core/src/main/java/org/apache/camel/model/remote/KubernetesConfigurationDefinition.java
deleted file mode 100644
index d4bd95a..0000000
--- a/camel-core/src/main/java/org/apache/camel/model/remote/KubernetesConfigurationDefinition.java
+++ /dev/null
@@ -1,364 +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.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;
-
-/**
- * Kubernetes remote service call configuration
- */
-@Metadata(label = "eip,routing,remote")
-@XmlRootElement(name = "kubernetesConfiguration")
-@XmlAccessorType(XmlAccessType.FIELD)
-public class KubernetesConfigurationDefinition extends ServiceCallConfigurationDefinition {
-
-    @XmlAttribute @Metadata(defaultValue = "environment")
-    private String lookup;
-    @XmlAttribute
-    private String dnsDomain;
-    @XmlAttribute
-    private String namespace;
-    @XmlAttribute
-    private String apiVersion;
-    @XmlAttribute @Metadata(label = "client")
-    private String masterUrl;
-    @XmlAttribute @Metadata(label = "client")
-    private String username;
-    @XmlAttribute @Metadata(label = "client")
-    private String password;
-    @XmlAttribute @Metadata(label = "client")
-    private String oauthToken;
-    @XmlAttribute @Metadata(label = "client")
-    private String caCertData;
-    @XmlAttribute @Metadata(label = "client")
-    private String caCertFile;
-    @XmlAttribute @Metadata(label = "client")
-    private String clientCertData;
-    @XmlAttribute @Metadata(label = "client")
-    private String clientCertFile;
-    @XmlAttribute @Metadata(label = "client")
-    private String clientKeyAlgo;
-    @XmlAttribute @Metadata(label = "client")
-    private String clientKeyData;
-    @XmlAttribute @Metadata(label = "client")
-    private String clientKeyFile;
-    @XmlAttribute @Metadata(label = "client")
-    private String clientKeyPassphrase;
-    @XmlAttribute @Metadata(label = "client")
-    private Boolean trustCerts;
-
-    public KubernetesConfigurationDefinition() {
-    }
-
-    public KubernetesConfigurationDefinition(ServiceCallDefinition parent) {
-        super(parent);
-    }
-
-    // Getter/Setter
-    // -------------------------------------------------------------------------
-
-
-    public String getMasterUrl() {
-        return masterUrl;
-    }
-
-    public void setMasterUrl(String masterUrl) {
-        this.masterUrl = masterUrl;
-    }
-
-    public String getNamespace() {
-        return namespace;
-    }
-
-    public void setNamespace(String namespace) {
-        this.namespace = namespace;
-    }
-
-    public String getApiVersion() {
-        return apiVersion;
-    }
-
-    public void setApiVersion(String apiVersion) {
-        this.apiVersion = apiVersion;
-    }
-
-    public String getLookup() {
-        return lookup;
-    }
-
-    public void setLookup(String lookup) {
-        this.lookup = lookup;
-    }
-
-    public String getDnsDomain() {
-        return dnsDomain;
-    }
-
-    public void setDnsDomain(String dnsDomain) {
-        this.dnsDomain = dnsDomain;
-    }
-
-    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 String getOauthToken() {
-        return oauthToken;
-    }
-
-    public void setOauthToken(String oauthToken) {
-        this.oauthToken = oauthToken;
-    }
-
-    public String getCaCertData() {
-        return caCertData;
-    }
-
-    public void setCaCertData(String caCertData) {
-        this.caCertData = caCertData;
-    }
-
-    public String getCaCertFile() {
-        return caCertFile;
-    }
-
-    public void setCaCertFile(String caCertFile) {
-        this.caCertFile = caCertFile;
-    }
-
-    public String getClientCertData() {
-        return clientCertData;
-    }
-
-    public void setClientCertData(String clientCertData) {
-        this.clientCertData = clientCertData;
-    }
-
-    public String getClientCertFile() {
-        return clientCertFile;
-    }
-
-    public void setClientCertFile(String clientCertFile) {
-        this.clientCertFile = clientCertFile;
-    }
-
-    public String getClientKeyAlgo() {
-        return clientKeyAlgo;
-    }
-
-    public void setClientKeyAlgo(String clientKeyAlgo) {
-        this.clientKeyAlgo = clientKeyAlgo;
-    }
-
-    public String getClientKeyData() {
-        return clientKeyData;
-    }
-
-    public void setClientKeyData(String clientKeyData) {
-        this.clientKeyData = clientKeyData;
-    }
-
-    public String getClientKeyFile() {
-        return clientKeyFile;
-    }
-
-    public void setClientKeyFile(String clientKeyFile) {
-        this.clientKeyFile = clientKeyFile;
-    }
-
-    public String getClientKeyPassphrase() {
-        return clientKeyPassphrase;
-    }
-
-    public void setClientKeyPassphrase(String clientKeyPassphrase) {
-        this.clientKeyPassphrase = clientKeyPassphrase;
-    }
-
-    public Boolean getTrustCerts() {
-        return trustCerts;
-    }
-
-    public void setTrustCerts(Boolean trustCerts) {
-        this.trustCerts = trustCerts;
-    }
-
-    // Fluent API
-    // -------------------------------------------------------------------------
-
-    /**
-     * Sets the URL to the master when using client lookup
-     */
-    public KubernetesConfigurationDefinition masterUrl(String masterUrl) {
-        setMasterUrl(masterUrl);
-        return this;
-    }
-
-    /**
-     * Sets the namespace to use. Will by default use namespace from the ENV variable KUBERNETES_MASTER.
-     */
-    public KubernetesConfigurationDefinition namespace(String namespace) {
-        setNamespace(namespace);
-        return this;
-    }
-
-    /**
-     * Sets the API version when using client lookup
-     */
-    public KubernetesConfigurationDefinition apiVersion(String apiVersion) {
-        setApiVersion(apiVersion);
-        return this;
-    }
-
-    /**
-     * How to perform service lookup. Possible values: client, dns, environment.
-     * <p/>
-     * When using client, then the client queries the kubernetes master to obtain a list
-     * of active pods that provides the service, and then random (or round robin) select a pod.
-     * <p/>
-     * When using dns the service name is resolved as <tt>name.namespace.service.dnsDomain</tt>.
-     * <p/>
-     * When using environment then environment variables are used to lookup the service.
-     * <p/>
-     * By default environment is used.
-     */
-    public KubernetesConfigurationDefinition lookup(String lookup) {
-        setLookup(lookup);
-        return this;
-    }
-
-    /**
-     * Sets the DNS domain to use for DNS lookup.
-     */
-    public KubernetesConfigurationDefinition dnsDomain(String dnsDomain) {
-        setDnsDomain(dnsDomain);
-        return this;
-    }
-
-    /**
-     * Sets the username for authentication when using client lookup
-     */
-    public KubernetesConfigurationDefinition username(String username) {
-        setUsername(username);
-        return this;
-    }
-
-    /**
-     * Sets the password for authentication when using client lookup
-     */
-    public KubernetesConfigurationDefinition password(String password) {
-        setPassword(password);
-        return this;
-    }
-
-    /**
-     * Sets the OAUTH token for authentication (instead of username/password) when using client lookup
-     */
-    public KubernetesConfigurationDefinition oauthToken(String oauthToken) {
-        setOauthToken(oauthToken);
-        return this;
-    }
-
-    /**
-     * Sets the Certificate Authority data when using client lookup
-     */
-    public KubernetesConfigurationDefinition caCertData(String caCertData) {
-        setCaCertData(caCertData);
-        return this;
-    }
-
-    /**
-     * Sets the Certificate Authority data that are loaded from the file when using client lookup
-     */
-    public KubernetesConfigurationDefinition caCertFile(String caCertFile) {
-        setCaCertFile(caCertFile);
-        return this;
-    }
-
-    /**
-     * Sets the Client Certificate data when using client lookup
-     */
-    public KubernetesConfigurationDefinition clientCertData(String clientCertData) {
-        setClientCertData(clientCertData);
-        return this;
-    }
-
-    /**
-     * Sets the Client Certificate data that are loaded from the file when using client lookup
-     */
-    public KubernetesConfigurationDefinition clientCertFile(String clientCertFile) {
-        setClientCertFile(clientCertFile);
-        return this;
-    }
-
-    /**
-     * Sets the Client Keystore algorithm, such as RSA when using client lookup
-     */
-    public KubernetesConfigurationDefinition clientKeyAlgo(String clientKeyAlgo) {
-        setClientKeyAlgo(clientKeyAlgo);
-        return this;
-    }
-
-    /**
-     * Sets the Client Keystore data when using client lookup
-     */
-    public KubernetesConfigurationDefinition clientKeyData(String clientKeyData) {
-        setClientKeyData(clientKeyData);
-        return this;
-    }
-
-    /**
-     * Sets the Client Keystore data that are loaded from the file when using client lookup
-     */
-    public KubernetesConfigurationDefinition clientKeyFile(String clientKeyFile) {
-        setClientKeyFile(clientKeyFile);
-        return this;
-    }
-
-    /**
-     * Sets the Client Keystore passphrase when using client lookup
-     */
-    public KubernetesConfigurationDefinition clientKeyPassphrase(String clientKeyPassphrase) {
-        setClientKeyPassphrase(clientKeyPassphrase);
-        return this;
-    }
-
-    /**
-     * Sets whether to turn on trust certificate check when using client lookup
-     */
-    public KubernetesConfigurationDefinition trustCerts(boolean trustCerts) {
-        setTrustCerts(trustCerts);
-        return this;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/camel-core/src/main/java/org/apache/camel/model/remote/RibbonConfigurationDefinition.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/model/remote/RibbonConfigurationDefinition.java b/camel-core/src/main/java/org/apache/camel/model/remote/RibbonConfigurationDefinition.java
deleted file mode 100644
index a528538..0000000
--- a/camel-core/src/main/java/org/apache/camel/model/remote/RibbonConfigurationDefinition.java
+++ /dev/null
@@ -1,48 +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.model.remote;
-
-import javax.xml.bind.annotation.XmlAccessType;
-import javax.xml.bind.annotation.XmlAccessorType;
-import javax.xml.bind.annotation.XmlRootElement;
-
-import org.apache.camel.spi.Metadata;
-
-/**
- * Ribbon remote service call configuration
- */
-@Metadata(label = "eip,routing,remote")
-@XmlRootElement(name = "ribbonConfiguration")
-@XmlAccessorType(XmlAccessType.FIELD)
-public class RibbonConfigurationDefinition extends ServiceCallConfigurationDefinition {
-
-    public RibbonConfigurationDefinition() {
-    }
-
-    public RibbonConfigurationDefinition(ServiceCallDefinition parent) {
-        super(parent);
-    }
-
-    // Getter/Setter
-    // -------------------------------------------------------------------------
-
-    // currently no ribbon specific options
-
-    // Fluent API
-    // -------------------------------------------------------------------------
-
-}

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/camel-core/src/main/java/org/apache/camel/model/remote/ServiceCallConfigurationDefinition.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/model/remote/ServiceCallConfigurationDefinition.java b/camel-core/src/main/java/org/apache/camel/model/remote/ServiceCallConfigurationDefinition.java
deleted file mode 100644
index 359bcdb..0000000
--- a/camel-core/src/main/java/org/apache/camel/model/remote/ServiceCallConfigurationDefinition.java
+++ /dev/null
@@ -1,222 +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.model.remote;
-
-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.XmlAnyAttribute;
-import javax.xml.bind.annotation.XmlAttribute;
-import javax.xml.bind.annotation.XmlElement;
-import javax.xml.bind.annotation.XmlRootElement;
-import javax.xml.bind.annotation.XmlTransient;
-import javax.xml.namespace.QName;
-
-import org.apache.camel.model.IdentifiedType;
-import org.apache.camel.model.OtherAttributesAware;
-import org.apache.camel.model.ProcessorDefinition;
-import org.apache.camel.model.PropertyDefinition;
-import org.apache.camel.spi.Metadata;
-import org.apache.camel.spi.ServiceCallLoadBalancer;
-import org.apache.camel.spi.ServiceCallServerListStrategy;
-
-/**
- * Remote service call configuration
- */
-@Metadata(label = "eip,routing,remote")
-@XmlRootElement(name = "serviceCallConfiguration")
-@XmlAccessorType(XmlAccessType.FIELD)
-public class ServiceCallConfigurationDefinition extends IdentifiedType implements OtherAttributesAware {
-
-    @XmlTransient
-    private ServiceCallDefinition parent;
-    @XmlAttribute @Metadata(defaultValue = "http")
-    private String component;
-    @XmlAttribute
-    private String loadBalancerRef;
-    @XmlTransient
-    private ServiceCallLoadBalancer loadBalancer;
-    @XmlAttribute
-    private String serverListStrategyRef;
-    @XmlTransient
-    private ServiceCallServerListStrategy serverListStrategy;
-    @XmlElement(name = "clientProperty") @Metadata(label = "advanced")
-    private List<PropertyDefinition> properties;
-    // use xs:any to support optional property placeholders
-    @XmlAnyAttribute
-    private Map<QName, Object> otherAttributes;
-
-    public ServiceCallConfigurationDefinition() {
-    }
-
-    public ServiceCallConfigurationDefinition(ServiceCallDefinition parent) {
-        this.parent = parent;
-    }
-
-    // Getter/Setter
-    // -------------------------------------------------------------------------
-
-
-    public String getComponent() {
-        return component;
-    }
-
-    public void setComponent(String component) {
-        this.component = component;
-    }
-
-    public String getLoadBalancerRef() {
-        return loadBalancerRef;
-    }
-
-    /**
-     * Sets a reference to a custom {@link org.apache.camel.spi.ServiceCallLoadBalancer} to use.
-     */
-    public void setLoadBalancerRef(String loadBalancerRef) {
-        this.loadBalancerRef = loadBalancerRef;
-    }
-
-    public ServiceCallLoadBalancer getLoadBalancer() {
-        return loadBalancer;
-    }
-
-    public void setLoadBalancer(ServiceCallLoadBalancer loadBalancer) {
-        this.loadBalancer = loadBalancer;
-    }
-
-    public String getServerListStrategyRef() {
-        return serverListStrategyRef;
-    }
-
-    /**
-     * Sets a reference to a custom {@link org.apache.camel.spi.ServiceCallServerListStrategy} to use.
-     */
-    public void setServerListStrategyRef(String serverListStrategyRef) {
-        this.serverListStrategyRef = serverListStrategyRef;
-    }
-
-    public ServiceCallServerListStrategy getServerListStrategy() {
-        return serverListStrategy;
-    }
-
-    public void setServerListStrategy(ServiceCallServerListStrategy serverListStrategy) {
-        this.serverListStrategy = serverListStrategy;
-    }
-
-    public List<PropertyDefinition> getProperties() {
-        return properties;
-    }
-
-    /**
-     * Set client properties to use.
-     * <p/>
-     * These properties are specific to what service call implementation are in 
-     * use. For example if using ribbon, then the client properties are define 
-     * in com.netflix.client.config.CommonClientConfigKey.
-     */
-    public void setProperties(List<PropertyDefinition> properties) {
-        this.properties = properties;
-    }
-
-    @Override
-    public Map<QName, Object> getOtherAttributes() {
-        return otherAttributes;
-    }
-
-    @Override
-    public void setOtherAttributes(Map<QName, Object> otherAttributes) {
-        this.otherAttributes = otherAttributes;
-    }
-
-    // Fluent API
-    // -------------------------------------------------------------------------
-
-    /**
-     * Sets the default Camel component to use for calling the remote service.
-     * <p/>
-     * By default the http component is used. You can configure this to use <tt>netty4-http</tt>, <tt>jetty</tt>,
-     * <tt>restlet</tt> or some other components of choice. If the service is not HTTP protocol you can use other
-     * components such as <tt>mqtt</tt>, <tt>jms</tt>, <tt>amqp</tt> etc.
-     * <p/>
-     * If the service call has been configured using an uri, then the component from the uri is used instead
-     * of this default component.
-     */
-    public ServiceCallConfigurationDefinition component(String component) {
-        setComponent(component);
-        return this;
-    }
-
-    /**
-     * Sets a reference to a custom {@link org.apache.camel.spi.ServiceCallLoadBalancer} to use.
-     */
-    public ServiceCallConfigurationDefinition loadBalancer(String loadBalancerRef) {
-        setLoadBalancerRef(loadBalancerRef);
-        return this;
-    }
-
-    /**
-     * Sets a custom {@link org.apache.camel.spi.ServiceCallLoadBalancer} to use.
-     */
-    public ServiceCallConfigurationDefinition loadBalancer(ServiceCallLoadBalancer loadBalancer) {
-        setLoadBalancer(loadBalancer);
-        return this;
-    }
-
-    /**
-     * Sets a reference to a custom {@link org.apache.camel.spi.ServiceCallServerListStrategy} to use.
-     */
-    public ServiceCallConfigurationDefinition serverListStrategy(String serverListStrategyRef) {
-        setServerListStrategyRef(serverListStrategyRef);
-        return this;
-    }
-
-    /**
-     * Sets a custom {@link org.apache.camel.spi.ServiceCallServerListStrategy} to use.
-     */
-    public ServiceCallConfigurationDefinition serverListStrategy(ServiceCallServerListStrategy serverListStrategy) {
-        setServerListStrategy(serverListStrategy);
-        return this;
-    }
-
-    /**
-     * Adds a custom client property to use.
-     * <p/>
-     * These properties are specific to what service call implementation are in use. For example if using ribbon, then
-     * the client properties are define in com.netflix.client.config.CommonClientConfigKey.
-     */
-    public ServiceCallConfigurationDefinition clientProperty(String key, String value) {
-        if (properties == null) {
-            properties = new ArrayList<>();
-        }
-        PropertyDefinition prop = new PropertyDefinition();
-        prop.setKey(key);
-        prop.setValue(value);
-        properties.add(prop);
-        return this;
-    }
-
-    /**
-     * End of configuration
-     */
-    public ProcessorDefinition end() {
-        // end parent as well so we do not have to use 2x end
-        return parent.end();
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/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
deleted file mode 100644
index d91aa5a..0000000
--- a/camel-core/src/main/java/org/apache/camel/model/remote/ServiceCallDefinition.java
+++ /dev/null
@@ -1,313 +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.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.XmlElement;
-import javax.xml.bind.annotation.XmlRootElement;
-import javax.xml.bind.annotation.XmlTransient;
-
-import org.apache.camel.ExchangePattern;
-import org.apache.camel.Processor;
-import org.apache.camel.model.NoOutputDefinition;
-import org.apache.camel.spi.Metadata;
-import org.apache.camel.spi.RouteContext;
-import org.apache.camel.spi.ServiceCallLoadBalancer;
-import org.apache.camel.spi.ServiceCallServerListStrategy;
-
-/**
- * Remote service call
- */
-@Metadata(label = "eip,routing")
-@XmlRootElement(name = "serviceCall")
-@XmlAccessorType(XmlAccessType.FIELD)
-public class ServiceCallDefinition extends NoOutputDefinition<ServiceCallDefinition> {
-
-    @XmlAttribute @Metadata(required = "true")
-    private String name;
-    @XmlAttribute
-    private String uri;
-    @XmlAttribute
-    private String component;
-    @XmlAttribute
-    private ExchangePattern pattern;
-    @XmlElement
-    private ServiceCallConfigurationDefinition serviceCallConfiguration;
-    @XmlAttribute
-    private String serviceCallConfigurationRef;
-    @XmlAttribute
-    private String loadBalancerRef;
-    // TODO: allow to use custom type as load balancer
-    @XmlTransient
-    private ServiceCallLoadBalancer loadBalancer;
-    @XmlAttribute
-    private String serverListStrategyRef;
-    @XmlTransient
-    private ServiceCallServerListStrategy serverListStrategy;
-
-    public ServiceCallDefinition() {
-    }
-
-    @Override
-    public String toString() {
-        return "ServiceCall[" + name + "]";
-    }
-
-    @Override
-    public String getLabel() {
-        return "serviceCall";
-    }
-
-    @Override
-    public Processor createProcessor(RouteContext routeContext) throws Exception {
-        throw new IllegalStateException("Cannot find Camel component supporting the ServiceCall EIP such as camel-kubernetes or camel-ribbon.");
-    }
-
-    // Fluent API
-    // -------------------------------------------------------------------------
-
-    /**
-     * Sets the optional {@link ExchangePattern} used to invoke this endpoint
-     */
-    public ServiceCallDefinition pattern(ExchangePattern pattern) {
-        setPattern(pattern);
-        return this;
-    }
-
-    /**
-     * Sets the name of the service to use
-     */
-    public ServiceCallDefinition name(String name) {
-        setName(name);
-        return this;
-    }
-
-    /**
-     * Sets the uri of the service to use
-     */
-    public ServiceCallDefinition uri(String uri) {
-        setUri(uri);
-        return this;
-    }
-
-    /**
-     * Sets the component to use
-     */
-    public ServiceCallDefinition component(String component) {
-        setComponent(component);
-        return this;
-    }
-
-    /**
-     * Configures the Service Call EIP using Kubernetes
-     * <p/>
-     * Use <tt>end</tt> when configuration is complete, to return back to the Service Call EIP.
-     */
-    public KubernetesConfigurationDefinition kubernetesConfiguration() {
-        serviceCallConfiguration = new KubernetesConfigurationDefinition(this);
-        return (KubernetesConfigurationDefinition) serviceCallConfiguration;
-    }
-
-    /**
-     * Configures the Service Call EIP using Ribbon
-     * <p/>
-     * Use <tt>end</tt> when configuration is complete, to return back to the Service Call EIP.
-     */
-    public RibbonConfigurationDefinition ribbonConfiguration() {
-        serviceCallConfiguration = new RibbonConfigurationDefinition(this);
-        return (RibbonConfigurationDefinition) serviceCallConfiguration;
-    }
-
-    /**
-     * Configures the Service Call EIP using Consul
-     * <p/>
-     * Use <tt>end</tt> when configuration is complete, to return back to the Service Call EIP.
-     */
-    public ConsulConfigurationDefinition consulConfiguration() {
-        serviceCallConfiguration = new ConsulConfigurationDefinition(this);
-        return (ConsulConfigurationDefinition) serviceCallConfiguration;
-    }
-
-    /**
-     * 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 Service Call EIP using Dns
-     * <p/>
-     * Use <tt>end</tt> when configuration is complete, to return back to the Service Call EIP.
-     */
-    public DnsConfigurationDefinition dnsConfiguration() {
-        serviceCallConfiguration = new DnsConfigurationDefinition(this);
-        return (DnsConfigurationDefinition) serviceCallConfiguration;
-    }
-
-    /**
-     * Configures the ServiceCall using the given configuration
-     */
-    public ServiceCallDefinition serviceCallConfiguration(ServiceCallConfigurationDefinition configuration) {
-        serviceCallConfiguration = configuration;
-        return this;
-    }
-
-    /**
-     * Refers to a ServiceCall configuration to use
-     */
-    public ServiceCallDefinition serviceCallConfiguration(String ref) {
-        serviceCallConfigurationRef = ref;
-        return this;
-    }
-
-    /**
-     * Sets a reference to a custom {@link org.apache.camel.spi.ServiceCallLoadBalancer} to use.
-     */
-    public ServiceCallDefinition loadBalancer(String loadBalancerRef) {
-        setLoadBalancerRef(loadBalancerRef);
-        return this;
-    }
-
-    /**
-     * Sets a custom {@link org.apache.camel.spi.ServiceCallLoadBalancer} to use.
-     */
-    public ServiceCallDefinition loadBalancer(ServiceCallLoadBalancer loadBalancer) {
-        setLoadBalancer(loadBalancer);
-        return this;
-    }
-
-    /**
-     * Sets a reference to a custom {@link org.apache.camel.spi.ServiceCallServerListStrategy} to use.
-     */
-    public ServiceCallDefinition serverListStrategy(String serverListStrategyRef) {
-        setServerListStrategyRef(serverListStrategyRef);
-        return this;
-    }
-
-    /**
-     * Sets a custom {@link org.apache.camel.spi.ServiceCallServerListStrategy} to use.
-     */
-    public ServiceCallDefinition serverListStrategy(ServiceCallServerListStrategy serverListStrategy) {
-        setServerListStrategy(serverListStrategy);
-        return this;
-    }
-
-    // Properties
-    // -------------------------------------------------------------------------
-
-    public String getName() {
-        return name;
-    }
-
-    public void setName(String name) {
-        this.name = name;
-    }
-
-    public ExchangePattern getPattern() {
-        return pattern;
-    }
-
-    public void setPattern(ExchangePattern pattern) {
-        this.pattern = pattern;
-    }
-
-    public ServiceCallConfigurationDefinition getServiceCallConfiguration() {
-        return serviceCallConfiguration;
-    }
-
-    public void setServiceCallConfiguration(ServiceCallConfigurationDefinition serviceCallConfiguration) {
-        this.serviceCallConfiguration = serviceCallConfiguration;
-    }
-
-    public String getServiceCallConfigurationRef() {
-        return serviceCallConfigurationRef;
-    }
-
-    /**
-     * Refers to a ServiceCall configuration to use
-     */
-    public void setServiceCallConfigurationRef(String serviceCallConfigurationRef) {
-        this.serviceCallConfigurationRef = serviceCallConfigurationRef;
-    }
-
-    public String getUri() {
-        return uri;
-    }
-
-    /**
-     * The uri of the endpoint to send to.
-     * The uri can be dynamic computed using the {@link org.apache.camel.language.simple.SimpleLanguage} expression.
-     */
-    public void setUri(String uri) {
-        this.uri = uri;
-    }
-
-    public String getComponent() {
-        return component;
-    }
-
-    /**
-     * The component to use.
-     */
-    public void setComponent(String component) {
-        this.component = component;
-    }
-
-    public String getLoadBalancerRef() {
-        return loadBalancerRef;
-    }
-
-    /**
-     * Sets a reference to a custom {@link org.apache.camel.spi.ServiceCallLoadBalancer} to use.
-     */
-    public void setLoadBalancerRef(String loadBalancerRef) {
-        this.loadBalancerRef = loadBalancerRef;
-    }
-
-    public ServiceCallLoadBalancer getLoadBalancer() {
-        return loadBalancer;
-    }
-
-    public void setLoadBalancer(ServiceCallLoadBalancer loadBalancer) {
-        this.loadBalancer = loadBalancer;
-    }
-
-    public String getServerListStrategyRef() {
-        return serverListStrategyRef;
-    }
-
-    /**
-     * Sets a reference to a custom {@link org.apache.camel.spi.ServiceCallServerListStrategy} to use.
-     */
-    public void setServerListStrategyRef(String serverListStrategyRef) {
-        this.serverListStrategyRef = serverListStrategyRef;
-    }
-
-    public ServiceCallServerListStrategy getServerListStrategy() {
-        return serverListStrategy;
-    }
-
-    public void setServerListStrategy(ServiceCallServerListStrategy serverListStrategy) {
-        this.serverListStrategy = serverListStrategy;
-    }
-}

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/camel-core/src/main/java/org/apache/camel/model/remote/ServiceCallProcessorFactory.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/model/remote/ServiceCallProcessorFactory.java b/camel-core/src/main/java/org/apache/camel/model/remote/ServiceCallProcessorFactory.java
deleted file mode 100644
index 8a07c8b..0000000
--- a/camel-core/src/main/java/org/apache/camel/model/remote/ServiceCallProcessorFactory.java
+++ /dev/null
@@ -1,22 +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.model.remote;
-
-import org.apache.camel.spi.ProcessorFactory;
-
-public interface ServiceCallProcessorFactory extends ProcessorFactory {
-}

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/camel-core/src/main/java/org/apache/camel/model/remote/package-info.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/model/remote/package-info.java b/camel-core/src/main/java/org/apache/camel/model/remote/package-info.java
deleted file mode 100644
index 5d6e89e..0000000
--- a/camel-core/src/main/java/org/apache/camel/model/remote/package-info.java
+++ /dev/null
@@ -1,23 +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.
- */
-
-
-/**
- * The JAXB POJOs for the remote service call DSL
- */
-@javax.xml.bind.annotation.XmlSchema(namespace = "http://camel.apache.org/schema/spring", elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED)
-package org.apache.camel.model.remote;

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/camel-core/src/main/java/org/apache/camel/spi/ServiceCallLoadBalancer.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/spi/ServiceCallLoadBalancer.java b/camel-core/src/main/java/org/apache/camel/spi/ServiceCallLoadBalancer.java
index 1897171..fba9279 100644
--- a/camel-core/src/main/java/org/apache/camel/spi/ServiceCallLoadBalancer.java
+++ b/camel-core/src/main/java/org/apache/camel/spi/ServiceCallLoadBalancer.java
@@ -14,23 +14,16 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.camel.spi;
 
-import java.util.List;
+package org.apache.camel.spi;
 
 /**
- * Allows SPIs to implement custom load balancing strategies for the Service Call EIP.
+ * Represents a load balancer for the Service Call EIP.
  *
- * @see ServiceCallServerListStrategy
+ * @see ServiceCallServiceChooser
+ * @see ServiceCallServiceDiscovery
  */
-public interface ServiceCallLoadBalancer<T extends ServiceCallServer> {
-
-    /**
-     * Chooses one of the servers to use using the implemented strategy.
-     *
-     * @param servers  list of servers
-     * @return the chosen server to use.
-     */
-    T chooseServer(List<T> servers);
-
+@FunctionalInterface
+public interface ServiceCallLoadBalancer {
+    <T> T process(String serviceName, ServiceCallLoadBalancerRequest<T> request) throws Exception;
 }

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/camel-core/src/main/java/org/apache/camel/spi/ServiceCallLoadBalancerRequest.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/spi/ServiceCallLoadBalancerRequest.java b/camel-core/src/main/java/org/apache/camel/spi/ServiceCallLoadBalancerRequest.java
new file mode 100644
index 0000000..63c2920
--- /dev/null
+++ b/camel-core/src/main/java/org/apache/camel/spi/ServiceCallLoadBalancerRequest.java
@@ -0,0 +1,29 @@
+/**
+ * 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.spi;
+
+/**
+ * Represents a load balancer for the Service Call EIP.
+ *
+ * @see ServiceCallServiceChooser
+ * @see ServiceCallServiceDiscovery
+ */
+@FunctionalInterface
+public interface ServiceCallLoadBalancerRequest<T> {
+    T process(ServiceCallService service) throws Exception;
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/camel-core/src/main/java/org/apache/camel/spi/ServiceCallServer.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/spi/ServiceCallServer.java b/camel-core/src/main/java/org/apache/camel/spi/ServiceCallServer.java
deleted file mode 100644
index bf79482..0000000
--- a/camel-core/src/main/java/org/apache/camel/spi/ServiceCallServer.java
+++ /dev/null
@@ -1,42 +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.spi;
-
-import java.util.Map;
-
-/**
- * Represents a server that host a service for the Service Call EIP.
- *
- * @see ServiceCallLoadBalancer
- * @see ServiceCallServerListStrategy
- */
-public interface ServiceCallServer {
-    /**
-     * Gets the IP or hostname of the server hosting the service
-     */
-    String getIp();
-
-    /**
-     * Gets the port number of the server hosting the service
-     */
-    int getPort();
-
-    /**
-     * Gets a key/value metadata associated with the service
-     */
-    Map<String, String> getMetadata();
-}

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/camel-core/src/main/java/org/apache/camel/spi/ServiceCallServerListStrategy.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/spi/ServiceCallServerListStrategy.java b/camel-core/src/main/java/org/apache/camel/spi/ServiceCallServerListStrategy.java
deleted file mode 100644
index 61bc4e3..0000000
--- a/camel-core/src/main/java/org/apache/camel/spi/ServiceCallServerListStrategy.java
+++ /dev/null
@@ -1,49 +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.spi;
-
-import java.util.List;
-
-/**
- * Allows SPIs to implement custom server list strategies for the Service Call EIP.
- *
- * @see ServiceCallLoadBalancer
- * @see ServiceCallServer
- */
-public interface ServiceCallServerListStrategy<T extends ServiceCallServer> {
-
-    /**
-     * Gets the initial list of servers.
-     * <p/>
-     * This method may return <tt>null</tt> or an empty list.
-     *
-     * @param name the service name
-     */
-    List<T> getInitialListOfServers(String name);
-
-    /**
-     * Gets the updated list of servers.
-     * <p/>
-     * This method can either be called on-demand prior to a service call, or have
-     * a background job that is scheduled to update the list, or a watcher
-     * that triggers when the list of servers changes.
-     *
-     * @param name the service name
-     */
-    List<T> getUpdatedListOfServers(String name);
-
-}

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/camel-core/src/main/java/org/apache/camel/spi/ServiceCallService.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/spi/ServiceCallService.java b/camel-core/src/main/java/org/apache/camel/spi/ServiceCallService.java
new file mode 100644
index 0000000..1fdcdb5
--- /dev/null
+++ b/camel-core/src/main/java/org/apache/camel/spi/ServiceCallService.java
@@ -0,0 +1,47 @@
+/**
+ * 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.spi;
+
+import java.util.Map;
+
+/**
+ * Represents a server that host a service for the Service Call EIP.
+ *
+ * @see ServiceCallServiceChooser
+ * @see ServiceCallServiceDiscovery
+ */
+public interface ServiceCallService {
+    /**
+     * Gets the service name.
+     */
+    String getName();
+
+    /**
+     * Gets the IP or hostname of the server hosting the service.
+     */
+    String getHost();
+
+    /**
+     * Gets the port number of the server hosting the service.
+     */
+    int getPort();
+
+    /**
+     * Gets a key/value metadata associated with the service.
+     */
+    Map<String, String> getMetadata();
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/camel-core/src/main/java/org/apache/camel/spi/ServiceCallServiceChooser.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/spi/ServiceCallServiceChooser.java b/camel-core/src/main/java/org/apache/camel/spi/ServiceCallServiceChooser.java
new file mode 100644
index 0000000..f5d71e4
--- /dev/null
+++ b/camel-core/src/main/java/org/apache/camel/spi/ServiceCallServiceChooser.java
@@ -0,0 +1,35 @@
+/**
+ * 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.spi;
+
+import java.util.List;
+
+/**
+ * Allows SPIs to implement custom Service Chooser for the Service Call EIP.
+ *
+ * @see ServiceCallServiceDiscovery
+ */
+@FunctionalInterface
+public interface ServiceCallServiceChooser {
+    /**
+     * Chooses one of the service to use
+     *
+     * @param services  list of services
+     * @return the chosen service to use.
+     */
+    ServiceCallService choose(List<ServiceCallService> services);
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/camel-core/src/main/java/org/apache/camel/spi/ServiceCallServiceChooserAware.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/spi/ServiceCallServiceChooserAware.java b/camel-core/src/main/java/org/apache/camel/spi/ServiceCallServiceChooserAware.java
new file mode 100644
index 0000000..43c8c60
--- /dev/null
+++ b/camel-core/src/main/java/org/apache/camel/spi/ServiceCallServiceChooserAware.java
@@ -0,0 +1,37 @@
+/**
+ * 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.spi;
+
+/**
+ * An interface to represent an object which wishes to be injected with
+ * a {@link ServiceCallServiceChooser}
+ */
+public interface ServiceCallServiceChooserAware {
+    /**
+     * Injects the {@link ServiceCallServiceChooser}
+     *
+     * @param serviceChooser the ServiceCallServerChooser
+     */
+    void setServiceChooser(ServiceCallServiceChooser serviceChooser);
+
+    /**
+     * Get the {@link ServiceCallServiceChooser}
+     *
+     * @return the ServiceCallServerChooser
+     */
+    ServiceCallServiceChooser getServiceChooser();
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/camel-core/src/main/java/org/apache/camel/spi/ServiceCallServiceDiscovery.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/spi/ServiceCallServiceDiscovery.java b/camel-core/src/main/java/org/apache/camel/spi/ServiceCallServiceDiscovery.java
new file mode 100644
index 0000000..7ca72be
--- /dev/null
+++ b/camel-core/src/main/java/org/apache/camel/spi/ServiceCallServiceDiscovery.java
@@ -0,0 +1,47 @@
+/**
+ * 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.spi;
+
+import java.util.List;
+
+/**
+ * Allows SPIs to implement custom Service Discovery for the Service Call EIP.
+ *
+ * @see ServiceCallServiceChooser
+ * @see ServiceCallService
+ */
+public interface ServiceCallServiceDiscovery {
+    /**
+     * Gets the initial list of services.
+     * <p/>
+     * This method may return <tt>null</tt> or an empty list.
+     *
+     * @param name the service name
+     */
+    List<ServiceCallService> getInitialListOfServices(String name);
+
+    /**
+     * Gets the updated list of services.
+     * <p/>
+     * This method can either be called on-demand prior to a service call, or have
+     * a background job that is scheduled to update the list, or a watcher
+     * that triggers when the list of services changes.
+     *
+     * @param name the service name
+     */
+    List<ServiceCallService> getUpdatedListOfServices(String name);
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/camel-core/src/main/java/org/apache/camel/spi/ServiceCallServiceDiscoveryAware.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/spi/ServiceCallServiceDiscoveryAware.java b/camel-core/src/main/java/org/apache/camel/spi/ServiceCallServiceDiscoveryAware.java
new file mode 100644
index 0000000..5faa0ed
--- /dev/null
+++ b/camel-core/src/main/java/org/apache/camel/spi/ServiceCallServiceDiscoveryAware.java
@@ -0,0 +1,37 @@
+/**
+ * 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.spi;
+
+/**
+ * An interface to represent an object which wishes to be injected with
+ * a {@link ServiceCallServiceDiscovery}
+ */
+public interface ServiceCallServiceDiscoveryAware {
+    /**
+     * Injects the {@link ServiceCallServiceDiscovery}
+     *
+     * @param serviceDiscovery the ServiceCallServerDiscovery
+     */
+    void setServiceDiscovery(ServiceCallServiceDiscovery serviceDiscovery);
+
+    /**
+     * Get the {@link ServiceCallServiceDiscovery}
+     *
+     * @return the ServiceCallServerDiscovery
+     */
+    ServiceCallServiceDiscovery getServiceDiscovery();
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/camel-core/src/main/java/org/apache/camel/support/ServiceCallExpressionSupport.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/support/ServiceCallExpressionSupport.java b/camel-core/src/main/java/org/apache/camel/support/ServiceCallExpressionSupport.java
index 1351d31..e80e2a2 100644
--- a/camel-core/src/main/java/org/apache/camel/support/ServiceCallExpressionSupport.java
+++ b/camel-core/src/main/java/org/apache/camel/support/ServiceCallExpressionSupport.java
@@ -17,89 +17,53 @@
 package org.apache.camel.support;
 
 import org.apache.camel.Exchange;
-import org.apache.camel.model.remote.ServiceCallDefinition;
+import org.apache.camel.impl.cloud.ServiceCallConstants;
+import org.apache.camel.util.ExchangeHelper;
 import org.apache.camel.util.ObjectHelper;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
-/**
- * Support class for custom implementations of {@link ServiceCallDefinition ServiceCall EIP} components.
- * <p/>
- * Below are some examples how to call a service and what Camel endpoint URI is constructed based on the input:
- * <pre>
-     serviceCall("myService") -> http://hostname:port
-     serviceCall("myService/foo") -> http://hostname:port/foo
-     serviceCall("http:myService/foo") -> http:hostname:port/foo
-     serviceCall("myService", "http:myService.host:myService.port/foo") -> http:hostname:port/foo
-     serviceCall("myService", "netty4:tcp:myService?connectTimeout=1000") -> netty:tcp:hostname:port?connectTimeout=1000
- * </pre>
- */
 public abstract class ServiceCallExpressionSupport extends ExpressionAdapter {
+    private String hostHeader;
+    private String portHeader;
 
-    private static final Logger LOG = LoggerFactory.getLogger(ServiceCallExpressionSupport.class);
+    public ServiceCallExpressionSupport() {
+        this(ServiceCallConstants.SERVICE_HOST, ServiceCallConstants.SERVICE_PORT);
+    }
 
-    private final String name;
-    private final String scheme;
-    private final String contextPath;
-    private final String uri;
+    public ServiceCallExpressionSupport(String hostHeader, String portHeader) {
+        this.hostHeader = hostHeader;
+        this.portHeader = portHeader;
+    }
 
-    public ServiceCallExpressionSupport(String name, String scheme, String contextPath, String uri) {
-        this.name = name;
-        this.scheme = scheme;
-        this.contextPath = contextPath;
-        this.uri = uri;
+    public String getHostHeader() {
+        return hostHeader;
     }
 
-    public abstract String getIp(Exchange exchange) throws Exception;
+    public void setHostHeader(String hostHeader) {
+        this.hostHeader = hostHeader;
+    }
 
-    public abstract int getPort(Exchange exchange) throws Exception;
+    public String getPortHeader() {
+        return portHeader;
+    }
+
+    public void setPortHeader(String portHeader) {
+        this.portHeader = portHeader;
+    }
 
     @Override
     public Object evaluate(Exchange exchange) {
         try {
-            String ip = getIp(exchange);
-            int port = getPort(exchange);
-            return buildCamelEndpointUri(ip, port, name, uri, contextPath, scheme);
+            return buildCamelEndpointUri(
+                ExchangeHelper.getMandatoryHeader(exchange, ServiceCallConstants.SERVICE_NAME, String.class),
+                ExchangeHelper.getMandatoryHeader(exchange, hostHeader, String.class),
+                exchange.getIn().getHeader(portHeader, Integer.class),
+                exchange.getIn().getHeader(ServiceCallConstants.SERVICE_CALL_URI, String.class),
+                exchange.getIn().getHeader(ServiceCallConstants.SERVICE_CALL_CONTEXT_PATH, String.class),
+                exchange.getIn().getHeader(ServiceCallConstants.SERVICE_CALL_SCHEME, String.class));
         } catch (Exception e) {
             throw ObjectHelper.wrapRuntimeCamelException(e);
         }
     }
 
-    protected static String buildCamelEndpointUri(String ip, int port, String name, String uri, String contextPath, String scheme) {
-        // build basic uri if none provided
-        String answer = uri;
-        if (answer == null) {
-            if (scheme == null) {
-                // use http/https by default if no scheme has been configured
-                if (port == 443) {
-                    scheme = "https";
-                } else {
-                    scheme = "http";
-                }
-            }
-            answer = scheme + "://" + ip + ":" + port;
-            if (contextPath != null) {
-                if (!contextPath.startsWith("/")) {
-                    contextPath = "/" + contextPath;
-                }
-
-                answer += contextPath;
-            }
-        } else {
-            // we have existing uri, then replace the serviceName with ip:port
-            if (answer.contains(name + ".host")) {
-                answer = answer.replaceFirst(name + "\\.host", ip);
-            }
-            if (answer.contains(name + ".port")) {
-                answer = answer.replaceFirst(name + "\\.port", "" + port);
-            }
-            if (answer.contains(name)) {
-                answer = answer.replaceFirst(name, ip + ":" + port);
-            }
-        }
-
-        LOG.debug("Camel endpoint uri: {} for calling service: {} on server {}:{}", answer, name, ip, port);
-        return answer;
-    }
-
+    protected abstract String buildCamelEndpointUri(String name, String host, Integer port, String uri, String contextPath, String scheme);
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/camel-core/src/main/resources/META-INF/services/org/apache/camel/cloud/static-service-discovery
----------------------------------------------------------------------
diff --git a/camel-core/src/main/resources/META-INF/services/org/apache/camel/cloud/static-service-discovery b/camel-core/src/main/resources/META-INF/services/org/apache/camel/cloud/static-service-discovery
new file mode 100644
index 0000000..5d2f763
--- /dev/null
+++ b/camel-core/src/main/resources/META-INF/services/org/apache/camel/cloud/static-service-discovery
@@ -0,0 +1,17 @@
+#
+# 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.impl.cloud.StaticServiceDiscoveryFactory
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/camel-core/src/main/resources/org/apache/camel/model/cloud/jaxb.index
----------------------------------------------------------------------
diff --git a/camel-core/src/main/resources/org/apache/camel/model/cloud/jaxb.index b/camel-core/src/main/resources/org/apache/camel/model/cloud/jaxb.index
new file mode 100644
index 0000000..e57f7e8
--- /dev/null
+++ b/camel-core/src/main/resources/org/apache/camel/model/cloud/jaxb.index
@@ -0,0 +1,28 @@
+## ------------------------------------------------------------------------
+## 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.
+## ------------------------------------------------------------------------
+ServiceCallDefinition
+ServiceCallConfigurationDefinition
+ServiceCallServiceDiscoveryConfiguration
+ServiceCallServiceFilterConfiguration
+ServiceCallServiceChooserConfiguration
+ServiceCallLoadBalancerConfiguration
+ConsulServiceCallServiceDiscoveryConfiguration
+DnsServiceCallServiceDiscoveryConfiguration
+EtcdServiceCallServiceDiscoveryConfiguration
+KubernetesServiceCallServiceDiscoveryConfiguration
+StaticServiceCallServiceDiscoveryConfiguration
+RibbonServiceCallLoadBalancerConfiguration

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/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
deleted file mode 100644
index 0b919fe..0000000
--- a/camel-core/src/main/resources/org/apache/camel/model/remote/jaxb.index
+++ /dev/null
@@ -1,23 +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.
-## ------------------------------------------------------------------------
-ConsulConfigurationDefinition
-DnsConfigurationDefinition
-EtcdConfigurationDefinition
-KubernetesConfigurationDefinition
-RibbonConfigurationDefinition
-ServiceCallDefinition
-ServiceCallConfigurationDefinition

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/camel-core/src/test/java/org/apache/camel/impl/cloud/CachingServiceCallServiceListStrategyTest.java
----------------------------------------------------------------------
diff --git a/camel-core/src/test/java/org/apache/camel/impl/cloud/CachingServiceCallServiceListStrategyTest.java b/camel-core/src/test/java/org/apache/camel/impl/cloud/CachingServiceCallServiceListStrategyTest.java
new file mode 100644
index 0000000..f17c000
--- /dev/null
+++ b/camel-core/src/test/java/org/apache/camel/impl/cloud/CachingServiceCallServiceListStrategyTest.java
@@ -0,0 +1,56 @@
+/**
+ * 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.impl.cloud;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+
+import org.apache.camel.cloud.ServiceDefinition;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class CachingServiceCallServiceListStrategyTest {
+    @Test
+    public void testCachingServiceDiscovery() throws Exception {
+        MyStrategy strategy = new MyStrategy();
+        CachingServiceDiscovery caching = CachingServiceDiscovery.wrap(strategy, 1, TimeUnit.SECONDS);
+
+        strategy.addServer(new DefaultServiceDefinition("noname", "localhost", 1111));
+        Assert.assertEquals(1, caching.getUpdatedListOfServices("noname").size());
+        strategy.addServer(new DefaultServiceDefinition("noname", "localhost", 1112));
+        Assert.assertEquals(1, caching.getUpdatedListOfServices("noname").size());
+
+        // Let the cache expire
+        Thread.sleep(1100);
+
+        Assert.assertEquals(2, caching.getUpdatedListOfServices("noname").size());
+    }
+
+    private class MyStrategy extends DefaultServiceDiscovery {
+        private List<ServiceDefinition> services = new ArrayList<>();
+
+        @Override
+        public List<ServiceDefinition> getUpdatedListOfServices(String name) {
+            return services;
+        }
+
+        public void addServer(ServiceDefinition service) {
+            services.add(service);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/camel-core/src/test/java/org/apache/camel/impl/remote/CachingServiceCallServiceListStrategyTest.java
----------------------------------------------------------------------
diff --git a/camel-core/src/test/java/org/apache/camel/impl/remote/CachingServiceCallServiceListStrategyTest.java b/camel-core/src/test/java/org/apache/camel/impl/remote/CachingServiceCallServiceListStrategyTest.java
deleted file mode 100644
index 0194c67..0000000
--- a/camel-core/src/test/java/org/apache/camel/impl/remote/CachingServiceCallServiceListStrategyTest.java
+++ /dev/null
@@ -1,56 +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.impl.remote;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.TimeUnit;
-
-import org.junit.Assert;
-import org.junit.Test;
-
-public class CachingServiceCallServiceListStrategyTest {
-
-    @Test
-    public void testCachingServiceList() throws Exception {
-        MyStrategy strategy = new MyStrategy();
-        CachingServiceCallServiceListStrategy<DefaultServiceCallServer> caching = CachingServiceCallServiceListStrategy.wrap(strategy, 1, TimeUnit.SECONDS);
-
-        strategy.addServer(new DefaultServiceCallServer("localhost", 1111));
-        Assert.assertEquals(1, caching.getUpdatedListOfServers("noname").size());
-        strategy.addServer(new DefaultServiceCallServer("localhost", 1112));
-        Assert.assertEquals(1, caching.getUpdatedListOfServers("noname").size());
-
-        // Let the cache expire
-        Thread.sleep(1100);
-
-        Assert.assertEquals(2, caching.getUpdatedListOfServers("noname").size());
-    }
-
-    private class MyStrategy extends DefaultServiceCallServerListStrategy<DefaultServiceCallServer> {
-        private List<DefaultServiceCallServer> servers = new ArrayList<>();
-
-        @Override
-        public List<DefaultServiceCallServer> getUpdatedListOfServers(String name) {
-            return servers;
-        }
-
-        public void addServer(DefaultServiceCallServer server) {
-            servers.add(server);
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/components/camel-blueprint/src/main/java/org/apache/camel/blueprint/BlueprintModelJAXBContextFactory.java
----------------------------------------------------------------------
diff --git a/components/camel-blueprint/src/main/java/org/apache/camel/blueprint/BlueprintModelJAXBContextFactory.java b/components/camel-blueprint/src/main/java/org/apache/camel/blueprint/BlueprintModelJAXBContextFactory.java
index dac0952..e366f35 100644
--- a/components/camel-blueprint/src/main/java/org/apache/camel/blueprint/BlueprintModelJAXBContextFactory.java
+++ b/components/camel-blueprint/src/main/java/org/apache/camel/blueprint/BlueprintModelJAXBContextFactory.java
@@ -47,6 +47,7 @@ public class BlueprintModelJAXBContextFactory implements ModelJAXBContextFactory
         classes.add(org.apache.camel.model.language.ExpressionDefinition.class);
         classes.add(org.apache.camel.model.loadbalancer.RoundRobinLoadBalancerDefinition.class);
         classes.add(org.apache.camel.model.rest.RestDefinition.class);
+        classes.add(org.apache.camel.model.cloud.ServiceCallDefinition.class);
 
         StringBuilder packages = new StringBuilder();
         for (Class<?> cl : classes) {


[09/10] camel git commit: CAMEL-10638: Refactor ServiceCall EIP

Posted by lb...@apache.org.
http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/camel-core/src/main/java/org/apache/camel/impl/cloud/ServiceCallConstants.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/impl/cloud/ServiceCallConstants.java b/camel-core/src/main/java/org/apache/camel/impl/cloud/ServiceCallConstants.java
new file mode 100644
index 0000000..6c09340
--- /dev/null
+++ b/camel-core/src/main/java/org/apache/camel/impl/cloud/ServiceCallConstants.java
@@ -0,0 +1,29 @@
+/**
+ * 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.impl.cloud;
+
+
+public interface ServiceCallConstants {
+    String SERVICE_CALL_SCHEME = "CamelServiceCallScheme";
+    String SERVICE_CALL_URI = "CamelServiceCallUri";
+    String SERVICE_CALL_CONTEXT_PATH = "CamelServiceCallContextPath";
+    String SERVICE_NAME = "CamelServiceCallServiceName";
+    String SERVICE_META = "CamelServiceCallServiceMeta";
+    String SERVICE_HOST = "CamelServiceCallServiceHost";
+    String SERVICE_PORT = "CamelServiceCallServicePort";
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/camel-core/src/main/java/org/apache/camel/impl/cloud/StaticServiceDiscovery.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/impl/cloud/StaticServiceDiscovery.java b/camel-core/src/main/java/org/apache/camel/impl/cloud/StaticServiceDiscovery.java
new file mode 100644
index 0000000..83fccc5
--- /dev/null
+++ b/camel-core/src/main/java/org/apache/camel/impl/cloud/StaticServiceDiscovery.java
@@ -0,0 +1,132 @@
+/**
+ * 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.impl.cloud;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+
+import org.apache.camel.cloud.ServiceDefinition;
+import org.apache.camel.util.StringHelper;
+
+/**
+ * A static list of known servers Camel Service Call EIP.
+ */
+public class StaticServiceDiscovery extends DefaultServiceDiscovery {
+
+    private final List<ServiceDefinition> servers;
+
+    public StaticServiceDiscovery() {
+        this.servers = new ArrayList<>();
+    }
+
+    public StaticServiceDiscovery(List<ServiceDefinition> servers) {
+        this.servers = new ArrayList<>(servers);
+    }
+
+    /**
+     * Set the servers.
+     *
+     * @param servers server in the format: [service@]host:port.
+     */
+    public void setServers(List<String> servers) {
+        this.servers.clear();
+        servers.forEach(this::addServer);
+    }
+
+    /**
+     * Set the servers.
+     *
+     * @param servers servers separated by comma in the format: [service@]host:port,[service@]host2:port,[service@]host3:port and so on.
+     */
+    public void setServers(String servers) {
+        this.servers.clear();
+        addServer(servers);
+    }
+
+    /**
+     * Add a server to the known list of servers.
+     */
+    public void addServer(ServiceDefinition server) {
+        servers.add(server);
+    }
+
+    /**
+     * Add a server to the known list of servers.
+     * @param serverString servers separated by comma in the format: [service@]host:port,[service@]host2:port,[service@]host3:port and so on.
+     */
+    public void addServer(String serverString) {
+        String[] parts = serverString.split(",");
+        for (String part : parts) {
+            String service = StringHelper.before(part, "@");
+            if (service != null) {
+                part = StringHelper.after(service, "@");
+            }
+            String host = StringHelper.before(part, ":");
+            String port = StringHelper.after(part, ":");
+
+            addServer(service, host, Integer.valueOf(port));
+        }
+    }
+
+    /**
+     * Add a server to the known list of servers.
+     */
+    public void addServer(String host, int port) {
+        addServer(null, host, port, null);
+    }
+
+    /**
+     * Add a server to the known list of servers.
+     */
+    public void addServer(String name, String host, int port) {
+        addServer(name, host, port, null);
+    }
+
+    /**
+     * Add a server to the known list of servers.
+     */
+    public void addServer(String name, String host, int port, Map<String, String> meta) {
+        servers.add(new DefaultServiceDefinition(name, host, port, meta));
+    }
+
+    /**
+     * Remove an existing server from the list of known servers.
+     */
+    public void removeServer(String host, int port) {
+        servers.removeIf(
+            s -> Objects.equals(host, s.getHost()) && port == s.getPort()
+        );
+    }
+
+    /**
+     * Remove an existing server from the list of known servers.
+     */
+    public void removeServer(String name, String host, int port) {
+        servers.removeIf(
+            s -> Objects.equals(name, s.getName()) && Objects.equals(host, s.getHost()) && port == s.getPort()
+        );
+    }
+
+    @Override
+    public List<ServiceDefinition> getUpdatedListOfServices(String name) {
+        return Collections.unmodifiableList(servers);
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/camel-core/src/main/java/org/apache/camel/impl/cloud/StaticServiceDiscoveryFactory.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/impl/cloud/StaticServiceDiscoveryFactory.java b/camel-core/src/main/java/org/apache/camel/impl/cloud/StaticServiceDiscoveryFactory.java
new file mode 100644
index 0000000..eb4d983
--- /dev/null
+++ b/camel-core/src/main/java/org/apache/camel/impl/cloud/StaticServiceDiscoveryFactory.java
@@ -0,0 +1,57 @@
+/**
+ * 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.impl.cloud;
+
+import java.util.List;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.cloud.ServiceDiscovery;
+import org.apache.camel.cloud.ServiceDiscoveryFactory;
+
+public class StaticServiceDiscoveryFactory implements ServiceDiscoveryFactory {
+
+    private List<String> servers;
+
+    public StaticServiceDiscoveryFactory() {
+    }
+
+    // *************************************************************************
+    // Properties
+    // *************************************************************************
+
+    public List<String> getServers() {
+        return servers;
+    }
+
+    public void setServers(List<String> servers) {
+        this.servers = servers;
+    }
+
+    // *************************************************************************
+    // Factory
+    // *************************************************************************
+
+    @Override
+    public ServiceDiscovery newInstance(CamelContext camelContext) throws Exception {
+        StaticServiceDiscovery serviceDiscovery = new StaticServiceDiscovery();
+        if (servers != null) {
+            serviceDiscovery.setServers(servers);
+        }
+
+        return serviceDiscovery;
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/camel-core/src/main/java/org/apache/camel/impl/remote/AbstractServiceCallProcessorFactory.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/impl/remote/AbstractServiceCallProcessorFactory.java b/camel-core/src/main/java/org/apache/camel/impl/remote/AbstractServiceCallProcessorFactory.java
deleted file mode 100644
index 7f0a0af..0000000
--- a/camel-core/src/main/java/org/apache/camel/impl/remote/AbstractServiceCallProcessorFactory.java
+++ /dev/null
@@ -1,42 +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.impl.remote;
-
-import org.apache.camel.Processor;
-import org.apache.camel.model.ProcessorDefinition;
-import org.apache.camel.model.remote.ServiceCallDefinition;
-import org.apache.camel.model.remote.ServiceCallProcessorFactory;
-import org.apache.camel.spi.RouteContext;
-
-public abstract class AbstractServiceCallProcessorFactory implements ServiceCallProcessorFactory {
-    @Override
-    public Processor createChildProcessor(RouteContext routeContext, ProcessorDefinition<?> definition, boolean mandatory) throws Exception {
-        // not in use
-        return null;
-    }
-
-    @Override
-    public Processor createProcessor(RouteContext routeContext, ProcessorDefinition<?> definition) throws Exception {
-        return definition instanceof ServiceCallDefinition
-            ? createProcessor(routeContext, (ServiceCallDefinition) definition)
-            : null;
-    }
-
-    protected abstract Processor createProcessor(RouteContext routeContext, ServiceCallDefinition definition) throws Exception;
-
-}

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/camel-core/src/main/java/org/apache/camel/impl/remote/CachingServiceCallServiceListStrategy.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/impl/remote/CachingServiceCallServiceListStrategy.java b/camel-core/src/main/java/org/apache/camel/impl/remote/CachingServiceCallServiceListStrategy.java
deleted file mode 100644
index 1ad9b74..0000000
--- a/camel-core/src/main/java/org/apache/camel/impl/remote/CachingServiceCallServiceListStrategy.java
+++ /dev/null
@@ -1,105 +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.impl.remote;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import java.util.concurrent.TimeUnit;
-
-import org.apache.camel.spi.ServiceCallServer;
-import org.apache.camel.spi.ServiceCallServerListStrategy;
-import org.apache.camel.util.ObjectHelper;
-
-public class CachingServiceCallServiceListStrategy<T extends ServiceCallServer> implements ServiceCallServerListStrategy<T> {
-    private final ServiceCallServerListStrategy<T> delegate;
-    private List<T> servers;
-    private long lastUpdate;
-    private long timeout;
-
-    public CachingServiceCallServiceListStrategy(ServiceCallServerListStrategy<T> delegate) {
-        this.delegate = ObjectHelper.notNull(delegate, "delegate");
-        this.lastUpdate = 0;
-        this.servers = Collections.emptyList();
-        this.timeout = 60 * 1000; // 1 min;
-    }
-
-    public void setTimeout(long timeout) {
-        this.timeout = timeout;
-    }
-
-    public void setTimeout(long timeout, TimeUnit unit) {
-        this.timeout = unit.toMillis(timeout);
-    }
-
-    public long getTimeout() {
-        return timeout;
-    }
-
-    public CachingServiceCallServiceListStrategy<T> timeout(long timeout) {
-        setTimeout(timeout);
-        return this;
-    }
-
-    public CachingServiceCallServiceListStrategy<T> timeout(long timeout, TimeUnit unit) {
-        setTimeout(timeout, unit);
-        return this;
-    }
-
-    @Override
-    public List<T> getInitialListOfServers(String name) {
-        return delegate.getInitialListOfServers(name);
-    }
-
-    @Override
-    public List<T> getUpdatedListOfServers(String name) {
-        long now = System.currentTimeMillis();
-
-        if (lastUpdate == 0 || now > lastUpdate + timeout) {
-            List<T> updatedList = delegate.getUpdatedListOfServers(name);
-            if (updatedList.isEmpty()) {
-                servers = Collections.emptyList();
-            } else {
-                // List is copied as the delegated ServiceCallServerListStrategy
-                // may update the list
-                servers = Collections.unmodifiableList(new ArrayList<>(updatedList));
-            }
-
-            lastUpdate = now;
-        }
-
-        return servers;
-    }
-
-    // **********************
-    // Helpers
-    // **********************
-
-    public static <S extends ServiceCallServer> CachingServiceCallServiceListStrategy<S> wrap(ServiceCallServerListStrategy<S> delegate) {
-        return new CachingServiceCallServiceListStrategy<>(delegate);
-    }
-
-    public static <S extends ServiceCallServer> CachingServiceCallServiceListStrategy<S> wrap(ServiceCallServerListStrategy<S> delegate, long timeout) {
-        return new CachingServiceCallServiceListStrategy<>(delegate)
-            .timeout(timeout);
-    }
-
-    public static <S extends ServiceCallServer> CachingServiceCallServiceListStrategy<S> wrap(ServiceCallServerListStrategy<S> delegate, long timeout, TimeUnit unit) {
-        return new CachingServiceCallServiceListStrategy<>(delegate)
-            .timeout(timeout, unit);
-    }
-}

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/camel-core/src/main/java/org/apache/camel/impl/remote/DefaultServiceCallExpression.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/impl/remote/DefaultServiceCallExpression.java b/camel-core/src/main/java/org/apache/camel/impl/remote/DefaultServiceCallExpression.java
deleted file mode 100644
index 8d790b2..0000000
--- a/camel-core/src/main/java/org/apache/camel/impl/remote/DefaultServiceCallExpression.java
+++ /dev/null
@@ -1,48 +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.impl.remote;
-
-import org.apache.camel.Exchange;
-import org.apache.camel.support.ServiceCallExpressionSupport;
-import org.apache.camel.util.ExchangeHelper;
-
-public class DefaultServiceCallExpression extends ServiceCallExpressionSupport {
-    private final String ipHeader;
-    private final String portHeader;
-
-    public DefaultServiceCallExpression(String name, String scheme, String contextPath, String uri) {
-        this(name, scheme, contextPath, uri, ServiceCallConstants.SERVER_IP, ServiceCallConstants.SERVER_PORT);
-    }
-
-    public DefaultServiceCallExpression(String name, String scheme, String contextPath, String uri, String ipHeader, String portHeader) {
-        super(name, scheme, contextPath, uri);
-
-        this.ipHeader = ipHeader;
-        this.portHeader = portHeader;
-    }
-
-    @Override
-    public String getIp(Exchange exchange) throws Exception {
-        return ExchangeHelper.getMandatoryHeader(exchange, ipHeader, String.class);
-    }
-
-    @Override
-    public int getPort(Exchange exchange) throws Exception {
-        return ExchangeHelper.getMandatoryHeader(exchange, portHeader, int.class);
-    }
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/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
deleted file mode 100644
index 9340406..0000000
--- a/camel-core/src/main/java/org/apache/camel/impl/remote/DefaultServiceCallProcessor.java
+++ /dev/null
@@ -1,250 +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.impl.remote;
-
-import java.util.List;
-import java.util.concurrent.RejectedExecutionException;
-
-import org.apache.camel.AsyncCallback;
-import org.apache.camel.AsyncProcessor;
-import org.apache.camel.CamelContext;
-import org.apache.camel.CamelContextAware;
-import org.apache.camel.Exchange;
-import org.apache.camel.ExchangePattern;
-import org.apache.camel.Expression;
-import org.apache.camel.Traceable;
-import org.apache.camel.processor.SendDynamicProcessor;
-import org.apache.camel.spi.IdAware;
-import org.apache.camel.spi.ServiceCallLoadBalancer;
-import org.apache.camel.spi.ServiceCallServer;
-import org.apache.camel.spi.ServiceCallServerListStrategy;
-import org.apache.camel.support.ServiceSupport;
-import org.apache.camel.util.AsyncProcessorHelper;
-import org.apache.camel.util.ObjectHelper;
-import org.apache.camel.util.ServiceHelper;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class DefaultServiceCallProcessor<S extends ServiceCallServer> extends ServiceSupport implements AsyncProcessor, CamelContextAware, Traceable, IdAware {
-    private static final Logger LOG = LoggerFactory.getLogger(DefaultServiceCallProcessor.class);
-
-    private final ExchangePattern exchangePattern;
-    private final String name;
-    private final String scheme;
-    private final String uri;
-    private final String contextPath;
-    private CamelContext camelContext;
-    private String id;
-    private ServiceCallServerListStrategy<S> serverListStrategy;
-    private ServiceCallLoadBalancer<S> loadBalancer;
-    private Expression serviceCallExpression;
-    private SendDynamicProcessor processor;
-
-    public DefaultServiceCallProcessor(String name, String scheme, String uri, ExchangePattern exchangePattern) {
-        this.uri = uri;
-        this.exchangePattern = exchangePattern;
-
-        // setup from the provided name which can contain scheme and context-path information as well
-        String serviceName;
-        if (name.contains("/")) {
-            serviceName = ObjectHelper.before(name, "/");
-            this.contextPath = ObjectHelper.after(name, "/");
-        } else if (name.contains("?")) {
-            serviceName = ObjectHelper.before(name, "?");
-            this.contextPath = ObjectHelper.after(name, "?");
-        } else {
-            serviceName = name;
-            this.contextPath = null;
-        }
-        if (serviceName.contains(":")) {
-            this.scheme = ObjectHelper.before(serviceName, ":");
-            this.name = ObjectHelper.after(serviceName, ":");
-        } else {
-            this.scheme = scheme;
-            this.name = serviceName;
-        }
-
-        this.serviceCallExpression = new DefaultServiceCallExpression(
-            this.name,
-            this.scheme,
-            this.contextPath,
-            this.uri);
-    }
-
-    @Override
-    public CamelContext getCamelContext() {
-        return camelContext;
-    }
-
-    @Override
-    public void setCamelContext(CamelContext camelContext) {
-        this.camelContext = camelContext;
-    }
-
-    @Override
-    public String getId() {
-        return id;
-    }
-
-    @Override
-    public void setId(String id) {
-        this.id = id;
-    }
-
-    @Override
-    public String getTraceLabel() {
-        return id;
-    }
-
-    public String getName() {
-        return name;
-    }
-
-    public String getScheme() {
-        return scheme;
-    }
-
-    public String getContextPath() {
-        return contextPath;
-    }
-
-    public String getUri() {
-        return uri;
-    }
-
-    public ExchangePattern getExchangePattern() {
-        return exchangePattern;
-    }
-
-    public ServiceCallLoadBalancer<S> getLoadBalancer() {
-        return loadBalancer;
-    }
-
-    public void setLoadBalancer(ServiceCallLoadBalancer<S> loadBalancer) {
-        this.loadBalancer = loadBalancer;
-    }
-
-    public DefaultServiceCallProcessor loadBalancer(ServiceCallLoadBalancer<S> loadBalancer) {
-        setLoadBalancer(loadBalancer);
-        return this;
-    }
-
-    public ServiceCallServerListStrategy<S> getServerListStrategy() {
-        return serverListStrategy;
-    }
-
-    public void setServerListStrategy(ServiceCallServerListStrategy<S> serverListStrategy) {
-        this.serverListStrategy = serverListStrategy;
-    }
-
-    public DefaultServiceCallProcessor serverListStrategy(ServiceCallServerListStrategy<S> serverListStrategy) {
-        setServerListStrategy(serverListStrategy);
-        return this;
-    }
-
-    public void setServiceCallExpression(Expression serviceCallExpression) {
-        this.serviceCallExpression = serviceCallExpression;
-    }
-
-    public Expression getServiceCallExpression() {
-        return serviceCallExpression;
-    }
-
-    public DefaultServiceCallProcessor serviceCallExpression(Expression serviceCallExpression) {
-        setServiceCallExpression(serviceCallExpression);
-        return this;
-    }
-
-    public AsyncProcessor getProcessor() {
-        return processor;
-    }
-
-    @Override
-    protected void doStart() throws Exception {
-        ObjectHelper.notEmpty(getName(), "name", "serviceName");
-        ObjectHelper.notNull(camelContext, "camelContext");
-        ObjectHelper.notNull(serviceCallExpression, "serviceCallExpression");
-
-        LOG.info("ServiceCall with service name: {} is using load balancer: {} and service discovery: {}",
-            name, loadBalancer, serverListStrategy);
-
-        processor = new SendDynamicProcessor(uri, serviceCallExpression);
-        processor.setCamelContext(getCamelContext());
-        if (exchangePattern != null) {
-            processor.setPattern(exchangePattern);
-        }
-
-        ServiceHelper.startServices(serverListStrategy, processor);
-    }
-
-    @Override
-    protected void doStop() throws Exception {
-        ServiceHelper.stopServices(processor, serverListStrategy);
-    }
-
-    @Override
-    public void process(Exchange exchange) throws Exception {
-        AsyncProcessorHelper.process(this, exchange);
-    }
-
-    @Override
-    public boolean process(Exchange exchange, AsyncCallback callback) {
-        final String serviceName = exchange.getIn().getHeader(ServiceCallConstants.SERVICE_NAME, name, String.class);
-        final ServiceCallServer server = chooseServer(exchange, serviceName);
-
-        if (exchange.getException() != null) {
-            callback.done(true);
-            return true;
-        }
-
-        String ip = server.getIp();
-        int port = server.getPort();
-        LOG.debug("Service {} active at server: {}:{}", name, ip, port);
-
-        // set selected server as header
-        exchange.getIn().setHeader(ServiceCallConstants.SERVER_IP, ip);
-        exchange.getIn().setHeader(ServiceCallConstants.SERVER_PORT, port);
-        exchange.getIn().setHeader(ServiceCallConstants.SERVICE_NAME, serviceName);
-
-        // use the dynamic send processor to call the service
-        return processor.process(exchange, callback);
-    }
-
-    protected S chooseServer(Exchange exchange, String serviceName) {
-        ObjectHelper.notNull(serverListStrategy, "serverListStrategy");
-        ObjectHelper.notNull(loadBalancer, "loadBalancer");
-
-        S server = null;
-
-        try {
-            List<S> servers = serverListStrategy.getUpdatedListOfServers(serviceName);
-            if (servers == null || servers.isEmpty()) {
-                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);
-        }
-
-        return server;
-    }
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/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
deleted file mode 100644
index 99a0844..0000000
--- a/camel-core/src/main/java/org/apache/camel/impl/remote/DefaultServiceCallProcessorFactory.java
+++ /dev/null
@@ -1,289 +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.impl.remote;
-
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Optional;
-import java.util.Set;
-
-import org.apache.camel.CamelContextAware;
-import org.apache.camel.ExchangePattern;
-import org.apache.camel.Processor;
-import org.apache.camel.model.PropertyDefinition;
-import org.apache.camel.model.remote.ServiceCallConfigurationDefinition;
-import org.apache.camel.model.remote.ServiceCallDefinition;
-import org.apache.camel.spi.RouteContext;
-import org.apache.camel.spi.ServiceCallLoadBalancer;
-import org.apache.camel.spi.ServiceCallServer;
-import org.apache.camel.spi.ServiceCallServerListStrategy;
-import org.apache.camel.util.CamelContextHelper;
-import org.apache.camel.util.IntrospectionSupport;
-import org.apache.camel.util.ObjectHelper;
-
-public abstract class DefaultServiceCallProcessorFactory<C, S extends ServiceCallServer> extends AbstractServiceCallProcessorFactory {
-    protected Processor createProcessor(RouteContext routeContext, ServiceCallDefinition definition) throws Exception {
-        return createProcessor(routeContext, definition, createConfiguration(routeContext));
-    }
-
-    protected Processor createProcessor(RouteContext routeContext, ServiceCallDefinition definition, C cfg) throws Exception {
-        String name = definition.getName();
-        String uri = definition.getUri();
-        ExchangePattern mep = definition.getPattern();
-
-        ServiceCallConfigurationDefinition config = definition.getServiceCallConfiguration();
-        ServiceCallConfigurationDefinition configRef = null;
-        if (definition.getServiceCallConfigurationRef() != null) {
-            // lookup in registry first
-            configRef = CamelContextHelper.lookup(routeContext.getCamelContext(), definition.getServiceCallConfigurationRef(), ServiceCallConfigurationDefinition.class);
-            if (configRef == null) {
-                // and fallback as service configuration
-                routeContext.getCamelContext().getServiceCallConfiguration(definition.getServiceCallConfigurationRef(), ServiceCallConfigurationDefinition.class);
-            }
-        }
-
-        // if no configuration explicit configured then use default
-        if (config == null && configRef == null) {
-            config = routeContext.getCamelContext().getServiceCallConfiguration(null, ServiceCallConfigurationDefinition.class);
-        }
-        if (config == null) {
-            // if no default then try to find if there configuration in the registry of the given type
-            Set<ServiceCallConfigurationDefinition> set = routeContext.getCamelContext().getRegistry().findByType(ServiceCallConfigurationDefinition.class);
-            if (set.size() == 1) {
-                config = set.iterator().next();
-            }
-        }
-
-        if (config == null && configRef == null) {
-            throw new IllegalStateException("The ServiceCall: " + definition + " must be configured before it can be used.");
-        }
-
-        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);
-        }
-
-        // lookup the load balancer to use (configured on EIP takes precedence vs configured on configuration)
-        ServiceCallLoadBalancer lb = configureLoadBalancer(cfg, routeContext, definition);
-        if (lb == null && config != null) {
-            lb = configureLoadBalancer(cfg, routeContext, config);
-        }
-        if (lb == null && configRef != null) {
-            lb = configureLoadBalancer(cfg, routeContext, configRef);
-        }
-
-        // lookup the server list strategy to use (configured on EIP takes precedence vs configured on configuration)
-        ServiceCallServerListStrategy sl = configureServerListStrategy(cfg, routeContext, definition);
-        if (sl == null && config != null) {
-            sl = configureServerListStrategy(cfg, routeContext, config);
-        }
-        if (sl == null && configRef != null) {
-            sl = configureServerListStrategy(cfg, routeContext, configRef);
-        }
-
-        // The component is used to configure what the default scheme to use (eg camel component name).
-        // The component configured on EIP takes precedence vs configured on configuration.
-        String component = definition.getComponent();
-        if (component == null) {
-            component = config != null ? config.getComponent() : null;
-            if (component == null && configRef != null) {
-                component = configRef.getComponent();
-            }
-        }
-
-        if (ObjectHelper.isNotEmpty(lb) && lb instanceof CamelContextAware) {
-            ((CamelContextAware)lb).setCamelContext(routeContext.getCamelContext());
-        }
-
-        if (ObjectHelper.isNotEmpty(sl) && sl instanceof CamelContextAware) {
-            ((CamelContextAware)sl).setCamelContext(routeContext.getCamelContext());
-        }
-
-        if (sl == null) {
-            sl = createDefaultServerListStrategy(cfg);
-        }
-        if (lb == null) {
-            lb = createDefaultLoadBalancer(cfg);
-        }
-
-        Map<String, String> properties = configureProperties(routeContext, config, configRef);
-
-        DefaultServiceCallProcessor processor = createProcessor(name, component, uri, mep, cfg, properties);
-        if (sl != null && processor.getServerListStrategy() == null) {
-            processor.setServerListStrategy(sl);
-        }
-        if (lb != null && processor.getLoadBalancer() == null) {
-            processor.setLoadBalancer(lb);
-        }
-
-        return processor;
-    }
-
-    // *************************************************************************
-    // Helpers
-    // *************************************************************************
-
-    protected Map<String, String> configureProperties(
-            RouteContext routeContext, ServiceCallConfigurationDefinition config, ServiceCallConfigurationDefinition configRef) throws Exception {
-
-        Map<String, String> answer = new HashMap<>();
-        if (config != null && config.getProperties() != null) {
-            for (PropertyDefinition prop : config.getProperties()) {
-                // support property placeholders
-                String key = CamelContextHelper.parseText(routeContext.getCamelContext(), prop.getKey());
-                String value = CamelContextHelper.parseText(routeContext.getCamelContext(), prop.getValue());
-                answer.put(key, value);
-            }
-        }
-        if (configRef != null && configRef.getProperties() != null) {
-            for (PropertyDefinition prop : configRef.getProperties()) {
-                // support property placeholders
-                String key = CamelContextHelper.parseText(routeContext.getCamelContext(), prop.getKey());
-                String value = CamelContextHelper.parseText(routeContext.getCamelContext(), prop.getValue());
-                answer.put(key, value);
-            }
-        }
-        return answer;
-    }
-
-    protected ServiceCallLoadBalancer configureLoadBalancer(C conf, RouteContext routeContext, ServiceCallDefinition sd)  throws Exception {
-        ServiceCallLoadBalancer lb = null;
-        String ref;
-
-        if (sd != null) {
-            lb = sd.getLoadBalancer();
-            ref = sd.getLoadBalancerRef();
-            if (lb == null && ref != null) {
-                lb = builtInLoadBalancer(
-                        conf,
-                        ref)
-                    .orElseGet(() -> CamelContextHelper.mandatoryLookup(
-                        routeContext.getCamelContext(),
-                        ref,
-                        ServiceCallLoadBalancer.class)
-                );
-            }
-        }
-
-        return lb;
-    }
-
-    protected ServiceCallLoadBalancer configureLoadBalancer(C conf, RouteContext routeContext, ServiceCallConfigurationDefinition config)  throws Exception {
-        ServiceCallLoadBalancer lb = config.getLoadBalancer();
-        String ref = config.getLoadBalancerRef();
-        if (lb == null && ref != null) {
-            lb = builtInLoadBalancer(
-                    conf,
-                    ref)
-                .orElseGet(() ->CamelContextHelper.mandatoryLookup(
-                    routeContext.getCamelContext(),
-                    ref,
-                    ServiceCallLoadBalancer.class)
-            );
-        }
-        return lb;
-    }
-
-    protected ServiceCallServerListStrategy configureServerListStrategy(C conf, RouteContext routeContext, ServiceCallDefinition sd)  throws Exception {
-        ServiceCallServerListStrategy sl = null;
-        String ref;
-        if (sd != null) {
-            sl = sd.getServerListStrategy();
-            ref = sd.getServerListStrategyRef();
-            if (sl == null && ref != null) {
-                sl = builtInServerListStrategy(
-                        conf,
-                        ref)
-                    .orElseGet(() -> CamelContextHelper.mandatoryLookup(
-                        routeContext.getCamelContext(),
-                        ref,
-                        ServiceCallServerListStrategy.class)
-                );
-            }
-        }
-
-        return sl;
-    }
-
-    protected ServiceCallServerListStrategy configureServerListStrategy(C conf, RouteContext routeContext, ServiceCallConfigurationDefinition config)  throws Exception {
-        ServiceCallServerListStrategy sl = config.getServerListStrategy();
-        String ref = config.getServerListStrategyRef();
-        if (sl == null && ref != null) {
-            sl = builtInServerListStrategy(
-                    conf,
-                    ref)
-                .orElseGet(() -> CamelContextHelper.mandatoryLookup(
-                    routeContext.getCamelContext(),
-                    ref,
-                    ServiceCallServerListStrategy.class)
-            );
-        }
-
-        return sl;
-    }
-
-    // special for ref is referring to built-in load balancers
-    protected Optional<ServiceCallLoadBalancer> builtInLoadBalancer(C conf, String name)  throws Exception {
-        ServiceCallLoadBalancer lb = null;
-        if (ObjectHelper.equal(name, "random", true)) {
-            lb = new RandomServiceCallLoadBalancer();
-        } else if (ObjectHelper.equal(name, "roundrobin", true)) {
-            lb = new RoundRobinServiceCallLoadBalancer();
-        }
-
-        return Optional.ofNullable(lb);
-    }
-
-    // special for ref is referring to built-in server list strategies
-    protected Optional<ServiceCallServerListStrategy> builtInServerListStrategy(C conf, String name)  throws Exception {
-        return Optional.empty();
-    }
-
-    protected DefaultServiceCallProcessor createProcessor(
-            String name,
-            String component,
-            String uri,
-            ExchangePattern mep,
-            C conf,
-            Map<String, String> properties) throws Exception {
-
-        return new DefaultServiceCallProcessor(name, component, uri, mep);
-    }
-
-    // TODO: rename
-    protected abstract C createConfiguration(RouteContext routeContext) throws Exception;
-
-    // *************************************************************************
-    // Defaults
-    // *************************************************************************
-
-    protected ServiceCallLoadBalancer<S> createDefaultLoadBalancer(C conf) throws Exception {
-        return new RoundRobinServiceCallLoadBalancer<>();
-    }
-
-    protected ServiceCallServerListStrategy<S> createDefaultServerListStrategy(C conf) throws Exception {
-        return null;
-    }
-}

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/camel-core/src/main/java/org/apache/camel/impl/remote/DefaultServiceCallServer.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/impl/remote/DefaultServiceCallServer.java b/camel-core/src/main/java/org/apache/camel/impl/remote/DefaultServiceCallServer.java
deleted file mode 100644
index 30aac8d..0000000
--- a/camel-core/src/main/java/org/apache/camel/impl/remote/DefaultServiceCallServer.java
+++ /dev/null
@@ -1,62 +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.impl.remote;
-
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Map;
-
-import org.apache.camel.spi.ServiceCallServer;
-
-public class DefaultServiceCallServer implements ServiceCallServer {
-
-    private final String ip;
-    private final int port;
-    private final Map<String, String> meta;
-
-    public DefaultServiceCallServer(String ip, int port) {
-        this.ip = ip;
-        this.port = port;
-        this.meta = Collections.emptyMap();
-    }
-
-    public DefaultServiceCallServer(String ip, int port, Map<String, String> meta) {
-        this.ip = ip;
-        this.port = port;
-        this.meta = Collections.unmodifiableMap(new HashMap<>(meta));
-    }
-
-    @Override
-    public String getIp() {
-        return ip;
-    }
-
-    @Override
-    public int getPort() {
-        return port;
-    }
-
-    @Override
-    public Map<String, String> getMetadata() {
-        return this.meta;
-    }
-
-    @Override
-    public String toString() {
-        return "DefaultServiceCallServer[" + ip + ":" + port + "]";
-    }
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/camel-core/src/main/java/org/apache/camel/impl/remote/DefaultServiceCallServerListStrategy.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/impl/remote/DefaultServiceCallServerListStrategy.java b/camel-core/src/main/java/org/apache/camel/impl/remote/DefaultServiceCallServerListStrategy.java
deleted file mode 100644
index 48f8b22..0000000
--- a/camel-core/src/main/java/org/apache/camel/impl/remote/DefaultServiceCallServerListStrategy.java
+++ /dev/null
@@ -1,63 +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.impl.remote;
-
-import java.util.Collections;
-import java.util.List;
-
-import org.apache.camel.CamelContext;
-import org.apache.camel.CamelContextAware;
-import org.apache.camel.spi.ServiceCallServer;
-import org.apache.camel.spi.ServiceCallServerListStrategy;
-import org.apache.camel.support.ServiceSupport;
-
-
-public class DefaultServiceCallServerListStrategy<T extends ServiceCallServer>
-        extends ServiceSupport implements ServiceCallServerListStrategy<T>, CamelContextAware {
-
-    private CamelContext camelContext;
-
-    @Override
-    public List<T> getInitialListOfServers(String name) {
-        return Collections.emptyList();
-    }
-
-    @Override
-    public List<T> getUpdatedListOfServers(String name) {
-        return Collections.emptyList();
-    }
-
-    @Override
-    public void setCamelContext(CamelContext camelContext) {
-        this.camelContext = camelContext;
-    }
-
-    @Override
-    public CamelContext getCamelContext() {
-        return camelContext;
-    }
-
-    @Override
-    protected void doStart() throws Exception {
-        // nop
-    }
-
-    @Override
-    protected void doStop() throws Exception {
-        // nop
-    }
-}

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/camel-core/src/main/java/org/apache/camel/impl/remote/RandomServiceCallLoadBalancer.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/impl/remote/RandomServiceCallLoadBalancer.java b/camel-core/src/main/java/org/apache/camel/impl/remote/RandomServiceCallLoadBalancer.java
deleted file mode 100644
index a9d7af2..0000000
--- a/camel-core/src/main/java/org/apache/camel/impl/remote/RandomServiceCallLoadBalancer.java
+++ /dev/null
@@ -1,44 +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.impl.remote;
-
-import java.util.List;
-import java.util.Random;
-
-import org.apache.camel.spi.ServiceCallLoadBalancer;
-import org.apache.camel.spi.ServiceCallServer;
-
-public class RandomServiceCallLoadBalancer implements ServiceCallLoadBalancer<ServiceCallServer> {
-    private final Random random;
-
-    public RandomServiceCallLoadBalancer() {
-        this.random = new Random();
-    }
-
-    @Override
-    public ServiceCallServer chooseServer(List<ServiceCallServer> servers) {
-        int size = servers.size();
-        int index = (size > 1) ? random.nextInt(size) : 0;
-
-        return servers.get(index);
-    }
-
-    @Override
-    public String toString() {
-        return "RandomServiceCallLoadBalancer";
-    }
-}

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/camel-core/src/main/java/org/apache/camel/impl/remote/RoundRobinServiceCallLoadBalancer.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/impl/remote/RoundRobinServiceCallLoadBalancer.java b/camel-core/src/main/java/org/apache/camel/impl/remote/RoundRobinServiceCallLoadBalancer.java
deleted file mode 100644
index 966a6ae..0000000
--- a/camel-core/src/main/java/org/apache/camel/impl/remote/RoundRobinServiceCallLoadBalancer.java
+++ /dev/null
@@ -1,41 +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.impl.remote;
-
-import java.util.List;
-
-import org.apache.camel.spi.ServiceCallLoadBalancer;
-import org.apache.camel.spi.ServiceCallServer;
-
-public class RoundRobinServiceCallLoadBalancer<S extends ServiceCallServer> implements ServiceCallLoadBalancer<S> {
-    private int counter = -1;
-
-    @Override
-    public S chooseServer(List<S> servers) {
-        int size = servers.size();
-        if (++counter >= size || size == 1) {
-            counter = 0;
-        }
-        return servers.get(counter);
-    }
-
-    @Override
-    public String toString() {
-        return "RoundRobinServiceCallLoadBalancer";
-    }
-}

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/camel-core/src/main/java/org/apache/camel/impl/remote/ServiceCallConstants.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/impl/remote/ServiceCallConstants.java b/camel-core/src/main/java/org/apache/camel/impl/remote/ServiceCallConstants.java
deleted file mode 100644
index 3d3fb26..0000000
--- a/camel-core/src/main/java/org/apache/camel/impl/remote/ServiceCallConstants.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.impl.remote;
-
-
-public interface ServiceCallConstants {
-    String SERVICE_NAME = "CamelServiceCallServiceName";
-    String SERVER_IP = "CamelServiceCallServerIp";
-    String SERVER_PORT = "CamelServiceCallServerPort";
-}

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/camel-core/src/main/java/org/apache/camel/impl/remote/package.html
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/impl/remote/package.html b/camel-core/src/main/java/org/apache/camel/impl/remote/package.html
deleted file mode 100644
index 0cb7249..0000000
--- a/camel-core/src/main/java/org/apache/camel/impl/remote/package.html
+++ /dev/null
@@ -1,25 +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.
--->
-<html>
-<head>
-</head>
-<body>
-
-Remote <a href="http://camel.apache.org/servicecall-eip.html">service call</a> support classes.
-
-</body>
-</html>

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/camel-core/src/main/java/org/apache/camel/model/Constants.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/model/Constants.java b/camel-core/src/main/java/org/apache/camel/model/Constants.java
index eaec06e..d6bbf3b 100644
--- a/camel-core/src/main/java/org/apache/camel/model/Constants.java
+++ b/camel-core/src/main/java/org/apache/camel/model/Constants.java
@@ -26,11 +26,11 @@ public final class Constants {
     public static final String JAXB_CONTEXT_PACKAGES = ""
         + "org.apache.camel:"
         + "org.apache.camel.model:"
+        + "org.apache.camel.model.cloud:"
         + "org.apache.camel.model.config:"
         + "org.apache.camel.model.dataformat:"
         + "org.apache.camel.model.language:"
         + "org.apache.camel.model.loadbalancer:"
-        + "org.apache.camel.model.remote:"
         + "org.apache.camel.model.rest:"
         + "org.apache.camel.model.transformer";
 

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/camel-core/src/main/java/org/apache/camel/model/ProcessorDefinition.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/model/ProcessorDefinition.java b/camel-core/src/main/java/org/apache/camel/model/ProcessorDefinition.java
index ba5fd37..bf2b315 100644
--- a/camel-core/src/main/java/org/apache/camel/model/ProcessorDefinition.java
+++ b/camel-core/src/main/java/org/apache/camel/model/ProcessorDefinition.java
@@ -51,11 +51,11 @@ import org.apache.camel.builder.ExpressionBuilder;
 import org.apache.camel.builder.ExpressionClause;
 import org.apache.camel.builder.ProcessClause;
 import org.apache.camel.builder.ProcessorBuilder;
+import org.apache.camel.model.cloud.ServiceCallDefinition;
 import org.apache.camel.model.language.ConstantExpression;
 import org.apache.camel.model.language.ExpressionDefinition;
 import org.apache.camel.model.language.LanguageExpression;
 import org.apache.camel.model.language.SimpleExpression;
-import org.apache.camel.model.remote.ServiceCallDefinition;
 import org.apache.camel.model.rest.RestDefinition;
 import org.apache.camel.processor.InterceptEndpointProcessor;
 import org.apache.camel.processor.Pipeline;

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/camel-core/src/main/java/org/apache/camel/model/cloud/ConsulServiceCallServiceDiscoveryConfiguration.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/model/cloud/ConsulServiceCallServiceDiscoveryConfiguration.java b/camel-core/src/main/java/org/apache/camel/model/cloud/ConsulServiceCallServiceDiscoveryConfiguration.java
new file mode 100644
index 0000000..b30f871
--- /dev/null
+++ b/camel-core/src/main/java/org/apache/camel/model/cloud/ConsulServiceCallServiceDiscoveryConfiguration.java
@@ -0,0 +1,258 @@
+/**
+ * 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.cloud;
+
+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 javax.xml.bind.annotation.XmlTransient;
+
+import org.apache.camel.spi.Metadata;
+import org.apache.camel.util.jsse.SSLContextParameters;
+
+@Metadata(label = "routing,cloud,service-discovery")
+@XmlRootElement(name = "consulServiceDiscovery")
+@XmlAccessorType(XmlAccessType.FIELD)
+public class ConsulServiceCallServiceDiscoveryConfiguration extends ServiceCallServiceDiscoveryConfiguration {
+    @XmlAttribute
+    private String url;
+    @XmlAttribute
+    private String dc;
+    @XmlAttribute @Metadata(label = "security")
+    private String aclToken;
+    @XmlAttribute @Metadata(label = "security")
+    private String userName;
+    @XmlAttribute @Metadata(label = "security")
+    private String password;
+    @XmlAttribute
+    private Long connectTimeoutMillis;
+    @XmlAttribute
+    private Long readTimeoutMillis;
+    @XmlAttribute
+    private Long writeTimeoutMillis;
+    @XmlAttribute @Metadata(defaultValue = "10")
+    private Integer blockSeconds = 10;
+    @XmlTransient
+    private SSLContextParameters sslContextParameters;
+
+    public ConsulServiceCallServiceDiscoveryConfiguration() {
+        this(null);
+    }
+
+    public ConsulServiceCallServiceDiscoveryConfiguration(ServiceCallDefinition parent) {
+        super(parent, "consul-service-discovery");
+    }
+
+    // *************************************************************************
+    // Getter/Setter
+    // *************************************************************************
+
+    /**
+     * The Consul agent URL
+     */
+    public String getUrl() {
+        return url;
+    }
+
+    public void setUrl(String url) {
+        this.url = url;
+    }
+
+    public String getDc() {
+        return dc;
+    }
+
+    /**
+     * The data center
+     */
+    public void setDc(String dc) {
+        this.dc = dc;
+    }
+
+    public String getAclToken() {
+        return aclToken;
+    }
+
+    /**
+     * Sets the ACL token to be used with Consul
+     */
+    public void setAclToken(String aclToken) {
+        this.aclToken = aclToken;
+    }
+
+    public String getUserName() {
+        return userName;
+    }
+
+    /**
+     * Sets the username to be used for basic authentication
+     */
+    public void setUserName(String userName) {
+        this.userName = userName;
+    }
+
+    public String getPassword() {
+        return password;
+    }
+
+    /**
+     * Sets the password to be used for basic authentication
+     */
+    public void setPassword(String password) {
+        this.password = password;
+    }
+
+    public Long getConnectTimeoutMillis() {
+        return connectTimeoutMillis;
+    }
+
+    /**
+     * Connect timeout for OkHttpClient
+     */
+    public void setConnectTimeoutMillis(Long connectTimeoutMillis) {
+        this.connectTimeoutMillis = connectTimeoutMillis;
+    }
+
+    public Long getReadTimeoutMillis() {
+        return readTimeoutMillis;
+    }
+
+    /**
+     * Read timeout for OkHttpClient
+     */
+    public void setReadTimeoutMillis(Long readTimeoutMillis) {
+        this.readTimeoutMillis = readTimeoutMillis;
+    }
+
+    public Long getWriteTimeoutMillis() {
+        return writeTimeoutMillis;
+    }
+
+    /**
+     * Write timeout for OkHttpClient
+     */
+    public void setWriteTimeoutMillis(Long writeTimeoutMillis) {
+        this.writeTimeoutMillis = writeTimeoutMillis;
+    }
+
+    public Integer getBlockSeconds() {
+        return blockSeconds;
+    }
+
+    /**
+     * The seconds to wait for a watch event, default 10 seconds
+     */
+    public void setBlockSeconds(Integer blockSeconds) {
+        this.blockSeconds = blockSeconds;
+    }
+
+    public SSLContextParameters getSslContextParameters() {
+        return sslContextParameters;
+    }
+
+    /**
+     * To configure security using SSLContextParameters.
+     */
+    public void setSslContextParameters(SSLContextParameters sslContextParameters) {
+        this.sslContextParameters = sslContextParameters;
+    }
+
+    // *************************************************************************
+    // Fluent API
+    // *************************************************************************
+
+    /**
+     * The Consul agent URL
+     */
+    public ConsulServiceCallServiceDiscoveryConfiguration url(String url) {
+        setUrl(url);
+        return this;
+    }
+
+    /**
+     * The data center
+     */
+    public ConsulServiceCallServiceDiscoveryConfiguration dc(String dc) {
+        setDc(dc);
+        return this;
+    }
+
+    /**
+     * Sets the ACL token to be used with Consul
+     */
+    public ConsulServiceCallServiceDiscoveryConfiguration aclToken(String aclToken) {
+        setAclToken(aclToken);
+        return this;
+    }
+
+    /**
+     * Sets the username to be used for basic authentication
+     */
+    public ConsulServiceCallServiceDiscoveryConfiguration userName(String userName) {
+        setUserName(userName);
+        return this;
+    }
+
+    /**
+     * Sets the password to be used for basic authentication
+     */
+    public ConsulServiceCallServiceDiscoveryConfiguration password(String password) {
+        setPassword(password);
+        return this;
+    }
+
+    /**
+     * Connect timeout for OkHttpClient
+     */
+    public ConsulServiceCallServiceDiscoveryConfiguration connectTimeoutMillis(Long connectTimeoutMillis) {
+        setConnectTimeoutMillis(connectTimeoutMillis);
+        return this;
+    }
+
+    /**
+     * Read timeout for OkHttpClient
+     */
+    public ConsulServiceCallServiceDiscoveryConfiguration readTimeoutMillis(Long readTimeoutMillis) {
+        setReadTimeoutMillis(readTimeoutMillis);
+        return this;
+    }
+
+    /**
+     * Write timeout for OkHttpClient
+     */
+    public ConsulServiceCallServiceDiscoveryConfiguration writeTimeoutMillis(Long writeTimeoutMillis) {
+        setWriteTimeoutMillis(writeTimeoutMillis);
+        return this;
+    }
+
+    /**
+     * The seconds to wait for a watch event, default 10 seconds
+     */
+    public ConsulServiceCallServiceDiscoveryConfiguration blockSeconds(Integer blockSeconds) {
+        setBlockSeconds(blockSeconds);
+        return this;
+    }
+
+    /**
+     * To configure security using SSLContextParameters.
+     */
+    public ConsulServiceCallServiceDiscoveryConfiguration sslContextParameters(SSLContextParameters sslContextParameters) {
+        setSslContextParameters(sslContextParameters);
+        return this;
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/camel-core/src/main/java/org/apache/camel/model/cloud/DnsServiceCallServiceDiscoveryConfiguration.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/model/cloud/DnsServiceCallServiceDiscoveryConfiguration.java b/camel-core/src/main/java/org/apache/camel/model/cloud/DnsServiceCallServiceDiscoveryConfiguration.java
new file mode 100644
index 0000000..1862ccd
--- /dev/null
+++ b/camel-core/src/main/java/org/apache/camel/model/cloud/DnsServiceCallServiceDiscoveryConfiguration.java
@@ -0,0 +1,88 @@
+/**
+ * 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.cloud;
+
+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;
+
+@Metadata(label = "routing,cloud,service-discovery")
+@XmlRootElement(name = "dnsServiceDiscovery")
+@XmlAccessorType(XmlAccessType.FIELD)
+public class DnsServiceCallServiceDiscoveryConfiguration extends ServiceCallServiceDiscoveryConfiguration {
+    @XmlAttribute @Metadata(defaultValue = "_tcp")
+    String proto = "_tcp";
+    @XmlAttribute
+    String domain;
+
+    public DnsServiceCallServiceDiscoveryConfiguration() {
+        this(null);
+    }
+
+    public DnsServiceCallServiceDiscoveryConfiguration(ServiceCallDefinition parent) {
+        super(parent, "dns-service-discovery");
+    }
+
+    // *************************************************************************
+    // Properties
+    // *************************************************************************
+
+    public String getProto() {
+        return proto;
+    }
+
+    /**
+     * The transport protocol of the desired service.
+     */
+    public void setProto(String proto) {
+        this.proto = proto;
+    }
+
+    public String getDomain() {
+        return domain;
+    }
+
+    /**
+     * The domain name;
+     */
+    public void setDomain(String domain) {
+        this.domain = domain;
+    }
+
+    // *************************************************************************
+    // Fluent API
+    // *************************************************************************
+
+    /**
+     * The transport protocol of the desired service.
+     */
+    public DnsServiceCallServiceDiscoveryConfiguration proto(String proto) {
+        setProto(proto);
+        return this;
+    }
+
+    /**
+     * The domain name;
+     */
+    public DnsServiceCallServiceDiscoveryConfiguration domain(String domain) {
+        setDomain(domain);
+        return this;
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/camel-core/src/main/java/org/apache/camel/model/cloud/EtcdServiceCallServiceDiscoveryConfiguration.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/model/cloud/EtcdServiceCallServiceDiscoveryConfiguration.java b/camel-core/src/main/java/org/apache/camel/model/cloud/EtcdServiceCallServiceDiscoveryConfiguration.java
new file mode 100644
index 0000000..22bd4cf
--- /dev/null
+++ b/camel-core/src/main/java/org/apache/camel/model/cloud/EtcdServiceCallServiceDiscoveryConfiguration.java
@@ -0,0 +1,194 @@
+/**
+ * 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.cloud;
+
+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 javax.xml.bind.annotation.XmlTransient;
+
+import org.apache.camel.spi.Metadata;
+import org.apache.camel.util.jsse.SSLContextParameters;
+
+@Metadata(label = "routing,cloud,service-discovery")
+@XmlRootElement(name = "etcdServiceDiscovery")
+@XmlAccessorType(XmlAccessType.FIELD)
+public class EtcdServiceCallServiceDiscoveryConfiguration extends ServiceCallServiceDiscoveryConfiguration {
+    @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/";
+    @XmlTransient
+    private SSLContextParameters sslContextParameters;
+    @XmlAttribute @Metadata(defaultValue = "on-demand", enums = "on-demand,watch")
+    private String type = "on-demand";
+
+    public EtcdServiceCallServiceDiscoveryConfiguration() {
+        this(null);
+    }
+
+    public EtcdServiceCallServiceDiscoveryConfiguration(ServiceCallDefinition parent) {
+        super(parent, "etcd-service-discovery");
+    }
+
+    // *************************************************************************
+    // Properties
+    // *************************************************************************
+
+    public String getUris() {
+        return uris;
+    }
+
+    /**
+     * The URIs the client can connect to.
+     */
+    public void setUris(String uris) {
+        this.uris = uris;
+    }
+
+    public String getUserName() {
+        return userName;
+    }
+
+    /**
+     * The user name to use for basic authentication.
+     */
+    public void setUserName(String userName) {
+        this.userName = userName;
+    }
+    public String getPassword() {
+        return password;
+    }
+
+    /**
+     * The password to use for basic authentication.
+     */
+    public void setPassword(String password) {
+        this.password = password;
+    }
+
+    public Long getTimeout() {
+        return timeout;
+    }
+
+    /**
+     * To set the maximum time an action could take to complete.
+     */
+    public void setTimeout(Long timeout) {
+        this.timeout = timeout;
+    }
+
+    public String getServicePath() {
+        return servicePath;
+    }
+
+    /**
+     * The path to look for for service discovery
+     */
+    public void setServicePath(String servicePath) {
+        this.servicePath = servicePath;
+    }
+
+    public SSLContextParameters getSslContextParameters() {
+        return sslContextParameters;
+    }
+
+    /**
+     * To configure security using SSLContextParameters.
+     */
+    public void setSslContextParameters(SSLContextParameters sslContextParameters) {
+        this.sslContextParameters = sslContextParameters;
+    }
+
+    public String getType() {
+        return type;
+    }
+
+    /**
+     * To set the discovery type, valid values are on-demand and watch.
+     */
+    public void setType(String type) {
+        this.type = type;
+    }
+
+    // *************************************************************************
+    // Fluent API
+    // *************************************************************************
+
+    /**
+     * The URIs the client can connect to.
+     */
+    public EtcdServiceCallServiceDiscoveryConfiguration uris(String uris) {
+        setUris(uris);
+        return this;
+    }
+
+    /**
+     * The user name to use for basic authentication.
+     */
+    public EtcdServiceCallServiceDiscoveryConfiguration userName(String userName) {
+        setUserName(userName);
+        return this;
+    }
+
+    /**
+     * The password to use for basic authentication.
+     */
+    public EtcdServiceCallServiceDiscoveryConfiguration password(String password) {
+        setPassword(password);
+        return this;
+    }
+
+    /**
+     * To set the maximum time an action could take to complete.
+     */
+    public EtcdServiceCallServiceDiscoveryConfiguration timeout(Long timeout) {
+        setTimeout(timeout);
+        return this;
+    }
+
+    /**
+     * The path to look for for service discovery
+     */
+    public EtcdServiceCallServiceDiscoveryConfiguration servicePath(String servicePath) {
+        setServicePath(servicePath);
+        return this;
+    }
+
+    /**
+     * To configure security using SSLContextParameters.
+     */
+    public EtcdServiceCallServiceDiscoveryConfiguration sslContextParameters(SSLContextParameters sslContextParameters) {
+        setSslContextParameters(sslContextParameters);
+        return this;
+    }
+
+    /**
+     * To set the discovery type, valid values are on-demand and watch.
+     */
+    public EtcdServiceCallServiceDiscoveryConfiguration type(String type) {
+        setType(type);
+        return this;
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/camel-core/src/main/java/org/apache/camel/model/cloud/KubernetesServiceCallServiceDiscoveryConfiguration.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/model/cloud/KubernetesServiceCallServiceDiscoveryConfiguration.java b/camel-core/src/main/java/org/apache/camel/model/cloud/KubernetesServiceCallServiceDiscoveryConfiguration.java
new file mode 100644
index 0000000..0aa9cbe
--- /dev/null
+++ b/camel-core/src/main/java/org/apache/camel/model/cloud/KubernetesServiceCallServiceDiscoveryConfiguration.java
@@ -0,0 +1,421 @@
+/**
+ * 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.cloud;
+
+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;
+
+@Metadata(label = "routing,cloud,service-discovery")
+@XmlRootElement(name = "kubernetesServiceDiscovery")
+@XmlAccessorType(XmlAccessType.FIELD)
+public class KubernetesServiceCallServiceDiscoveryConfiguration extends ServiceCallServiceDiscoveryConfiguration {
+    @XmlAttribute @Metadata(defaultValue = "environment", enums = "environment,dns,client")
+    private String lookup = "environment";
+    @XmlAttribute
+    private String dnsDomain;
+    @XmlAttribute
+    private String namespace;
+    @XmlAttribute
+    private String apiVersion;
+    @XmlAttribute @Metadata(label = "client")
+    private String masterUrl;
+    @XmlAttribute @Metadata(label = "client")
+    private String username;
+    @XmlAttribute @Metadata(label = "client")
+    private String password;
+    @XmlAttribute @Metadata(label = "client")
+    private String oauthToken;
+    @XmlAttribute @Metadata(label = "client")
+    private String caCertData;
+    @XmlAttribute @Metadata(label = "client")
+    private String caCertFile;
+    @XmlAttribute @Metadata(label = "client")
+    private String clientCertData;
+    @XmlAttribute @Metadata(label = "client")
+    private String clientCertFile;
+    @XmlAttribute @Metadata(label = "client")
+    private String clientKeyAlgo;
+    @XmlAttribute @Metadata(label = "client")
+    private String clientKeyData;
+    @XmlAttribute @Metadata(label = "client")
+    private String clientKeyFile;
+    @XmlAttribute @Metadata(label = "client")
+    private String clientKeyPassphrase;
+    @XmlAttribute @Metadata(label = "client")
+    private Boolean trustCerts;
+
+    public KubernetesServiceCallServiceDiscoveryConfiguration() {
+        this(null);
+    }
+
+    public KubernetesServiceCallServiceDiscoveryConfiguration(ServiceCallDefinition parent) {
+        super(parent, "kubernetes-service-discovery");
+    }
+
+    // *************************************************************************
+    // Properties
+    // *************************************************************************
+
+    public String getMasterUrl() {
+        return masterUrl;
+    }
+
+    /**
+     * Sets the URL to the master when using client lookup
+     */
+    public void setMasterUrl(String masterUrl) {
+        this.masterUrl = masterUrl;
+    }
+
+    public String getNamespace() {
+        return namespace;
+    }
+
+    /**
+     * Sets the namespace to use. Will by default use namespace from the ENV variable KUBERNETES_MASTER.
+     */
+    public void setNamespace(String namespace) {
+        this.namespace = namespace;
+    }
+
+    public String getApiVersion() {
+        return apiVersion;
+    }
+
+    /**
+     * Sets the API version when using client lookup
+     */
+    public void setApiVersion(String apiVersion) {
+        this.apiVersion = apiVersion;
+    }
+
+    public String getLookup() {
+        return lookup;
+    }
+
+    /**
+     * How to perform service lookup. Possible values: client, dns, environment.
+     * <p/>
+     * When using client, then the client queries the kubernetes master to obtain a list
+     * of active pods that provides the service, and then random (or round robin) select a pod.
+     * <p/>
+     * When using dns the service name is resolved as <tt>name.namespace.service.dnsDomain</tt>.
+     * <p/>
+     * When using environment then environment variables are used to lookup the service.
+     * <p/>
+     * By default environment is used.
+     */
+    public void setLookup(String lookup) {
+        this.lookup = lookup;
+    }
+
+    public String getDnsDomain() {
+        return dnsDomain;
+    }
+
+    /**
+     * Sets the DNS domain to use for DNS lookup.
+     */
+    public void setDnsDomain(String dnsDomain) {
+        this.dnsDomain = dnsDomain;
+    }
+
+    public String getUsername() {
+        return username;
+    }
+
+    /**
+     * Sets the username for authentication when using client lookup
+     */
+    public void setUsername(String username) {
+        this.username = username;
+    }
+
+    public String getPassword() {
+        return password;
+    }
+
+    /**
+     * Sets the password for authentication when using client lookup
+     */
+    public void setPassword(String password) {
+        this.password = password;
+    }
+
+    public String getOauthToken() {
+        return oauthToken;
+    }
+
+    /**
+     * Sets the OAUTH token for authentication (instead of username/password) when using client lookup
+     */
+    public void setOauthToken(String oauthToken) {
+        this.oauthToken = oauthToken;
+    }
+
+    public String getCaCertData() {
+        return caCertData;
+    }
+
+    /**
+     * Sets the Certificate Authority data when using client lookup
+     */
+    public void setCaCertData(String caCertData) {
+        this.caCertData = caCertData;
+    }
+
+    public String getCaCertFile() {
+        return caCertFile;
+    }
+
+    /**
+     * Sets the Certificate Authority data that are loaded from the file when using client lookup
+     */
+    public void setCaCertFile(String caCertFile) {
+        this.caCertFile = caCertFile;
+    }
+
+    public String getClientCertData() {
+        return clientCertData;
+    }
+
+    /**
+     * Sets the Client Certificate data when using client lookup
+     */
+    public void setClientCertData(String clientCertData) {
+        this.clientCertData = clientCertData;
+    }
+
+    public String getClientCertFile() {
+        return clientCertFile;
+    }
+
+    /**
+     * Sets the Client Certificate data that are loaded from the file when using client lookup
+     */
+    public void setClientCertFile(String clientCertFile) {
+        this.clientCertFile = clientCertFile;
+    }
+
+    public String getClientKeyAlgo() {
+        return clientKeyAlgo;
+    }
+
+    /**
+     * Sets the Client Keystore algorithm, such as RSA when using client lookup
+     */
+    public void setClientKeyAlgo(String clientKeyAlgo) {
+        this.clientKeyAlgo = clientKeyAlgo;
+    }
+
+    public String getClientKeyData() {
+        return clientKeyData;
+    }
+
+    /**
+     * Sets the Client Keystore data when using client lookup
+     */
+    public void setClientKeyData(String clientKeyData) {
+        this.clientKeyData = clientKeyData;
+    }
+
+    public String getClientKeyFile() {
+        return clientKeyFile;
+    }
+
+    /**
+     * Sets the Client Keystore data that are loaded from the file when using client lookup
+     */
+    public void setClientKeyFile(String clientKeyFile) {
+        this.clientKeyFile = clientKeyFile;
+    }
+
+    public String getClientKeyPassphrase() {
+        return clientKeyPassphrase;
+    }
+
+    /**
+     * Sets the Client Keystore passphrase when using client lookup
+     */
+    public void setClientKeyPassphrase(String clientKeyPassphrase) {
+        this.clientKeyPassphrase = clientKeyPassphrase;
+    }
+
+    public Boolean getTrustCerts() {
+        return trustCerts;
+    }
+
+    /**
+     * Sets whether to turn on trust certificate check when using client lookup
+     */
+    public void setTrustCerts(Boolean trustCerts) {
+        this.trustCerts = trustCerts;
+    }
+
+    // *************************************************************************
+    // Fluent API
+    // *************************************************************************
+
+    /**
+     * Sets the URL to the master when using client lookup
+     */
+    public KubernetesServiceCallServiceDiscoveryConfiguration masterUrl(String masterUrl) {
+        setMasterUrl(masterUrl);
+        return this;
+    }
+
+    /**
+     * Sets the namespace to use. Will by default use namespace from the ENV variable KUBERNETES_MASTER.
+     */
+    public KubernetesServiceCallServiceDiscoveryConfiguration namespace(String namespace) {
+        setNamespace(namespace);
+        return this;
+    }
+
+    /**
+     * Sets the API version when using client lookup
+     */
+    public KubernetesServiceCallServiceDiscoveryConfiguration apiVersion(String apiVersion) {
+        setApiVersion(apiVersion);
+        return this;
+    }
+
+    /**
+     * How to perform service lookup. Possible values: client, dns, environment.
+     * <p/>
+     * When using client, then the client queries the kubernetes master to obtain a list
+     * of active pods that provides the service, and then random (or round robin) select a pod.
+     * <p/>
+     * When using dns the service name is resolved as <tt>name.namespace.service.dnsDomain</tt>.
+     * <p/>
+     * When using environment then environment variables are used to lookup the service.
+     * <p/>
+     * By default environment is used.
+     */
+    public KubernetesServiceCallServiceDiscoveryConfiguration lookup(String lookup) {
+        setLookup(lookup);
+        return this;
+    }
+
+    /**
+     * Sets the DNS domain to use for DNS lookup.
+     */
+    public KubernetesServiceCallServiceDiscoveryConfiguration dnsDomain(String dnsDomain) {
+        setDnsDomain(dnsDomain);
+        return this;
+    }
+
+    /**
+     * Sets the username for authentication when using client lookup
+     */
+    public KubernetesServiceCallServiceDiscoveryConfiguration username(String username) {
+        setUsername(username);
+        return this;
+    }
+
+    /**
+     * Sets the password for authentication when using client lookup
+     */
+    public KubernetesServiceCallServiceDiscoveryConfiguration password(String password) {
+        setPassword(password);
+        return this;
+    }
+
+    /**
+     * Sets the OAUTH token for authentication (instead of username/password) when using client lookup
+     */
+    public KubernetesServiceCallServiceDiscoveryConfiguration oauthToken(String oauthToken) {
+        setOauthToken(oauthToken);
+        return this;
+    }
+
+    /**
+     * Sets the Certificate Authority data when using client lookup
+     */
+    public KubernetesServiceCallServiceDiscoveryConfiguration caCertData(String caCertData) {
+        setCaCertData(caCertData);
+        return this;
+    }
+
+    /**
+     * Sets the Certificate Authority data that are loaded from the file when using client lookup
+     */
+    public KubernetesServiceCallServiceDiscoveryConfiguration caCertFile(String caCertFile) {
+        setCaCertFile(caCertFile);
+        return this;
+    }
+
+    /**
+     * Sets the Client Certificate data when using client lookup
+     */
+    public KubernetesServiceCallServiceDiscoveryConfiguration clientCertData(String clientCertData) {
+        setClientCertData(clientCertData);
+        return this;
+    }
+
+    /**
+     * Sets the Client Certificate data that are loaded from the file when using client lookup
+     */
+    public KubernetesServiceCallServiceDiscoveryConfiguration clientCertFile(String clientCertFile) {
+        setClientCertFile(clientCertFile);
+        return this;
+    }
+
+    /**
+     * Sets the Client Keystore algorithm, such as RSA when using client lookup
+     */
+    public KubernetesServiceCallServiceDiscoveryConfiguration clientKeyAlgo(String clientKeyAlgo) {
+        setClientKeyAlgo(clientKeyAlgo);
+        return this;
+    }
+
+    /**
+     * Sets the Client Keystore data when using client lookup
+     */
+    public KubernetesServiceCallServiceDiscoveryConfiguration clientKeyData(String clientKeyData) {
+        setClientKeyData(clientKeyData);
+        return this;
+    }
+
+    /**
+     * Sets the Client Keystore data that are loaded from the file when using client lookup
+     */
+    public KubernetesServiceCallServiceDiscoveryConfiguration clientKeyFile(String clientKeyFile) {
+        setClientKeyFile(clientKeyFile);
+        return this;
+    }
+
+    /**
+     * Sets the Client Keystore passphrase when using client lookup
+     */
+    public KubernetesServiceCallServiceDiscoveryConfiguration clientKeyPassphrase(String clientKeyPassphrase) {
+        setClientKeyPassphrase(clientKeyPassphrase);
+        return this;
+    }
+
+    /**
+     * Sets whether to turn on trust certificate check when using client lookup
+     */
+    public KubernetesServiceCallServiceDiscoveryConfiguration trustCerts(boolean trustCerts) {
+        setTrustCerts(trustCerts);
+        return this;
+    }
+}
\ No newline at end of file


[08/10] camel git commit: CAMEL-10638: Refactor ServiceCall EIP

Posted by lb...@apache.org.
http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/camel-core/src/main/java/org/apache/camel/model/cloud/RibbonServiceCallLoadBalancerConfiguration.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/model/cloud/RibbonServiceCallLoadBalancerConfiguration.java b/camel-core/src/main/java/org/apache/camel/model/cloud/RibbonServiceCallLoadBalancerConfiguration.java
new file mode 100644
index 0000000..05f2523
--- /dev/null
+++ b/camel-core/src/main/java/org/apache/camel/model/cloud/RibbonServiceCallLoadBalancerConfiguration.java
@@ -0,0 +1,67 @@
+/**
+ * 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.cloud;
+
+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;
+
+@Metadata(label = "routing,cloud,load-balancing")
+@XmlRootElement(name = "ribbonLoadBalancer")
+@XmlAccessorType(XmlAccessType.FIELD)
+public class RibbonServiceCallLoadBalancerConfiguration extends ServiceCallLoadBalancerConfiguration {
+    @XmlAttribute
+    private String clientName;
+
+    public RibbonServiceCallLoadBalancerConfiguration() {
+        this(null);
+    }
+
+    public RibbonServiceCallLoadBalancerConfiguration(ServiceCallDefinition parent) {
+        super(parent, "ribbon-load-balancer");
+    }
+
+    // *************************************************************************
+    // Properties
+    // *************************************************************************
+
+    public String getClientName() {
+        return clientName;
+    }
+
+    /**
+     * Sets the Ribbon client name
+     */
+    public void setClientName(String clientName) {
+        this.clientName = clientName;
+    }
+
+    // *************************************************************************
+    // Fluent API
+    // *************************************************************************
+
+    /**
+     * Sets the Ribbon client name
+     */
+    public RibbonServiceCallLoadBalancerConfiguration clientName(String clientName) {
+        setClientName(clientName);
+        return this;
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/camel-core/src/main/java/org/apache/camel/model/cloud/ServiceCallConfigurationDefinition.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/model/cloud/ServiceCallConfigurationDefinition.java b/camel-core/src/main/java/org/apache/camel/model/cloud/ServiceCallConfigurationDefinition.java
new file mode 100644
index 0000000..c35fed9
--- /dev/null
+++ b/camel-core/src/main/java/org/apache/camel/model/cloud/ServiceCallConfigurationDefinition.java
@@ -0,0 +1,407 @@
+/**
+ * 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.cloud;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlElements;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlTransient;
+
+import org.apache.camel.ExchangePattern;
+import org.apache.camel.Expression;
+import org.apache.camel.cloud.LoadBalancer;
+import org.apache.camel.cloud.ServiceChooser;
+import org.apache.camel.cloud.ServiceDiscovery;
+import org.apache.camel.cloud.ServiceFilter;
+import org.apache.camel.model.IdentifiedType;
+import org.apache.camel.spi.Metadata;
+
+/**
+ * Remote service call configuration
+ */
+@Metadata(label = "routing,cloud")
+@XmlRootElement(name = "serviceCallConfiguration")
+@XmlAccessorType(XmlAccessType.FIELD)
+public class ServiceCallConfigurationDefinition extends IdentifiedType {
+    @XmlAttribute
+    private String uri;
+    @XmlAttribute @Metadata(defaultValue = "http")
+    private String component;
+    @XmlAttribute
+    private ExchangePattern pattern;
+    @XmlAttribute
+    private String serviceDiscoveryRef;
+    @XmlTransient
+    private ServiceDiscovery serviceDiscovery;
+    @XmlAttribute
+    private String serviceFilterRef;
+    @XmlTransient
+    private ServiceFilter serviceFilter;
+    @XmlAttribute
+    private String serviceChooserRef;
+    @XmlTransient
+    private ServiceChooser serviceChooser;
+    @XmlAttribute
+    private String loadBalancerRef;
+    @XmlTransient
+    private LoadBalancer loadBalancer;
+    @XmlAttribute
+    private String expressionRef;
+    @XmlTransient
+    private Expression expression;
+    @XmlElements({
+        @XmlElement(name = "consulServiceDiscovery", type = ConsulServiceCallServiceDiscoveryConfiguration.class),
+        @XmlElement(name = "dnsServiceDiscovery", type = DnsServiceCallServiceDiscoveryConfiguration.class),
+        @XmlElement(name = "etcdServiceDiscovery", type = EtcdServiceCallServiceDiscoveryConfiguration.class),
+        @XmlElement(name = "kubernetesServiceDiscovery", type = KubernetesServiceCallServiceDiscoveryConfiguration.class),
+        @XmlElement(name = "staticServiceDiscovery", type = StaticServiceCallServiceDiscoveryConfiguration.class)}
+    )
+    private ServiceCallServiceDiscoveryConfiguration serviceDiscoveryConfiguration;
+
+    @XmlElements({
+        @XmlElement(name = "ribbonLoadBalancer", type = RibbonServiceCallLoadBalancerConfiguration.class)}
+    )
+    private ServiceCallLoadBalancerConfiguration loadBalancerConfiguration;
+
+    @XmlElements({
+        @XmlElement(name = "expression", type = ServiceCallExpressionConfiguration.class)}
+    )
+    private ServiceCallExpressionConfiguration expressionConfiguration;
+
+    public ServiceCallConfigurationDefinition() {
+    }
+
+    // *****************************
+    // Properties
+    // *****************************
+
+    public ExchangePattern getPattern() {
+        return pattern;
+    }
+
+    public void setPattern(ExchangePattern pattern) {
+        this.pattern = pattern;
+    }
+
+    public String getUri() {
+        return uri;
+    }
+
+    /**
+     * The uri of the endpoint to send to.
+     * The uri can be dynamic computed using the {@link org.apache.camel.language.simple.SimpleLanguage} expression.
+     */
+    public void setUri(String uri) {
+        this.uri = uri;
+    }
+
+    public String getComponent() {
+        return component;
+    }
+
+    /**
+     * The component to use.
+     */
+    public void setComponent(String component) {
+        this.component = component;
+    }
+
+    public String getServiceDiscoveryRef() {
+        return serviceDiscoveryRef;
+    }
+
+    /**
+     * Sets a reference to a custom {@link ServiceDiscovery} to use.
+     */
+    public void setServiceDiscoveryRef(String serviceDiscoveryRef) {
+        this.serviceDiscoveryRef = serviceDiscoveryRef;
+    }
+
+    public ServiceDiscovery getServiceDiscovery() {
+        return serviceDiscovery;
+    }
+
+    /**
+     * Sets a custom {@link ServiceDiscovery} to use.
+     */
+    public void setServiceDiscovery(ServiceDiscovery serviceDiscovery) {
+        this.serviceDiscovery = serviceDiscovery;
+    }
+
+    public String getServiceFilterRef() {
+        return serviceFilterRef;
+    }
+
+    /**
+     * Sets a reference to a custom {@link ServiceFilter} to use.
+     */
+    public void setServiceFilterRef(String serviceFilterRef) {
+        this.serviceFilterRef = serviceFilterRef;
+    }
+
+    public ServiceFilter getServiceFilter() {
+        return serviceFilter;
+    }
+
+    /**
+     * Sets a custom {@link ServiceFilter} to use.
+     */
+    public void setServiceFilter(ServiceFilter serviceFilter) {
+        this.serviceFilter = serviceFilter;
+    }
+
+    public String getServiceChooserRef() {
+        return serviceChooserRef;
+    }
+
+    /**
+     * Sets a reference to a custom {@link ServiceChooser} to use.
+     */
+    public void setServiceChooserRef(String serviceChooserRef) {
+        this.serviceChooserRef = serviceChooserRef;
+    }
+
+    public ServiceChooser getServiceChooser() {
+        return serviceChooser;
+    }
+
+    /**
+     * Sets a custom {@link ServiceChooser} to use.
+     */
+    public void setServiceChooser(ServiceChooser serviceChooser) {
+        this.serviceChooser = serviceChooser;
+    }
+
+    public String getLoadBalancerRef() {
+        return loadBalancerRef;
+    }
+
+    /**
+     * Sets a reference to a custom {@link LoadBalancer} to use.
+     */
+    public void setLoadBalancerRef(String loadBalancerRef) {
+        this.loadBalancerRef = loadBalancerRef;
+    }
+
+    public LoadBalancer getLoadBalancer() {
+        return loadBalancer;
+    }
+
+    /**
+     * Sets a custom {@link LoadBalancer} to use.
+     */
+    public void setLoadBalancer(LoadBalancer loadBalancer) {
+        this.loadBalancer = loadBalancer;
+    }
+
+    public String getExpressionRef() {
+        return expressionRef;
+    }
+
+    /**
+     * Set a reference to a custom {@link Expression} to use.
+     */
+    public void setExpressionRef(String expressionRef) {
+        this.expressionRef = expressionRef;
+    }
+
+    public Expression getExpression() {
+        return expression;
+    }
+
+    /**
+     * Set a custom {@link Expression} to use.
+     */
+    public void setExpression(Expression expression) {
+        this.expression = expression;
+    }
+
+    public ServiceCallServiceDiscoveryConfiguration getServiceDiscoveryConfiguration() {
+        return serviceDiscoveryConfiguration;
+    }
+
+    /**
+     * Configures the ServiceDiscovery using the given configuration.
+     */
+    public void setServiceDiscoveryConfiguration(ServiceCallServiceDiscoveryConfiguration serviceDiscoveryConfiguration) {
+        this.serviceDiscoveryConfiguration = serviceDiscoveryConfiguration;
+    }
+
+    public ServiceCallLoadBalancerConfiguration getLoadBalancerConfiguration() {
+        return loadBalancerConfiguration;
+    }
+
+    /**
+     * Configures theL oadBalancer using the given configuration.
+     */
+    public void setLoadBalancerConfiguration(ServiceCallLoadBalancerConfiguration loadBalancerConfiguration) {
+        this.loadBalancerConfiguration = loadBalancerConfiguration;
+    }
+
+    public ServiceCallExpressionConfiguration getExpressionConfiguration() {
+        return expressionConfiguration;
+    }
+
+    /**
+     * Configures the Expression using the given configuration.
+     */
+    public void setExpressionConfiguration(ServiceCallExpressionConfiguration expressionConfiguration) {
+        this.expressionConfiguration = expressionConfiguration;
+    }
+
+    // *****************************
+    // Fluent API
+    // *****************************
+
+    /**
+     * Sets the default Camel component to use for calling the remote service.
+     * <p/>
+     * By default the http component is used. You can configure this to use <tt>netty4-http</tt>, <tt>jetty</tt>,
+     * <tt>restlet</tt> or some other components of choice. If the service is not HTTP protocol you can use other
+     * components such as <tt>mqtt</tt>, <tt>jms</tt>, <tt>amqp</tt> etc.
+     * <p/>
+     * If the service call has been configured using an uri, then the component from the uri is used instead
+     * of this default component.
+     */
+    public ServiceCallConfigurationDefinition component(String component) {
+        setComponent(component);
+        return this;
+    }
+
+    /**
+     * Sets the uri of the service to use
+     */
+    public ServiceCallConfigurationDefinition uri(String uri) {
+        setUri(uri);
+        return this;
+    }
+
+    /**
+     * Sets the optional {@link ExchangePattern} used to invoke this endpoint
+     */
+    public ServiceCallConfigurationDefinition pattern(ExchangePattern pattern) {
+        setPattern(pattern);
+        return this;
+    }
+
+    /**
+     * Sets a reference to a custom {@link ServiceDiscovery} to use.
+     */
+    public ServiceCallConfigurationDefinition serviceDiscovery(String serviceDiscoveryRef) {
+        setServiceDiscoveryRef(serviceDiscoveryRef);
+        return this;
+    }
+
+    /**
+     * Sets a custom {@link ServiceDiscovery} to use.
+     */
+    public ServiceCallConfigurationDefinition serviceDiscovery(ServiceDiscovery serviceDiscovery) {
+        setServiceDiscovery(serviceDiscovery);
+        return this;
+    }
+
+    /**
+     * Sets a reference to a custom {@link ServiceFilter} to use.
+     */
+    public ServiceCallConfigurationDefinition serviceFilter(String serviceFilterRef) {
+        setServiceDiscoveryRef(serviceDiscoveryRef);
+        return this;
+    }
+
+    /**
+     * Sets a custom {@link ServiceFilter} to use.
+     */
+    public ServiceCallConfigurationDefinition serviceFilter(ServiceFilter serviceFilter) {
+        setServiceFilter(serviceFilter);
+        return this;
+    }
+
+    /**
+     * Sets a reference to a custom {@link ServiceChooser} to use.
+     */
+    public ServiceCallConfigurationDefinition serviceChooser(String serviceChooserRef) {
+        setServiceChooserRef(serviceChooserRef);
+        return this;
+    }
+
+    /**
+     * Sets a custom {@link ServiceChooser} to use.
+     */
+    public ServiceCallConfigurationDefinition serviceChooser(ServiceChooser serviceChooser) {
+        setServiceChooser(serviceChooser);
+        return this;
+    }
+
+    /**
+     * Sets a reference to a custom {@link LoadBalancer} to use.
+     */
+    public ServiceCallConfigurationDefinition loadBalancer(String loadBalancerRef) {
+        setLoadBalancerRef(loadBalancerRef);
+        return this;
+    }
+
+    /**
+     * Sets a custom {@link LoadBalancer} to use.
+     */
+    public ServiceCallConfigurationDefinition loadBalancer(LoadBalancer loadBalancer) {
+        setLoadBalancer(loadBalancer);
+        return this;
+    }
+
+    /**
+     * Sets a reference to a custom {@link Expression} to use.
+     */
+    public ServiceCallConfigurationDefinition expression(String expressionRef) {
+        setExpressionRef(loadBalancerRef);
+        return this;
+    }
+
+    /**
+     * Sets a custom {@link Expression} to use.
+     */
+    public ServiceCallConfigurationDefinition expression(Expression expression) {
+        setExpression(expression);
+        return this;
+    }
+
+    /**
+     * Configures the ServiceDiscovery using the given configuration.
+     */
+    public ServiceCallConfigurationDefinition serviceDiscoveryConfiguration(ServiceCallServiceDiscoveryConfiguration serviceDiscoveryConfiguration) {
+        setServiceDiscoveryConfiguration(serviceDiscoveryConfiguration);
+        return this;
+    }
+
+    /**
+     * Configures the LoadBalancer using the given configuration.
+     */
+    public ServiceCallConfigurationDefinition loadBalancerConfiguration(ServiceCallLoadBalancerConfiguration loadBalancerConfiguration) {
+        setLoadBalancerConfiguration(loadBalancerConfiguration);
+        return this;
+    }
+
+    /**
+     * Configures the Expression using the given configuration.
+     */
+    public ServiceCallConfigurationDefinition expressionConfiguration(ServiceCallExpressionConfiguration expressionConfiguration) {
+        setExpressionConfiguration(expressionConfiguration);
+        return this;
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/camel-core/src/main/java/org/apache/camel/model/cloud/ServiceCallConstants.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/model/cloud/ServiceCallConstants.java b/camel-core/src/main/java/org/apache/camel/model/cloud/ServiceCallConstants.java
new file mode 100644
index 0000000..09910d1
--- /dev/null
+++ b/camel-core/src/main/java/org/apache/camel/model/cloud/ServiceCallConstants.java
@@ -0,0 +1,36 @@
+/**
+ * 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.cloud;
+
+import java.util.Arrays;
+import java.util.List;
+
+final class ServiceCallConstants {
+    public static final List<ServiceCallServiceDiscoveryConfiguration> SERVICE_DISCOVERY_CONFIGURATIONS = Arrays.asList(
+        new ConsulServiceCallServiceDiscoveryConfiguration(),
+        new EtcdServiceCallServiceDiscoveryConfiguration(),
+        new KubernetesServiceCallServiceDiscoveryConfiguration(),
+        new DnsServiceCallServiceDiscoveryConfiguration()
+    );
+
+    public static final List<ServiceCallLoadBalancerConfiguration> LOAD_BALANCER_CONFIGURATIONS = Arrays.asList(
+        new RibbonServiceCallLoadBalancerConfiguration()
+    );
+
+    private ServiceCallConstants() {
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/camel-core/src/main/java/org/apache/camel/model/cloud/ServiceCallDefinition.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/model/cloud/ServiceCallDefinition.java b/camel-core/src/main/java/org/apache/camel/model/cloud/ServiceCallDefinition.java
new file mode 100644
index 0000000..84a0fd7
--- /dev/null
+++ b/camel-core/src/main/java/org/apache/camel/model/cloud/ServiceCallDefinition.java
@@ -0,0 +1,721 @@
+/**
+ * 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.cloud;
+
+import java.util.Set;
+import java.util.function.Supplier;
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlElements;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlTransient;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.CamelContextAware;
+import org.apache.camel.ExchangePattern;
+import org.apache.camel.Expression;
+import org.apache.camel.NoFactoryAvailableException;
+import org.apache.camel.Processor;
+import org.apache.camel.cloud.LoadBalancer;
+import org.apache.camel.cloud.ServiceChooser;
+import org.apache.camel.cloud.ServiceChooserAware;
+import org.apache.camel.cloud.ServiceDiscovery;
+import org.apache.camel.cloud.ServiceDiscoveryAware;
+import org.apache.camel.cloud.ServiceFilter;
+import org.apache.camel.cloud.ServiceFilterAware;
+import org.apache.camel.impl.cloud.AllServiceFilter;
+import org.apache.camel.impl.cloud.DefaultLoadBalancer;
+import org.apache.camel.impl.cloud.DefaultServiceCallExpression;
+import org.apache.camel.impl.cloud.DefaultServiceCallProcessor;
+import org.apache.camel.impl.cloud.HealthyServiceFilter;
+import org.apache.camel.impl.cloud.RandomServiceChooser;
+import org.apache.camel.impl.cloud.RoundRobinServiceChooser;
+import org.apache.camel.model.NoOutputDefinition;
+import org.apache.camel.spi.Metadata;
+import org.apache.camel.spi.RouteContext;
+import org.apache.camel.util.CamelContextHelper;
+import org.apache.camel.util.ObjectHelper;
+
+/**
+ * Remote service call definition
+ */
+@Metadata(label = "eip,routing")
+@XmlRootElement(name = "serviceCall")
+@XmlAccessorType(XmlAccessType.FIELD)
+public class ServiceCallDefinition extends NoOutputDefinition<ServiceCallDefinition> {
+    @XmlAttribute @Metadata(required = "true")
+    private String name;
+    @XmlAttribute @Metadata(defaultValue = "http")
+    private String uri;
+    @XmlAttribute
+    private String component;
+    @XmlAttribute
+    private ExchangePattern pattern;
+    @XmlAttribute
+    private String configurationRef;
+    @XmlAttribute
+    private String serviceDiscoveryRef;
+    @XmlTransient
+    private ServiceDiscovery serviceDiscovery;
+    @XmlAttribute
+    private String serviceFilterRef;
+    @XmlTransient
+    private ServiceFilter serviceFilter;
+    @XmlAttribute
+    private String serviceChooserRef;
+    @XmlTransient
+    private ServiceChooser serviceChooser;
+    @XmlAttribute
+    private String loadBalancerRef;
+    @XmlTransient
+    private LoadBalancer loadBalancer;
+    @XmlAttribute
+    private String expressionRef;
+    @XmlTransient
+    private Expression expression;
+
+    @XmlElements({
+        @XmlElement(name = "consulServiceDiscovery", type = ConsulServiceCallServiceDiscoveryConfiguration.class),
+        @XmlElement(name = "dnsServiceDiscovery", type = DnsServiceCallServiceDiscoveryConfiguration.class),
+        @XmlElement(name = "etcdServiceDiscovery", type = EtcdServiceCallServiceDiscoveryConfiguration.class),
+        @XmlElement(name = "kubernetesServiceDiscovery", type = KubernetesServiceCallServiceDiscoveryConfiguration.class),
+        @XmlElement(name = "staticServiceDiscovery", type = StaticServiceCallServiceDiscoveryConfiguration.class)}
+    )
+    private ServiceCallServiceDiscoveryConfiguration serviceDiscoveryConfiguration;
+
+    @XmlElements({
+        @XmlElement(name = "ribbonLoadBalancer", type = RibbonServiceCallLoadBalancerConfiguration.class)}
+    )
+    private ServiceCallLoadBalancerConfiguration loadBalancerConfiguration;
+
+    @XmlElements({
+        @XmlElement(name = "expressionCOnfiguration", type = ServiceCallExpressionConfiguration.class)}
+    )
+    private ServiceCallExpressionConfiguration expressionConfiguration;
+
+    public ServiceCallDefinition() {
+    }
+
+    @Override
+    public String toString() {
+        return "ServiceCall[" + name + "]";
+    }
+
+    @Override
+    public String getLabel() {
+        return "serviceCall";
+    }
+
+    // *****************************
+    // Properties
+    // *****************************
+
+    public String getName() {
+        return name;
+    }
+
+    /**
+     * Sets the name of the service to use
+     */
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public ExchangePattern getPattern() {
+        return pattern;
+    }
+
+    /**
+     * Sets the optional {@link ExchangePattern} used to invoke this endpoint
+     */
+    public void setPattern(ExchangePattern pattern) {
+        this.pattern = pattern;
+    }
+
+    public String getConfigurationRef() {
+        return configurationRef;
+    }
+
+    /**
+     * Refers to a ServiceCall configuration to use
+     */
+    public void setConfigurationRef(String configurationRef) {
+        this.configurationRef = configurationRef;
+    }
+
+    public String getUri() {
+        return uri;
+    }
+
+    /**
+     * The uri of the endpoint to send to.
+     * The uri can be dynamic computed using the {@link org.apache.camel.language.simple.SimpleLanguage} expression.
+     */
+    public void setUri(String uri) {
+        this.uri = uri;
+    }
+
+    public String getComponent() {
+        return component;
+    }
+
+    /**
+     * The component to use.
+     */
+    public void setComponent(String component) {
+        this.component = component;
+    }
+
+    public String getServiceDiscoveryRef() {
+        return serviceDiscoveryRef;
+    }
+
+    /**
+     * Sets a reference to a custom {@link ServiceDiscovery} to use.
+     */
+    public void setServiceDiscoveryRef(String serviceDiscoveryRef) {
+        this.serviceDiscoveryRef = serviceDiscoveryRef;
+    }
+
+    public ServiceDiscovery getServiceDiscovery() {
+        return serviceDiscovery;
+    }
+
+    /**
+     * Sets a custom {@link ServiceDiscovery} to use.
+     */
+    public void setServiceDiscovery(ServiceDiscovery serviceDiscovery) {
+        this.serviceDiscovery = serviceDiscovery;
+    }
+
+    public String getServiceFilterRef() {
+        return serviceFilterRef;
+    }
+
+    /**
+     * Sets a reference to a custom {@link ServiceFilter} to use.
+     */
+    public void setServiceFilterRef(String serviceFilterRef) {
+        this.serviceFilterRef = serviceFilterRef;
+    }
+
+    public ServiceFilter getServiceFilter() {
+        return serviceFilter;
+    }
+
+    /**
+     * Sets a custom {@link ServiceFilter} to use.
+     */
+    public void setServiceFilter(ServiceFilter serviceFilter) {
+        this.serviceFilter = serviceFilter;
+    }
+
+    public String getServiceChooserRef() {
+        return serviceChooserRef;
+    }
+
+    /**
+     * Sets a reference to a custom {@link ServiceChooser} to use.
+     */
+    public void setServiceChooserRef(String serviceChooserRef) {
+        this.serviceChooserRef = serviceChooserRef;
+    }
+
+    public ServiceChooser getServiceChooser() {
+        return serviceChooser;
+    }
+
+    /**
+     * Sets a custom {@link ServiceChooser} to use.
+     */
+    public void setServiceChooser(ServiceChooser serviceChooser) {
+        this.serviceChooser = serviceChooser;
+    }
+
+    public String getLoadBalancerRef() {
+        return loadBalancerRef;
+    }
+
+    /**
+     * Sets a reference to a custom {@link LoadBalancer} to use.
+     */
+    public void setLoadBalancerRef(String loadBalancerRef) {
+        this.loadBalancerRef = loadBalancerRef;
+    }
+
+    public LoadBalancer getLoadBalancer() {
+        return loadBalancer;
+    }
+
+    /**
+     * Sets a custom {@link LoadBalancer} to use.
+     */
+    public void setLoadBalancer(LoadBalancer loadBalancer) {
+        this.loadBalancer = loadBalancer;
+    }
+
+    public String getExpressionRef() {
+        return expressionRef;
+    }
+
+    /**
+     * Set a reference to a custom {@link Expression} to use.
+     */
+    public void setExpressionRef(String expressionRef) {
+        this.expressionRef = expressionRef;
+    }
+
+    public Expression getExpression() {
+        return expression;
+    }
+
+    /**
+     * Set a custom {@link Expression} to use.
+     */
+    public void setExpression(Expression expression) {
+        this.expression = expression;
+    }
+
+    public ServiceCallServiceDiscoveryConfiguration getServiceDiscoveryConfiguration() {
+        return serviceDiscoveryConfiguration;
+    }
+
+    /**
+     * Configures the ServiceDiscovery using the given configuration.
+     */
+    public void setServiceDiscoveryConfiguration(ServiceCallServiceDiscoveryConfiguration serviceDiscoveryConfiguration) {
+        this.serviceDiscoveryConfiguration = serviceDiscoveryConfiguration;
+    }
+
+    public ServiceCallLoadBalancerConfiguration getLoadBalancerConfiguration() {
+        return loadBalancerConfiguration;
+    }
+
+    /**
+     * Configures the LoadBalancer using the given configuration.
+     */
+    public void setLoadBalancerConfiguration(ServiceCallLoadBalancerConfiguration loadBalancerConfiguration) {
+        this.loadBalancerConfiguration = loadBalancerConfiguration;
+    }
+
+    public ServiceCallExpressionConfiguration getExpressionConfiguration() {
+        return expressionConfiguration;
+    }
+
+    /**
+     * Configures the Expression using the given configuration.
+     */
+    public void setExpressionConfiguration(ServiceCallExpressionConfiguration expressionConfiguration) {
+        this.expressionConfiguration = expressionConfiguration;
+    }
+
+    // *****************************
+    // Fluent API
+    // *****************************
+
+    /**
+     * Sets the optional {@link ExchangePattern} used to invoke this endpoint
+     */
+    public ServiceCallDefinition pattern(ExchangePattern pattern) {
+        setPattern(pattern);
+        return this;
+    }
+
+    /**
+     * Sets the name of the service to use
+     */
+    public ServiceCallDefinition name(String name) {
+        setName(name);
+        return this;
+    }
+
+    /**
+     * Sets the uri of the service to use
+     */
+    public ServiceCallDefinition uri(String uri) {
+        setUri(uri);
+        return this;
+    }
+
+    /**
+     * Sets the component to use
+     */
+    public ServiceCallDefinition component(String component) {
+        setComponent(component);
+        return this;
+    }
+
+    /**
+     * Refers to a ServiceCall configuration to use
+     */
+    public ServiceCallDefinition serviceCallConfiguration(String ref) {
+        configurationRef = ref;
+        return this;
+    }
+
+    /**
+     * Sets a reference to a custom {@link ServiceDiscovery} to use.
+     */
+    public ServiceCallDefinition serviceDiscovery(String serviceDiscoveryRef) {
+        setServiceDiscoveryRef(serviceDiscoveryRef);
+        return this;
+    }
+
+    /**
+     * Sets a custom {@link ServiceDiscovery} to use.
+     */
+    public ServiceCallDefinition serviceDiscovery(ServiceDiscovery serviceDiscovery) {
+        setServiceDiscovery(serviceDiscovery);
+        return this;
+    }
+
+    /**
+     * Sets a reference to a custom {@link ServiceFilter} to use.
+     */
+    public ServiceCallDefinition serviceFilter(String serviceFilterRef) {
+        setServiceDiscoveryRef(serviceDiscoveryRef);
+        return this;
+    }
+
+    /**
+     * Sets a custom {@link ServiceFilter} to use.
+     */
+    public ServiceCallDefinition serviceFilter(ServiceFilter serviceFilter) {
+        setServiceFilter(serviceFilter);
+        return this;
+    }
+
+    /**
+     * Sets a reference to a custom {@link ServiceChooser} to use.
+     */
+    public ServiceCallDefinition serviceChooser(String serviceChooserRef) {
+        setServiceChooserRef(serviceChooserRef);
+        return this;
+    }
+
+    /**
+     * Sets a custom {@link ServiceChooser} to use.
+     */
+    public ServiceCallDefinition serviceChooser(ServiceChooser serviceChooser) {
+        setServiceChooser(serviceChooser);
+        return this;
+    }
+
+    /**
+     * Sets a reference to a custom {@link LoadBalancer} to use.
+     */
+    public ServiceCallDefinition loadBalancer(String loadBalancerRef) {
+        setLoadBalancerRef(loadBalancerRef);
+        return this;
+    }
+
+    /**
+     * Sets a custom {@link LoadBalancer} to use.
+     */
+    public ServiceCallDefinition loadBalancer(LoadBalancer loadBalancer) {
+        setLoadBalancer(loadBalancer);
+        return this;
+    }
+
+    /**
+     * Sets a reference to a custom {@link Expression} to use.
+     */
+    public ServiceCallDefinition expression(String expressionRef) {
+        setExpressionRef(loadBalancerRef);
+        return this;
+    }
+
+    /**
+     * Sets a custom {@link Expression} to use.
+     */
+    public ServiceCallDefinition expression(Expression expression) {
+        setExpression(expression);
+        return this;
+    }
+
+    /**
+     * Configures the ServiceDiscovery using the given configuration.
+     */
+    public ServiceCallDefinition serviceDiscoveryConfiguration(ServiceCallServiceDiscoveryConfiguration serviceDiscoveryConfiguration) {
+        setServiceDiscoveryConfiguration(serviceDiscoveryConfiguration);
+        return this;
+    }
+
+    /**
+     * Configures the LoadBalancer using the given configuration.
+     */
+    public ServiceCallDefinition loadBalancerConfiguration(ServiceCallLoadBalancerConfiguration loadBalancerConfiguration) {
+        setLoadBalancerConfiguration(loadBalancerConfiguration);
+        return this;
+    }
+
+    /**
+     * Configures the Expression using the given configuration.
+     */
+    public ServiceCallDefinition expressionConfiguration(ServiceCallExpressionConfiguration expressionConfiguration) {
+        setExpressionConfiguration(expressionConfiguration);
+        return this;
+    }
+
+    // *****************************
+    // Processor Factory
+    // *****************************
+
+    @Override
+    public Processor createProcessor(RouteContext routeContext) throws Exception {
+        final CamelContext camelContext = routeContext.getCamelContext();
+        final ServiceCallConfigurationDefinition config = retrieveConfig(camelContext);
+
+        ServiceDiscovery serviceDiscovery = retrieveServiceDiscovery(camelContext, config);
+        ServiceFilter serviceFilter = retrieveServiceFilter(camelContext, config);
+        ServiceChooser serviceChooser = retrieveServiceChooser(camelContext, config);
+        LoadBalancer loadBalancer = retrieveLoadBalancer(camelContext, config);
+        Expression expression = retrieveExpression(camelContext, config);
+
+        if (loadBalancer instanceof CamelContextAware) {
+            ((CamelContextAware) loadBalancer).setCamelContext(camelContext);
+        }
+        if (loadBalancer instanceof ServiceDiscoveryAware) {
+            ((ServiceDiscoveryAware) loadBalancer).setServiceDiscovery(serviceDiscovery);
+        }
+        if (loadBalancer instanceof ServiceFilterAware) {
+            ((ServiceFilterAware) loadBalancer).setServiceFilter(serviceFilter);
+        }
+        if (loadBalancer instanceof ServiceChooserAware) {
+            ((ServiceChooserAware) loadBalancer).setServiceChooser(serviceChooser);
+        }
+
+        // The component is used to configure what the default scheme to use (eg camel component name).
+        // The component configured on EIP takes precedence vs configured on configuration.
+        String component = this.component;
+        if (component == null) {
+            component = config != null ? config.getComponent() : null;
+        }
+
+        return new DefaultServiceCallProcessor(camelContext, name, component, uri, pattern, loadBalancer, expression);
+    }
+
+    // *****************************
+    // Helpers
+    // *****************************
+
+    private ServiceCallConfigurationDefinition retrieveConfig(CamelContext camelContext) {
+        ServiceCallConfigurationDefinition config = null;
+        if (configurationRef != null) {
+            // lookup in registry first
+            config = CamelContextHelper.lookup(camelContext, configurationRef, ServiceCallConfigurationDefinition.class);
+            if (config == null) {
+                // and fallback as service configuration
+                config = camelContext.getServiceCallConfiguration(configurationRef);
+            }
+        }
+
+        if (config == null) {
+            config = camelContext.getServiceCallConfiguration(null);
+        }
+        if (config == null) {
+            // if no default then try to find if there configuration in the registry of the given type
+            Set<ServiceCallConfigurationDefinition> set = camelContext.getRegistry().findByType(ServiceCallConfigurationDefinition.class);
+            if (set.size() == 1) {
+                config = set.iterator().next();
+            }
+        }
+
+        return config;
+    }
+
+    private ServiceDiscovery retrieveServiceDiscovery(CamelContext camelContext, ServiceCallConfigurationDefinition config) throws Exception {
+        ServiceDiscovery answer;
+        if (serviceDiscoveryConfiguration != null) {
+            answer = serviceDiscoveryConfiguration.newInstance(camelContext);
+        } else if (config != null && config.getServiceDiscoveryConfiguration() != null) {
+            answer = config.getServiceDiscoveryConfiguration().newInstance(camelContext);
+        } else {
+            answer = retrieve(ServiceDiscovery.class, camelContext, this::getServiceDiscovery, this::getServiceDiscoveryRef);
+            if (answer == null && config != null) {
+                answer = retrieve(ServiceDiscovery.class, camelContext, config::getServiceDiscovery, config::getServiceDiscoveryRef);
+            }
+            if (answer == null) {
+                answer = findByType(camelContext, ServiceDiscovery.class);
+            }
+        }
+
+        // If there's no configuration, let's try to find a suitable implementation
+        if (answer == null) {
+            for (ServiceCallServiceDiscoveryConfiguration configuration : ServiceCallConstants.SERVICE_DISCOVERY_CONFIGURATIONS) {
+                try {
+                    answer = configuration.newInstance(camelContext);
+
+                    if (answer != null) {
+                        break;
+                    }
+                } catch (NoFactoryAvailableException e) {
+                    // skip
+                }
+            }
+        }
+
+        return answer;
+    }
+
+    private ServiceFilter retrieveServiceFilter(CamelContext camelContext, ServiceCallConfigurationDefinition config) {
+        ServiceFilter answer = retrieve(ServiceFilter.class, camelContext, this::getServiceFilter, this::getServiceFilterRef);
+        if (answer == null && config != null) {
+            answer = retrieve(ServiceFilter.class, camelContext, config::getServiceFilter, config::getServiceFilterRef);
+
+            // If the ServiceFilter is not found but a ref is set, try to determine
+            // the implementation according to the ref name.
+            if (answer == null) {
+                String ref = config.getServiceFilterRef();
+                if (ObjectHelper.equal("healthy", ref, true)) {
+                    answer = new HealthyServiceFilter();
+                } else if (ObjectHelper.equal("all", ref, true)) {
+                    answer = new AllServiceFilter();
+                }
+            }
+        }
+        if (answer == null) {
+            answer = findByType(camelContext, ServiceFilter.class);
+        }
+
+        // If there's no configuration, let's use the healthy strategy
+        if (answer == null) {
+            answer = new HealthyServiceFilter();
+        }
+
+        return answer;
+    }
+
+    private ServiceChooser retrieveServiceChooser(CamelContext camelContext, ServiceCallConfigurationDefinition config) {
+        ServiceChooser answer = retrieve(ServiceChooser.class, camelContext, this::getServiceChooser, this::getServiceChooserRef);
+        if (answer == null && config != null) {
+            answer = retrieve(ServiceChooser.class, camelContext, config::getServiceChooser, config::getServiceChooserRef);
+
+            // If the ServiceChooser is not found but a ref is set, try to determine
+            // the implementation according to the ref name.
+            if (answer == null) {
+                String ref = config.getServiceChooserRef();
+                if (ObjectHelper.equal("roundrobin", ref, true)) {
+                    answer = new RoundRobinServiceChooser();
+                } else if (ObjectHelper.equal("round-robin", ref, true)) {
+                    answer = new RoundRobinServiceChooser();
+                } else if (ObjectHelper.equal("random", ref, true)) {
+                    answer = new RandomServiceChooser();
+                }
+            }
+        }
+        if (answer == null) {
+            answer = findByType(camelContext, ServiceChooser.class);
+        }
+
+        // If there's no configuration, let's use the round-robin strategy
+        if (answer == null) {
+            answer = new RoundRobinServiceChooser();
+        }
+
+        return answer;
+    }
+
+    private LoadBalancer retrieveLoadBalancer(CamelContext camelContext, ServiceCallConfigurationDefinition config) throws Exception {
+        LoadBalancer answer;
+        if (loadBalancerConfiguration != null) {
+            answer = loadBalancerConfiguration.newInstance(camelContext);
+        } else if (config != null && config.getLoadBalancerConfiguration() != null) {
+            answer = config.getLoadBalancerConfiguration().newInstance(camelContext);
+        } else {
+            answer = retrieve(LoadBalancer.class, camelContext, this::getLoadBalancer, this::getLoadBalancerRef);
+            if (answer == null && config != null) {
+                answer = retrieve(LoadBalancer.class, camelContext, config::getLoadBalancer, config::getLoadBalancerRef);
+            }
+            if (answer == null) {
+                answer = findByType(camelContext, LoadBalancer.class);
+            }
+        }
+
+        // If there's no configuration, let's try to find a suitable implementation
+        if (answer == null) {
+            for (ServiceCallLoadBalancerConfiguration configuration : ServiceCallConstants.LOAD_BALANCER_CONFIGURATIONS) {
+                try {
+                    answer = configuration.newInstance(camelContext);
+
+                    if (answer != null) {
+                        break;
+                    }
+                } catch (NoFactoryAvailableException e) {
+                    // skip
+                }
+            }
+        }
+
+        if (answer == null) {
+            answer = new DefaultLoadBalancer();
+        }
+
+        return answer;
+    }
+
+    private Expression retrieveExpression(CamelContext camelContext, ServiceCallConfigurationDefinition config) throws Exception {
+        Expression answer;
+
+        if (expressionConfiguration != null) {
+            answer = expressionConfiguration.newInstance(camelContext);
+        } else if (config != null && config.getExpressionConfiguration() != null) {
+            answer = config.getExpressionConfiguration().newInstance(camelContext);
+        } else {
+            answer = retrieve(Expression.class, camelContext, this::getExpression, this::getExpressionRef);
+            if (answer == null && config != null) {
+                answer = retrieve(Expression.class, camelContext, config::getExpression, config::getExpressionRef);
+            }
+            if (answer == null) {
+                answer = findByType(camelContext, Expression.class);
+            }
+        }
+
+        if (answer == null) {
+            answer = new DefaultServiceCallExpression();
+        }
+
+        return answer;
+    }
+
+    private <T> T retrieve(Class<T> type, CamelContext camelContext, Supplier<T> instanceSupplier, Supplier<String> refSupplier) {
+        T answer = null;
+        if (instanceSupplier != null) {
+            answer = instanceSupplier.get();
+        }
+
+        if (answer == null && refSupplier != null) {
+            String ref = refSupplier.get();
+            if (ref != null) {
+                answer = CamelContextHelper.lookup(camelContext, ref, type);
+            }
+        }
+
+        return answer;
+    }
+
+    private <T> T findByType(CamelContext camelContext, Class<T> type) {
+        Set<T> set = camelContext.getRegistry().findByType(type);
+        if (set.size() == 1) {
+            return set.iterator().next();
+        }
+
+        return null;
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/camel-core/src/main/java/org/apache/camel/model/cloud/ServiceCallExpressionConfiguration.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/model/cloud/ServiceCallExpressionConfiguration.java b/camel-core/src/main/java/org/apache/camel/model/cloud/ServiceCallExpressionConfiguration.java
new file mode 100644
index 0000000..0b66595
--- /dev/null
+++ b/camel-core/src/main/java/org/apache/camel/model/cloud/ServiceCallExpressionConfiguration.java
@@ -0,0 +1,221 @@
+/**
+ * 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.cloud;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlTransient;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.Expression;
+import org.apache.camel.NoFactoryAvailableException;
+import org.apache.camel.cloud.ServiceExpressionFactory;
+import org.apache.camel.impl.cloud.ServiceCallConstants;
+import org.apache.camel.model.IdentifiedType;
+import org.apache.camel.model.ProcessorDefinition;
+import org.apache.camel.model.PropertyDefinition;
+import org.apache.camel.spi.Metadata;
+import org.apache.camel.util.CamelContextHelper;
+import org.apache.camel.util.IntrospectionSupport;
+import org.apache.camel.util.ObjectHelper;
+
+@Metadata(label = "routing,cloud")
+@XmlRootElement(name = "expressionConfiguration")
+@XmlAccessorType(XmlAccessType.FIELD)
+public class ServiceCallExpressionConfiguration extends IdentifiedType implements ServiceExpressionFactory {
+    private static final String RESOURCE_PATH = "META-INF/services/org/apache/camel/cloud/";
+
+    @XmlTransient
+    private final Optional<ServiceCallDefinition> parent;
+    @XmlTransient
+    private final String factoryKey;
+    @XmlElement(name = "properties") @Metadata(label = "advanced")
+    private List<PropertyDefinition> properties;
+    @XmlAttribute @Metadata(defaultValue = ServiceCallConstants.SERVICE_HOST)
+    private String hostHeader = ServiceCallConstants.SERVICE_HOST;
+    @XmlAttribute @Metadata(defaultValue = ServiceCallConstants.SERVICE_PORT)
+    private String portHeader = ServiceCallConstants.SERVICE_PORT;
+
+    public ServiceCallExpressionConfiguration() {
+        this(null, null);
+    }
+
+    public ServiceCallExpressionConfiguration(ServiceCallDefinition parent, String factoryKey) {
+        this.parent = Optional.ofNullable(parent);
+        this.factoryKey = factoryKey;
+    }
+
+    public ProcessorDefinition end() {
+        // end parent as well so we do not have to use 2x end
+        return this.parent.orElseGet(null);
+    }
+
+    // *************************************************************************
+    //
+    // *************************************************************************
+
+    public List<PropertyDefinition> getProperties() {
+        return properties;
+    }
+
+    /**
+     * Set client properties to use.
+     * <p/>
+     * These properties are specific to what service call implementation are in
+     * use. For example if using ribbon, then the client properties are define
+     * in com.netflix.client.config.CommonClientConfigKey.
+     */
+    public void setProperties(List<PropertyDefinition> properties) {
+        this.properties = properties;
+    }
+
+    /**
+     * Adds a custom property to use.
+     * <p/>
+     * These properties are specific to what service call implementation are in
+     * use. For example if using ribbon, then the client properties are define
+     * in com.netflix.client.config.CommonClientConfigKey.
+     */
+    public ServiceCallExpressionConfiguration property(String key, String value) {
+        if (properties == null) {
+            properties = new ArrayList<>();
+        }
+        PropertyDefinition prop = new PropertyDefinition();
+        prop.setKey(key);
+        prop.setValue(value);
+        properties.add(prop);
+        return this;
+    }
+
+    protected Map<String, String> getPropertiesAsMap(CamelContext camelContext) throws Exception {
+        Map<String, String> answer;
+
+        if (properties == null || properties.isEmpty()) {
+            answer = Collections.emptyMap();
+        } else {
+            answer = new HashMap<>();
+            for (PropertyDefinition prop : properties) {
+                // support property placeholders
+                String key = CamelContextHelper.parseText(camelContext, prop.getKey());
+                String value = CamelContextHelper.parseText(camelContext, prop.getValue());
+                answer.put(key, value);
+            }
+        }
+
+        return answer;
+    }
+
+    public String getHostHeader() {
+        return hostHeader;
+    }
+
+    /**
+     * The header that holds the service host information, default ServiceCallConstants.SERVICE_HOST
+     */
+    public void setHostHeader(String hostHeader) {
+        this.hostHeader = hostHeader;
+    }
+
+    public String getPortHeader() {
+        return portHeader;
+    }
+
+    /**
+     * The header that holds the service port information, default ServiceCallConstants.SERVICE_PORT
+     */
+    public void setPortHeader(String portHeader) {
+        this.portHeader = portHeader;
+    }
+
+    /**
+     * The header that holds the service host information, default ServiceCallConstants.SERVICE_HOST
+     */
+    public ServiceCallExpressionConfiguration hostHeader(String hostHeader) {
+        setHostHeader(hostHeader);
+        return this;
+    }
+
+    /**
+     * The header that holds the service port information, default ServiceCallConstants.SERVICE_PORT
+     */
+    public ServiceCallExpressionConfiguration portHeader(String portHeader) {
+        setPortHeader(portHeader);
+        return this;
+    }
+
+    // *************************************************************************
+    // Factory
+    // *************************************************************************
+
+    @Override
+    public Expression newInstance(CamelContext camelContext) throws Exception {
+        ObjectHelper.notNull(factoryKey, "Expression factoryKey");
+
+        Expression answer;
+
+        // First try to find the factory from the registry.
+        ServiceExpressionFactory factory = CamelContextHelper.lookup(camelContext, factoryKey, ServiceExpressionFactory.class);
+        if (factory != null) {
+            // If a factory is found in the registry do not re-configure it as
+            // it should be pre-configured.
+            answer = factory.newInstance(camelContext);
+        } else {
+
+            Class<?> type;
+            try {
+                // Then use Service factory.
+                type = camelContext.getFactoryFinder(RESOURCE_PATH).findClass(factoryKey);
+            } catch (Exception e) {
+                throw new NoFactoryAvailableException(RESOURCE_PATH + factoryKey, e);
+            }
+
+            if (type != null) {
+                if (ServiceExpressionFactory.class.isAssignableFrom(type)) {
+                    factory = (ServiceExpressionFactory) camelContext.getInjector().newInstance(type);
+                } else {
+                    throw new IllegalArgumentException(
+                        "Resolving Expression: " + factoryKey + " detected type conflict: Not a ExpressionFactory implementation. Found: " + type.getName());
+                }
+            }
+
+            try {
+                Map<String, Object> parameters = new HashMap<>();
+                IntrospectionSupport.getProperties(this, parameters, null, false);
+                parameters.put("properties", getPropertiesAsMap(camelContext));
+
+                IntrospectionSupport.setProperties(factory, parameters);
+
+
+                answer = factory.newInstance(camelContext);
+            } catch (Exception e) {
+                throw new IllegalArgumentException(e);
+            }
+        }
+
+        return answer;
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/camel-core/src/main/java/org/apache/camel/model/cloud/ServiceCallLoadBalancerConfiguration.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/model/cloud/ServiceCallLoadBalancerConfiguration.java b/camel-core/src/main/java/org/apache/camel/model/cloud/ServiceCallLoadBalancerConfiguration.java
new file mode 100644
index 0000000..8739a85
--- /dev/null
+++ b/camel-core/src/main/java/org/apache/camel/model/cloud/ServiceCallLoadBalancerConfiguration.java
@@ -0,0 +1,177 @@
+/**
+ * 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.cloud;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlTransient;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.NoFactoryAvailableException;
+import org.apache.camel.cloud.LoadBalancer;
+import org.apache.camel.cloud.LoadBalancerFactory;
+import org.apache.camel.model.IdentifiedType;
+import org.apache.camel.model.ProcessorDefinition;
+import org.apache.camel.model.PropertyDefinition;
+import org.apache.camel.spi.Metadata;
+import org.apache.camel.util.CamelContextHelper;
+import org.apache.camel.util.IntrospectionSupport;
+import org.apache.camel.util.ObjectHelper;
+
+@Metadata(label = "routing,cloud,load-balancing")
+@XmlRootElement(name = "loadBalancerConfiguration")
+@XmlAccessorType(XmlAccessType.FIELD)
+public class ServiceCallLoadBalancerConfiguration extends IdentifiedType implements LoadBalancerFactory {
+    private static final String RESOURCE_PATH = "META-INF/services/org/apache/camel/cloud/";
+
+    @XmlTransient
+    private final Optional<ServiceCallDefinition> parent;
+    @XmlTransient
+    private final String factoryKey;
+    @XmlElement(name = "properties") @Metadata(label = "advanced")
+    private List<PropertyDefinition> properties;
+
+    public ServiceCallLoadBalancerConfiguration() {
+        this(null, null);
+    }
+
+    public ServiceCallLoadBalancerConfiguration(ServiceCallDefinition parent, String factoryKey) {
+        this.parent = Optional.ofNullable(parent);
+        this.factoryKey = factoryKey;
+    }
+
+    public ProcessorDefinition end() {
+        // end parent as well so we do not have to use 2x end
+        return this.parent.orElseGet(null);
+    }
+
+    // *************************************************************************
+    //
+    // *************************************************************************
+
+    public List<PropertyDefinition> getProperties() {
+        return properties;
+    }
+
+    /**
+     * Set client properties to use.
+     * <p/>
+     * These properties are specific to what service call implementation are in
+     * use. For example if using ribbon, then the client properties are define
+     * in com.netflix.client.config.CommonClientConfigKey.
+     */
+    public void setProperties(List<PropertyDefinition> properties) {
+        this.properties = properties;
+    }
+
+    /**
+     * Adds a custom property to use.
+     * <p/>
+     * These properties are specific to what service call implementation are in
+     * use. For example if using ribbon, then the client properties are define
+     * in com.netflix.client.config.CommonClientConfigKey.
+     */
+    public ServiceCallLoadBalancerConfiguration property(String key, String value) {
+        if (properties == null) {
+            properties = new ArrayList<>();
+        }
+        PropertyDefinition prop = new PropertyDefinition();
+        prop.setKey(key);
+        prop.setValue(value);
+        properties.add(prop);
+        return this;
+    }
+
+    protected Map<String, String> getPropertiesAsMap(CamelContext camelContext) throws Exception {
+        Map<String, String> answer;
+
+        if (properties == null || properties.isEmpty()) {
+            answer = Collections.emptyMap();
+        } else {
+            answer = new HashMap<>();
+            for (PropertyDefinition prop : properties) {
+                // support property placeholders
+                String key = CamelContextHelper.parseText(camelContext, prop.getKey());
+                String value = CamelContextHelper.parseText(camelContext, prop.getValue());
+                answer.put(key, value);
+            }
+        }
+
+        return answer;
+    }
+
+    // *************************************************************************
+    // Factory
+    // *************************************************************************
+
+    @Override
+    public LoadBalancer newInstance(CamelContext camelContext) throws Exception {
+        ObjectHelper.notNull(factoryKey, "LoadBalancer factoryKey");
+
+        LoadBalancer answer;
+
+        // First try to find the factory from the registry.
+        LoadBalancerFactory factory = CamelContextHelper.lookup(camelContext, factoryKey, LoadBalancerFactory.class);
+        if (factory != null) {
+            // If a factory is found in the registry do not re-configure it as
+            // it should be pre-configured.
+            answer = factory.newInstance(camelContext);
+        } else {
+
+            Class<?> type;
+            try {
+                // Then use Service factory.
+                type = camelContext.getFactoryFinder(RESOURCE_PATH).findClass(factoryKey);
+            } catch (Exception e) {
+                throw new NoFactoryAvailableException(RESOURCE_PATH + factoryKey, e);
+            }
+
+            if (type != null) {
+                if (LoadBalancerFactory.class.isAssignableFrom(type)) {
+                    factory = (LoadBalancerFactory) camelContext.getInjector().newInstance(type);
+                } else {
+                    throw new IllegalArgumentException(
+                        "Resolving LoadBalancer: " + factoryKey + " detected type conflict: Not a LoadBalancerFactory implementation. Found: " + type.getName());
+                }
+            }
+
+            try {
+                Map<String, Object> parameters = new HashMap<>();
+                IntrospectionSupport.getProperties(this, parameters, null, false);
+                parameters.put("properties", getPropertiesAsMap(camelContext));
+
+                IntrospectionSupport.setProperties(factory, parameters);
+
+
+                answer = factory.newInstance(camelContext);
+            } catch (Exception e) {
+                throw new IllegalArgumentException(e);
+            }
+        }
+
+        return answer;
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/camel-core/src/main/java/org/apache/camel/model/cloud/ServiceCallServiceChooserConfiguration.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/model/cloud/ServiceCallServiceChooserConfiguration.java b/camel-core/src/main/java/org/apache/camel/model/cloud/ServiceCallServiceChooserConfiguration.java
new file mode 100644
index 0000000..d3a418b
--- /dev/null
+++ b/camel-core/src/main/java/org/apache/camel/model/cloud/ServiceCallServiceChooserConfiguration.java
@@ -0,0 +1,177 @@
+/**
+ * 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.cloud;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlTransient;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.NoFactoryAvailableException;
+import org.apache.camel.cloud.ServiceChooser;
+import org.apache.camel.cloud.ServiceChooserFactory;
+import org.apache.camel.model.IdentifiedType;
+import org.apache.camel.model.ProcessorDefinition;
+import org.apache.camel.model.PropertyDefinition;
+import org.apache.camel.spi.Metadata;
+import org.apache.camel.util.CamelContextHelper;
+import org.apache.camel.util.IntrospectionSupport;
+import org.apache.camel.util.ObjectHelper;
+
+@Metadata(label = "routing,cloud,service-discovery")
+@XmlRootElement(name = "serviceChooserConfiguration")
+@XmlAccessorType(XmlAccessType.FIELD)
+public class ServiceCallServiceChooserConfiguration extends IdentifiedType implements ServiceChooserFactory {
+    private static final String RESOURCE_PATH = "META-INF/services/org/apache/camel/cloud/";
+
+    @XmlTransient
+    private final Optional<ServiceCallDefinition> parent;
+    @XmlTransient
+    private final String factoryKey;
+    @XmlElement(name = "properties") @Metadata(label = "advanced")
+    private List<PropertyDefinition> properties;
+
+    public ServiceCallServiceChooserConfiguration() {
+        this(null, null);
+    }
+
+    public ServiceCallServiceChooserConfiguration(ServiceCallDefinition parent, String factoryKey) {
+        this.parent = Optional.ofNullable(parent);
+        this.factoryKey = factoryKey;
+    }
+
+    public ProcessorDefinition end() {
+        // end parent as well so we do not have to use 2x end
+        return this.parent.orElseGet(null);
+    }
+
+    // *************************************************************************
+    //
+    // *************************************************************************
+
+    public List<PropertyDefinition> getProperties() {
+        return properties;
+    }
+
+    /**
+     * Set client properties to use.
+     * <p/>
+     * These properties are specific to what service call implementation are in
+     * use. For example if using ribbon, then the client properties are define
+     * in com.netflix.client.config.CommonClientConfigKey.
+     */
+    public void setProperties(List<PropertyDefinition> properties) {
+        this.properties = properties;
+    }
+
+    /**
+     * Adds a custom property to use.
+     * <p/>
+     * These properties are specific to what service call implementation are in
+     * use. For example if using ribbon, then the client properties are define
+     * in com.netflix.client.config.CommonClientConfigKey.
+     */
+    public ServiceCallServiceChooserConfiguration property(String key, String value) {
+        if (properties == null) {
+            properties = new ArrayList<>();
+        }
+        PropertyDefinition prop = new PropertyDefinition();
+        prop.setKey(key);
+        prop.setValue(value);
+        properties.add(prop);
+        return this;
+    }
+
+    protected Map<String, String> getPropertiesAsMap(CamelContext camelContext) throws Exception {
+        Map<String, String> answer;
+
+        if (properties == null || properties.isEmpty()) {
+            answer = Collections.emptyMap();
+        } else {
+            answer = new HashMap<>();
+            for (PropertyDefinition prop : properties) {
+                // support property placeholders
+                String key = CamelContextHelper.parseText(camelContext, prop.getKey());
+                String value = CamelContextHelper.parseText(camelContext, prop.getValue());
+                answer.put(key, value);
+            }
+        }
+
+        return answer;
+    }
+
+    // *************************************************************************
+    // Factory
+    // *************************************************************************
+
+    @Override
+    public ServiceChooser newInstance(CamelContext camelContext) throws Exception {
+        ObjectHelper.notNull(factoryKey, "ServiceChooser factoryKey");
+
+        ServiceChooser answer;
+
+        // First try to find the factory from the registry.
+        ServiceChooserFactory factory = CamelContextHelper.lookup(camelContext, factoryKey, ServiceChooserFactory.class);
+        if (factory != null) {
+            // If a factory is found in the registry do not re-configure it as
+            // it should be pre-configured.
+            answer = factory.newInstance(camelContext);
+        } else {
+
+            Class<?> type;
+            try {
+                // Then use Service factory.
+                type = camelContext.getFactoryFinder(RESOURCE_PATH).findClass(factoryKey);
+            } catch (Exception e) {
+                throw new NoFactoryAvailableException(RESOURCE_PATH + factoryKey, e);
+            }
+
+            if (type != null) {
+                if (ServiceChooserFactory.class.isAssignableFrom(type)) {
+                    factory = (ServiceChooserFactory) camelContext.getInjector().newInstance(type);
+                } else {
+                    throw new NoFactoryAvailableException(
+                        "Resolving ServiceChooser: " + factoryKey + " detected type conflict: Not a ServiceChooserFactory implementation. Found: " + type.getName());
+                }
+            }
+
+            try {
+                Map<String, Object> parameters = new HashMap<>();
+                IntrospectionSupport.getProperties(this, parameters, null, false);
+                parameters.put("properties", getPropertiesAsMap(camelContext));
+
+                IntrospectionSupport.setProperties(factory, parameters);
+
+
+                answer = factory.newInstance(camelContext);
+            } catch (Exception e) {
+                throw new IllegalArgumentException(e);
+            }
+        }
+
+        return answer;
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/camel-core/src/main/java/org/apache/camel/model/cloud/ServiceCallServiceDiscoveryConfiguration.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/model/cloud/ServiceCallServiceDiscoveryConfiguration.java b/camel-core/src/main/java/org/apache/camel/model/cloud/ServiceCallServiceDiscoveryConfiguration.java
new file mode 100644
index 0000000..600705b
--- /dev/null
+++ b/camel-core/src/main/java/org/apache/camel/model/cloud/ServiceCallServiceDiscoveryConfiguration.java
@@ -0,0 +1,177 @@
+/**
+ * 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.cloud;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlTransient;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.NoFactoryAvailableException;
+import org.apache.camel.cloud.ServiceDiscovery;
+import org.apache.camel.cloud.ServiceDiscoveryFactory;
+import org.apache.camel.model.IdentifiedType;
+import org.apache.camel.model.ProcessorDefinition;
+import org.apache.camel.model.PropertyDefinition;
+import org.apache.camel.spi.Metadata;
+import org.apache.camel.util.CamelContextHelper;
+import org.apache.camel.util.IntrospectionSupport;
+import org.apache.camel.util.ObjectHelper;
+
+@Metadata(label = "routing,cloud,service-discovery")
+@XmlRootElement(name = "serviceDiscoveryConfiguration")
+@XmlAccessorType(XmlAccessType.FIELD)
+public class ServiceCallServiceDiscoveryConfiguration extends IdentifiedType implements ServiceDiscoveryFactory {
+    private static final String RESOURCE_PATH = "META-INF/services/org/apache/camel/cloud/";
+
+    @XmlTransient
+    private final Optional<ServiceCallDefinition> parent;
+    @XmlTransient
+    private final String factoryKey;
+    @XmlElement(name = "properties") @Metadata(label = "advanced")
+    private List<PropertyDefinition> properties;
+
+    public ServiceCallServiceDiscoveryConfiguration() {
+        this(null, null);
+    }
+
+    public ServiceCallServiceDiscoveryConfiguration(ServiceCallDefinition parent, String factoryKey) {
+        this.parent = Optional.ofNullable(parent);
+        this.factoryKey = factoryKey;
+    }
+
+    public ProcessorDefinition end() {
+        // end parent as well so we do not have to use 2x end
+        return this.parent.orElseGet(null);
+    }
+
+    // *************************************************************************
+    //
+    // *************************************************************************
+
+    public List<PropertyDefinition> getProperties() {
+        return properties;
+    }
+
+    /**
+     * Set client properties to use.
+     * <p/>
+     * These properties are specific to what service call implementation are in
+     * use. For example if using ribbon, then the client properties are define
+     * in com.netflix.client.config.CommonClientConfigKey.
+     */
+    public void setProperties(List<PropertyDefinition> properties) {
+        this.properties = properties;
+    }
+
+    /**
+     * Adds a custom property to use.
+     * <p/>
+     * These properties are specific to what service call implementation are in
+     * use. For example if using ribbon, then the client properties are define
+     * in com.netflix.client.config.CommonClientConfigKey.
+     */
+    public ServiceCallServiceDiscoveryConfiguration property(String key, String value) {
+        if (properties == null) {
+            properties = new ArrayList<>();
+        }
+        PropertyDefinition prop = new PropertyDefinition();
+        prop.setKey(key);
+        prop.setValue(value);
+        properties.add(prop);
+        return this;
+    }
+
+    protected Map<String, String> getPropertiesAsMap(CamelContext camelContext) throws Exception {
+        Map<String, String> answer;
+
+        if (properties == null || properties.isEmpty()) {
+            answer = Collections.emptyMap();
+        } else {
+            answer = new HashMap<>();
+            for (PropertyDefinition prop : properties) {
+                // support property placeholders
+                String key = CamelContextHelper.parseText(camelContext, prop.getKey());
+                String value = CamelContextHelper.parseText(camelContext, prop.getValue());
+                answer.put(key, value);
+            }
+        }
+
+        return answer;
+    }
+
+    // *************************************************************************
+    // Factory
+    // *************************************************************************
+
+    @Override
+    public ServiceDiscovery newInstance(CamelContext camelContext) throws Exception {
+        ObjectHelper.notNull(factoryKey, "ServiceDiscovery factoryKey");
+
+        ServiceDiscovery answer;
+
+        // First try to find the factory from the registry.
+        ServiceDiscoveryFactory factory = CamelContextHelper.lookup(camelContext, factoryKey, ServiceDiscoveryFactory.class);
+        if (factory != null) {
+            // If a factory is found in the registry do not re-configure it as
+            // it should be pre-configured.
+            answer = factory.newInstance(camelContext);
+        } else {
+
+            Class<?> type;
+            try {
+                // Then use Service factory.
+                type = camelContext.getFactoryFinder(RESOURCE_PATH).findClass(factoryKey);
+            } catch (Exception e) {
+                throw new NoFactoryAvailableException(RESOURCE_PATH + factoryKey, e);
+            }
+
+            if (type != null) {
+                if (ServiceDiscoveryFactory.class.isAssignableFrom(type)) {
+                    factory = (ServiceDiscoveryFactory) camelContext.getInjector().newInstance(type);
+                } else {
+                    throw new IllegalArgumentException(
+                        "Resolving ServiceDiscovery: " + factoryKey + " detected type conflict: Not a ServiceDiscoveryFactory implementation. Found: " + type.getName());
+                }
+            }
+
+            try {
+                Map<String, Object> parameters = new HashMap<>();
+                IntrospectionSupport.getProperties(this, parameters, null, false);
+                parameters.put("properties", getPropertiesAsMap(camelContext));
+
+                IntrospectionSupport.setProperties(factory, parameters);
+
+
+                answer = factory.newInstance(camelContext);
+            } catch (Exception e) {
+                throw new IllegalArgumentException(e);
+            }
+        }
+
+        return answer;
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/camel-core/src/main/java/org/apache/camel/model/cloud/ServiceCallServiceFilterConfiguration.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/model/cloud/ServiceCallServiceFilterConfiguration.java b/camel-core/src/main/java/org/apache/camel/model/cloud/ServiceCallServiceFilterConfiguration.java
new file mode 100644
index 0000000..09651fa
--- /dev/null
+++ b/camel-core/src/main/java/org/apache/camel/model/cloud/ServiceCallServiceFilterConfiguration.java
@@ -0,0 +1,177 @@
+/**
+ * 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.cloud;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlTransient;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.NoFactoryAvailableException;
+import org.apache.camel.cloud.ServiceFilter;
+import org.apache.camel.cloud.ServiceFilterFactory;
+import org.apache.camel.model.IdentifiedType;
+import org.apache.camel.model.ProcessorDefinition;
+import org.apache.camel.model.PropertyDefinition;
+import org.apache.camel.spi.Metadata;
+import org.apache.camel.util.CamelContextHelper;
+import org.apache.camel.util.IntrospectionSupport;
+import org.apache.camel.util.ObjectHelper;
+
+@Metadata(label = "routing,cloud,service-discovery")
+@XmlRootElement(name = "serviceFilterConfiguration")
+@XmlAccessorType(XmlAccessType.FIELD)
+public class ServiceCallServiceFilterConfiguration extends IdentifiedType implements ServiceFilterFactory {
+    private static final String RESOURCE_PATH = "META-INF/services/org/apache/camel/cloud/";
+
+    @XmlTransient
+    private final Optional<ServiceCallDefinition> parent;
+    @XmlTransient
+    private final String factoryKey;
+    @XmlElement(name = "properties") @Metadata(label = "advanced")
+    private List<PropertyDefinition> properties;
+
+    public ServiceCallServiceFilterConfiguration() {
+        this(null, null);
+    }
+
+    public ServiceCallServiceFilterConfiguration(ServiceCallDefinition parent, String factoryKey) {
+        this.parent = Optional.ofNullable(parent);
+        this.factoryKey = factoryKey;
+    }
+
+    public ProcessorDefinition end() {
+        // end parent as well so we do not have to use 2x end
+        return this.parent.orElseGet(null);
+    }
+
+    // *************************************************************************
+    //
+    // *************************************************************************
+
+    public List<PropertyDefinition> getProperties() {
+        return properties;
+    }
+
+    /**
+     * Set client properties to use.
+     * <p/>
+     * These properties are specific to what service call implementation are in
+     * use. For example if using ribbon, then the client properties are define
+     * in com.netflix.client.config.CommonClientConfigKey.
+     */
+    public void setProperties(List<PropertyDefinition> properties) {
+        this.properties = properties;
+    }
+
+    /**
+     * Adds a custom property to use.
+     * <p/>
+     * These properties are specific to what service call implementation are in
+     * use. For example if using ribbon, then the client properties are define
+     * in com.netflix.client.config.CommonClientConfigKey.
+     */
+    public ServiceCallServiceFilterConfiguration property(String key, String value) {
+        if (properties == null) {
+            properties = new ArrayList<>();
+        }
+        PropertyDefinition prop = new PropertyDefinition();
+        prop.setKey(key);
+        prop.setValue(value);
+        properties.add(prop);
+        return this;
+    }
+
+    protected Map<String, String> getPropertiesAsMap(CamelContext camelContext) throws Exception {
+        Map<String, String> answer;
+
+        if (properties == null || properties.isEmpty()) {
+            answer = Collections.emptyMap();
+        } else {
+            answer = new HashMap<>();
+            for (PropertyDefinition prop : properties) {
+                // support property placeholders
+                String key = CamelContextHelper.parseText(camelContext, prop.getKey());
+                String value = CamelContextHelper.parseText(camelContext, prop.getValue());
+                answer.put(key, value);
+            }
+        }
+
+        return answer;
+    }
+
+    // *************************************************************************
+    // Factory
+    // *************************************************************************
+
+    @Override
+    public ServiceFilter newInstance(CamelContext camelContext) throws Exception {
+        ObjectHelper.notNull(factoryKey, "ServiceFilter factoryKey");
+
+        ServiceFilter answer;
+
+        // First try to find the factory from the registry.
+        ServiceFilterFactory factory = CamelContextHelper.lookup(camelContext, factoryKey, ServiceFilterFactory.class);
+        if (factory != null) {
+            // If a factory is found in the registry do not re-configure it as
+            // it should be pre-configured.
+            answer = factory.newInstance(camelContext);
+        } else {
+
+            Class<?> type;
+            try {
+                // Then use Service factory.
+                type = camelContext.getFactoryFinder(RESOURCE_PATH).findClass(factoryKey);
+            } catch (Exception e) {
+                throw new NoFactoryAvailableException(RESOURCE_PATH + factoryKey, e);
+            }
+
+            if (type != null) {
+                if (ServiceFilterFactory.class.isAssignableFrom(type)) {
+                    factory = (ServiceFilterFactory) camelContext.getInjector().newInstance(type);
+                } else {
+                    throw new NoFactoryAvailableException(
+                        "Resolving ServiceFilter: " + factoryKey + " detected type conflict: Not a ServiceFilterFactory implementation. Found: " + type.getName());
+                }
+            }
+
+            try {
+                Map<String, Object> parameters = new HashMap<>();
+                IntrospectionSupport.getProperties(this, parameters, null, false);
+                parameters.put("properties", getPropertiesAsMap(camelContext));
+
+                IntrospectionSupport.setProperties(factory, parameters);
+
+
+                answer = factory.newInstance(camelContext);
+            } catch (Exception e) {
+                throw new IllegalArgumentException(e);
+            }
+        }
+
+        return answer;
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/camel-core/src/main/java/org/apache/camel/model/cloud/StaticServiceCallServiceDiscoveryConfiguration.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/model/cloud/StaticServiceCallServiceDiscoveryConfiguration.java b/camel-core/src/main/java/org/apache/camel/model/cloud/StaticServiceCallServiceDiscoveryConfiguration.java
new file mode 100644
index 0000000..0c5dae1
--- /dev/null
+++ b/camel-core/src/main/java/org/apache/camel/model/cloud/StaticServiceCallServiceDiscoveryConfiguration.java
@@ -0,0 +1,69 @@
+/**
+ * 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.cloud;
+
+import java.util.List;
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+
+import org.apache.camel.spi.Metadata;
+
+@Metadata(label = "routing,cloud,service-discovery")
+@XmlRootElement(name = "staticServiceDiscovery")
+@XmlAccessorType(XmlAccessType.FIELD)
+public class StaticServiceCallServiceDiscoveryConfiguration extends ServiceCallServiceDiscoveryConfiguration {
+    @XmlElement
+    private List<String> servers;
+
+    public StaticServiceCallServiceDiscoveryConfiguration() {
+        this(null);
+    }
+
+    public StaticServiceCallServiceDiscoveryConfiguration(ServiceCallDefinition parent) {
+        super(parent, "static-service-discovery");
+    }
+
+    // *************************************************************************
+    // Properties
+    // *************************************************************************
+
+    public List<String> getServers() {
+        return servers;
+    }
+
+    /**
+     * Sets the server list;
+     */
+    public void setServers(List<String> servers) {
+        this.servers = servers;
+    }
+
+    // *************************************************************************
+    // Fluent API
+    // *************************************************************************
+
+    /**
+     * Sets the server list;
+     */
+    public StaticServiceCallServiceDiscoveryConfiguration servers(List<String> servers) {
+        setServers(servers);
+        return this;
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/camel-core/src/main/java/org/apache/camel/model/cloud/package-info.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/model/cloud/package-info.java b/camel-core/src/main/java/org/apache/camel/model/cloud/package-info.java
new file mode 100644
index 0000000..f3d02a6
--- /dev/null
+++ b/camel-core/src/main/java/org/apache/camel/model/cloud/package-info.java
@@ -0,0 +1,23 @@
+/**
+ * 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.
+ */
+
+
+/**
+ * The JAXB POJOs for the remote service call DSL
+ */
+@javax.xml.bind.annotation.XmlSchema(namespace = "http://camel.apache.org/schema/spring", elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED)
+package org.apache.camel.model.cloud;


[05/10] camel git commit: CAMEL-10638: Refactor ServiceCall EIP

Posted by lb...@apache.org.
http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/components/camel-dns/src/main/java/org/apache/camel/component/dns/cloud/DnsServiceDiscoveryFactory.java
----------------------------------------------------------------------
diff --git a/components/camel-dns/src/main/java/org/apache/camel/component/dns/cloud/DnsServiceDiscoveryFactory.java b/components/camel-dns/src/main/java/org/apache/camel/component/dns/cloud/DnsServiceDiscoveryFactory.java
new file mode 100644
index 0000000..18568d7
--- /dev/null
+++ b/components/camel-dns/src/main/java/org/apache/camel/component/dns/cloud/DnsServiceDiscoveryFactory.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.dns.cloud;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.cloud.ServiceDiscovery;
+import org.apache.camel.cloud.ServiceDiscoveryFactory;
+import org.apache.camel.component.dns.DnsConfiguration;
+
+public class DnsServiceDiscoveryFactory implements ServiceDiscoveryFactory {
+    private final DnsConfiguration configuration;
+
+    public DnsServiceDiscoveryFactory() {
+        this.configuration = new DnsConfiguration();
+    }
+
+    // *************************************************************************
+    // Properties
+    // *************************************************************************
+
+    public String getProto() {
+        return configuration.getProto();
+    }
+
+    public void setProto(String proto) {
+        configuration.setProto(proto);
+    }
+
+    public String getDomain() {
+        return configuration.getDomain();
+    }
+
+    public void setDomain(String domain) {
+        configuration.setDomain(domain);
+    }
+
+    // *************************************************************************
+    // Factory
+    // *************************************************************************
+
+    @Override
+    public ServiceDiscovery newInstance(CamelContext camelContext) throws Exception {
+        return new DnsServiceDiscovery(configuration);
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/components/camel-dns/src/main/java/org/apache/camel/component/dns/processor/remote/DnsServiceCallProcessor.java
----------------------------------------------------------------------
diff --git a/components/camel-dns/src/main/java/org/apache/camel/component/dns/processor/remote/DnsServiceCallProcessor.java b/components/camel-dns/src/main/java/org/apache/camel/component/dns/processor/remote/DnsServiceCallProcessor.java
deleted file mode 100644
index f469428..0000000
--- a/components/camel-dns/src/main/java/org/apache/camel/component/dns/processor/remote/DnsServiceCallProcessor.java
+++ /dev/null
@@ -1,42 +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.dns.processor.remote;
-
-import org.apache.camel.ExchangePattern;
-import org.apache.camel.component.dns.DnsConfiguration;
-import org.apache.camel.impl.remote.DefaultServiceCallProcessor;
-import org.apache.camel.spi.ServiceCallServer;
-import org.apache.camel.spi.ServiceCallServerListStrategy;
-
-/**
- * @author lburgazzoli
- */
-public class DnsServiceCallProcessor extends DefaultServiceCallProcessor<ServiceCallServer> {
-    public DnsServiceCallProcessor(String name, String scheme, String uri, ExchangePattern exchangePattern, DnsConfiguration conf) {
-        super(name, scheme, uri, exchangePattern);
-    }
-
-    @Override
-    public void setServerListStrategy(ServiceCallServerListStrategy<ServiceCallServer> serverListStrategy) {
-        if (!(serverListStrategy instanceof DnsServiceCallServerListStrategy)) {
-            throw new IllegalArgumentException("ServerListStrategy is not an instance of DnsServiceCallServerListStrategy");
-        }
-
-        super.setServerListStrategy(serverListStrategy);
-    }
-}

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/components/camel-dns/src/main/java/org/apache/camel/component/dns/processor/remote/DnsServiceCallProcessorFactory.java
----------------------------------------------------------------------
diff --git a/components/camel-dns/src/main/java/org/apache/camel/component/dns/processor/remote/DnsServiceCallProcessorFactory.java b/components/camel-dns/src/main/java/org/apache/camel/component/dns/processor/remote/DnsServiceCallProcessorFactory.java
deleted file mode 100644
index 6c285a6..0000000
--- a/components/camel-dns/src/main/java/org/apache/camel/component/dns/processor/remote/DnsServiceCallProcessorFactory.java
+++ /dev/null
@@ -1,68 +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.dns.processor.remote;
-
-import java.util.Map;
-import java.util.Optional;
-
-import org.apache.camel.ExchangePattern;
-import org.apache.camel.component.dns.DnsConfiguration;
-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 DnsServiceCallProcessorFactory extends DefaultServiceCallProcessorFactory<DnsConfiguration, ServiceCallServer> {
-    @Override
-    protected DnsConfiguration createConfiguration(RouteContext routeContext) throws Exception {
-        return new DnsConfiguration();
-    }
-
-    @Override
-    protected DefaultServiceCallProcessor createProcessor(
-            String name,
-            String component,
-            String uri,
-            ExchangePattern mep,
-            DnsConfiguration conf,
-            Map<String, String> properties) throws Exception {
-
-        return new DnsServiceCallProcessor(name, component, uri, mep, conf);
-    }
-
-    @Override
-    protected Optional<ServiceCallServerListStrategy> builtInServerListStrategy(DnsConfiguration conf, String name) throws Exception {
-        ServiceCallServerListStrategy strategy = null;
-        if (ObjectHelper.equal("ondemand", name, true)) {
-            strategy = new DnsServiceCallServerListStrategies.OnDemand(conf);
-        }
-
-        return Optional.ofNullable(strategy);
-    }
-
-    @Override
-    protected ServiceCallServerListStrategy<ServiceCallServer> createDefaultServerListStrategy(DnsConfiguration conf) throws Exception {
-        return new DnsServiceCallServerListStrategies.OnDemand(conf);
-    }
-}

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/components/camel-dns/src/main/java/org/apache/camel/component/dns/processor/remote/DnsServiceCallServer.java
----------------------------------------------------------------------
diff --git a/components/camel-dns/src/main/java/org/apache/camel/component/dns/processor/remote/DnsServiceCallServer.java b/components/camel-dns/src/main/java/org/apache/camel/component/dns/processor/remote/DnsServiceCallServer.java
deleted file mode 100644
index 77b7082..0000000
--- a/components/camel-dns/src/main/java/org/apache/camel/component/dns/processor/remote/DnsServiceCallServer.java
+++ /dev/null
@@ -1,53 +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.dns.processor.remote;
-
-import java.util.Comparator;
-import java.util.HashMap;
-import java.util.Map;
-
-import org.apache.camel.impl.remote.DefaultServiceCallServer;
-import org.xbill.DNS.SRVRecord;
-
-import static org.apache.camel.util.ObjectHelper.ifNotEmpty;
-
-public class DnsServiceCallServer extends DefaultServiceCallServer {
-    public static final Comparator<SRVRecord> COMPARATOR = comparator();
-
-    public DnsServiceCallServer(SRVRecord record) {
-        super(
-            record.getTarget().toString(true),
-            record.getPort(),
-            getRecordMetaData(record)
-        );
-    }
-
-    public static Comparator<SRVRecord> comparator() {
-        Comparator<SRVRecord> byPriority = (e1, e2) -> Integer.compare(e2.getPriority(), e1.getPriority());
-        Comparator<SRVRecord> byWeight = (e1, e2) -> Integer.compare(e2.getWeight(), e1.getWeight());
-
-        return byPriority.thenComparing(byWeight);
-    }
-
-    public static Map<String, String> getRecordMetaData(SRVRecord record) {
-        Map<String, String> meta = new HashMap<>();
-        ifNotEmpty(record.getPriority(), val -> meta.put("priority", Integer.toString(val)));
-        ifNotEmpty(record.getWeight(), val -> meta.put("weight", Integer.toString(val)));
-
-        return meta;
-    }
-}

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/components/camel-dns/src/main/java/org/apache/camel/component/dns/processor/remote/DnsServiceCallServerListStrategies.java
----------------------------------------------------------------------
diff --git a/components/camel-dns/src/main/java/org/apache/camel/component/dns/processor/remote/DnsServiceCallServerListStrategies.java b/components/camel-dns/src/main/java/org/apache/camel/component/dns/processor/remote/DnsServiceCallServerListStrategies.java
deleted file mode 100644
index e69ff17..0000000
--- a/components/camel-dns/src/main/java/org/apache/camel/component/dns/processor/remote/DnsServiceCallServerListStrategies.java
+++ /dev/null
@@ -1,77 +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.dns.processor.remote;
-
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-import java.util.Objects;
-import java.util.stream.Collectors;
-
-import org.apache.camel.component.dns.DnsConfiguration;
-import org.apache.camel.spi.ServiceCallServer;
-import org.xbill.DNS.Lookup;
-import org.xbill.DNS.Record;
-import org.xbill.DNS.SRVRecord;
-
-
-public final class DnsServiceCallServerListStrategies {
-    private DnsServiceCallServerListStrategies() {
-    }
-
-    public static final class OnDemand extends DnsServiceCallServerListStrategy {
-        private final DnsServiceLookupFactory lookupFactory;
-
-        public OnDemand(DnsConfiguration configuration) throws Exception {
-            super(configuration);
-            this.lookupFactory = new DnsServiceLookupFactory(configuration);
-        }
-
-        @Override
-        public List<ServiceCallServer> getUpdatedListOfServers(String name) {
-            final Lookup lookup = lookupFactory.apply(name);
-            final Record[] records = lookup.run();
-
-            List<ServiceCallServer> servers;
-            if (Objects.nonNull(records) && lookup.getResult() == Lookup.SUCCESSFUL) {
-                servers = Arrays.stream(records)
-                    .filter(SRVRecord.class::isInstance)
-                    .map(SRVRecord.class::cast)
-                    .sorted(DnsServiceCallServer.COMPARATOR)
-                    .map(DnsServiceCallServer::new)
-                    .collect(Collectors.toList());
-            } else {
-                servers = Collections.emptyList();
-            }
-
-            return servers;
-        }
-
-        @Override
-        public String toString() {
-            return "OnDemand";
-        }
-    }
-
-    // *************************************************************************
-    // Helpers
-    // *************************************************************************
-
-    public static DnsServiceCallServerListStrategy onDemand(DnsConfiguration configuration) throws Exception {
-        return new OnDemand(configuration);
-    }
-}

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/components/camel-dns/src/main/java/org/apache/camel/component/dns/processor/remote/DnsServiceCallServerListStrategy.java
----------------------------------------------------------------------
diff --git a/components/camel-dns/src/main/java/org/apache/camel/component/dns/processor/remote/DnsServiceCallServerListStrategy.java b/components/camel-dns/src/main/java/org/apache/camel/component/dns/processor/remote/DnsServiceCallServerListStrategy.java
deleted file mode 100644
index 85ae26a..0000000
--- a/components/camel-dns/src/main/java/org/apache/camel/component/dns/processor/remote/DnsServiceCallServerListStrategy.java
+++ /dev/null
@@ -1,33 +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.dns.processor.remote;
-
-import org.apache.camel.component.dns.DnsConfiguration;
-import org.apache.camel.impl.remote.DefaultServiceCallServerListStrategy;
-import org.apache.camel.spi.ServiceCallServer;
-
-public class DnsServiceCallServerListStrategy extends DefaultServiceCallServerListStrategy<ServiceCallServer> {
-    private final DnsConfiguration configuration;
-
-    public DnsServiceCallServerListStrategy(DnsConfiguration configuration) {
-        this.configuration = configuration;
-    }
-
-    protected DnsConfiguration getConfiguration() {
-        return configuration;
-    }
-}

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/components/camel-dns/src/main/java/org/apache/camel/component/dns/processor/remote/DnsServiceLookupFactory.java
----------------------------------------------------------------------
diff --git a/components/camel-dns/src/main/java/org/apache/camel/component/dns/processor/remote/DnsServiceLookupFactory.java b/components/camel-dns/src/main/java/org/apache/camel/component/dns/processor/remote/DnsServiceLookupFactory.java
deleted file mode 100644
index ce63c96..0000000
--- a/components/camel-dns/src/main/java/org/apache/camel/component/dns/processor/remote/DnsServiceLookupFactory.java
+++ /dev/null
@@ -1,52 +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.dns.processor.remote;
-
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.function.Function;
-
-import org.apache.camel.RuntimeCamelException;
-import org.apache.camel.component.dns.DnsConfiguration;
-import org.xbill.DNS.Lookup;
-import org.xbill.DNS.TextParseException;
-import org.xbill.DNS.Type;
-
-public class DnsServiceLookupFactory implements Function<String, Lookup> {
-    private final DnsConfiguration configuration;
-    private final ConcurrentHashMap<String, Lookup> cache;
-
-    public DnsServiceLookupFactory(DnsConfiguration configuration) {
-        this.configuration = configuration;
-        this.cache = new ConcurrentHashMap<>();
-    }
-
-    @Override
-    public Lookup apply(String name) {
-        return cache.computeIfAbsent(name, this::createLookup);
-    }
-
-    private Lookup createLookup(String name) {
-        try {
-            return new Lookup(
-                String.format("%s.%s.%s", name, configuration.getProto(), configuration.getDomain()),
-                Type.SRV);
-        } catch (TextParseException e) {
-            throw new RuntimeCamelException(e);
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/components/camel-dns/src/main/resources/META-INF/services/org/apache/camel/cloud/dns-service-discovery
----------------------------------------------------------------------
diff --git a/components/camel-dns/src/main/resources/META-INF/services/org/apache/camel/cloud/dns-service-discovery b/components/camel-dns/src/main/resources/META-INF/services/org/apache/camel/cloud/dns-service-discovery
new file mode 100644
index 0000000..4c667da
--- /dev/null
+++ b/components/camel-dns/src/main/resources/META-INF/services/org/apache/camel/cloud/dns-service-discovery
@@ -0,0 +1,17 @@
+#
+# 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.dns.cloud.DnsServiceDiscoveryFactory

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/components/camel-dns/src/main/resources/META-INF/services/org/apache/camel/model/ServiceCallDefinition
----------------------------------------------------------------------
diff --git a/components/camel-dns/src/main/resources/META-INF/services/org/apache/camel/model/ServiceCallDefinition b/components/camel-dns/src/main/resources/META-INF/services/org/apache/camel/model/ServiceCallDefinition
deleted file mode 100644
index d0bd19b..0000000
--- a/components/camel-dns/src/main/resources/META-INF/services/org/apache/camel/model/ServiceCallDefinition
+++ /dev/null
@@ -1,18 +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.
-#
-
-class=org.apache.camel.component.dns.processor.remote.DnsServiceCallProcessorFactory

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/components/camel-dns/src/test/java/org/apache/camel/component/dns/cloud/DnsServiceDiscoveryTest.java
----------------------------------------------------------------------
diff --git a/components/camel-dns/src/test/java/org/apache/camel/component/dns/cloud/DnsServiceDiscoveryTest.java b/components/camel-dns/src/test/java/org/apache/camel/component/dns/cloud/DnsServiceDiscoveryTest.java
new file mode 100644
index 0000000..e204e95
--- /dev/null
+++ b/components/camel-dns/src/test/java/org/apache/camel/component/dns/cloud/DnsServiceDiscoveryTest.java
@@ -0,0 +1,48 @@
+/**
+ * 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.dns.cloud;
+
+import java.util.List;
+
+import org.apache.camel.cloud.ServiceDefinition;
+import org.apache.camel.component.dns.DnsConfiguration;
+import org.junit.Test;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+
+public class DnsServiceDiscoveryTest {
+    @Test
+    public void testServiceDiscovery() throws Exception {
+        DnsConfiguration configuration = new DnsConfiguration();
+        DnsServiceDiscovery discovery = new DnsServiceDiscovery(configuration);
+
+        configuration.setDomain("gmail.com");
+        configuration.setProto("_tcp");
+
+        List<ServiceDefinition> services = discovery.getUpdatedListOfServices("_xmpp-server");
+        assertNotNull(services);
+        assertFalse(services.isEmpty());
+
+        for (ServiceDefinition service : services) {
+            assertFalse(service.getMetadata().isEmpty());
+            assertNotNull(service.getMetadata().get("priority"));
+            assertNotNull(service.getMetadata().get("weight"));
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/components/camel-dns/src/test/java/org/apache/camel/component/dns/processor/remote/DnsServiceCallServerListStrategiesTest.java
----------------------------------------------------------------------
diff --git a/components/camel-dns/src/test/java/org/apache/camel/component/dns/processor/remote/DnsServiceCallServerListStrategiesTest.java b/components/camel-dns/src/test/java/org/apache/camel/component/dns/processor/remote/DnsServiceCallServerListStrategiesTest.java
deleted file mode 100644
index e13eab2..0000000
--- a/components/camel-dns/src/test/java/org/apache/camel/component/dns/processor/remote/DnsServiceCallServerListStrategiesTest.java
+++ /dev/null
@@ -1,47 +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.dns.processor.remote;
-
-import java.util.List;
-
-import org.apache.camel.component.dns.DnsConfiguration;
-import org.apache.camel.spi.ServiceCallServer;
-import org.junit.Test;
-
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-
-public class DnsServiceCallServerListStrategiesTest {
-    @Test
-    public void testOnDemand() throws Exception {
-        DnsConfiguration configuration = new DnsConfiguration();
-        DnsServiceCallServerListStrategy strategy = DnsServiceCallServerListStrategies.onDemand(configuration);
-
-        configuration.setDomain("gmail.com");
-        configuration.setProto("_tcp");
-
-        List<ServiceCallServer> servers = strategy.getUpdatedListOfServers("_xmpp-server");
-        assertNotNull(servers);
-        assertFalse(servers.isEmpty());
-
-        for (ServiceCallServer server : servers) {
-            assertFalse(server.getMetadata().isEmpty());
-            assertNotNull(server.getMetadata().get("priority"));
-            assertNotNull(server.getMetadata().get("weight"));
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/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 aeb089a..4c97ceb 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
@@ -51,6 +51,10 @@ public class EtcdConfiguration {
 
     private final CamelContext camelContext;
 
+    public EtcdConfiguration() {
+        this.camelContext = null;
+    }
+
     public EtcdConfiguration(CamelContext camelContext) {
         this.camelContext = camelContext;
     }

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/components/camel-etcd/src/main/java/org/apache/camel/component/etcd/cloud/EtcdOnDemandServiceDiscovery.java
----------------------------------------------------------------------
diff --git a/components/camel-etcd/src/main/java/org/apache/camel/component/etcd/cloud/EtcdOnDemandServiceDiscovery.java b/components/camel-etcd/src/main/java/org/apache/camel/component/etcd/cloud/EtcdOnDemandServiceDiscovery.java
new file mode 100644
index 0000000..6eb5e9f
--- /dev/null
+++ b/components/camel-etcd/src/main/java/org/apache/camel/component/etcd/cloud/EtcdOnDemandServiceDiscovery.java
@@ -0,0 +1,34 @@
+/**
+ * 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.cloud;
+
+import java.util.List;
+
+import org.apache.camel.cloud.ServiceDefinition;
+import org.apache.camel.component.etcd.EtcdConfiguration;
+
+public class EtcdOnDemandServiceDiscovery extends EtcdServiceDiscovery {
+    public EtcdOnDemandServiceDiscovery(EtcdConfiguration configuration) throws Exception {
+        super(configuration);
+    }
+
+    @Override
+    public List<ServiceDefinition> getUpdatedListOfServices(String name) {
+        return getServices(s -> name.equalsIgnoreCase(s.getName()));
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/components/camel-etcd/src/main/java/org/apache/camel/component/etcd/cloud/EtcdServiceDefinition.java
----------------------------------------------------------------------
diff --git a/components/camel-etcd/src/main/java/org/apache/camel/component/etcd/cloud/EtcdServiceDefinition.java b/components/camel-etcd/src/main/java/org/apache/camel/component/etcd/cloud/EtcdServiceDefinition.java
new file mode 100644
index 0000000..8a9d276
--- /dev/null
+++ b/components/camel-etcd/src/main/java/org/apache/camel/component/etcd/cloud/EtcdServiceDefinition.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.cloud;
+
+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.cloud.DefaultServiceDefinition;
+
+public class EtcdServiceDefinition extends DefaultServiceDefinition {
+    public static final Comparator<EtcdServiceDefinition> COMPARATOR = comparator();
+
+    @JsonCreator
+    public EtcdServiceDefinition(
+        @JsonProperty("name") final String name,
+        @JsonProperty("address") final String address,
+        @JsonProperty("port") final Integer port,
+        @JsonProperty("tags") final Map<String, String> tags) {
+        super(name, address, port, tags);
+    }
+
+    public static Comparator<EtcdServiceDefinition> comparator() {
+        Comparator<EtcdServiceDefinition> byAddress = (e1, e2) -> e2.getHost().compareTo(e1.getHost());
+        Comparator<EtcdServiceDefinition> byPort = (e1, e2) -> Integer.compare(e2.getPort(), e1.getPort());
+
+        return byAddress.thenComparing(byPort);
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/components/camel-etcd/src/main/java/org/apache/camel/component/etcd/cloud/EtcdServiceDiscovery.java
----------------------------------------------------------------------
diff --git a/components/camel-etcd/src/main/java/org/apache/camel/component/etcd/cloud/EtcdServiceDiscovery.java b/components/camel-etcd/src/main/java/org/apache/camel/component/etcd/cloud/EtcdServiceDiscovery.java
new file mode 100644
index 0000000..edb0c4c
--- /dev/null
+++ b/components/camel-etcd/src/main/java/org/apache/camel/component/etcd/cloud/EtcdServiceDiscovery.java
@@ -0,0 +1,120 @@
+/**
+ * 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.cloud;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Objects;
+import java.util.concurrent.TimeUnit;
+import java.util.function.Predicate;
+import java.util.stream.Collectors;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import mousio.etcd4j.EtcdClient;
+import mousio.etcd4j.requests.EtcdKeyGetRequest;
+import mousio.etcd4j.responses.EtcdKeysResponse;
+import org.apache.camel.RuntimeCamelException;
+import org.apache.camel.cloud.ServiceDefinition;
+import org.apache.camel.component.etcd.EtcdConfiguration;
+import org.apache.camel.component.etcd.EtcdHelper;
+import org.apache.camel.impl.cloud.DefaultServiceDiscovery;
+import org.apache.camel.util.ObjectHelper;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+abstract class EtcdServiceDiscovery extends DefaultServiceDiscovery {
+    private static final Logger LOGGER = LoggerFactory.getLogger(EtcdServiceDiscovery.class);
+    private static final ObjectMapper MAPPER = EtcdHelper.createObjectMapper();
+
+    private final EtcdConfiguration configuration;
+    private EtcdClient client;
+
+    EtcdServiceDiscovery(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 EtcdServiceDefinition nodeFromString(String value) {
+        EtcdServiceDefinition server = null;
+
+        try {
+            server = MAPPER.readValue(value, EtcdServiceDefinition.class);
+        } catch (Exception e) {
+            LOGGER.warn("", e);
+        }
+
+        return server;
+    }
+
+    protected List<ServiceDefinition> getServices() {
+        return getServices(s -> true);
+    }
+
+    protected List<ServiceDefinition> getServices(Predicate<EtcdServiceDefinition> filter) {
+        List<ServiceDefinition> servers = Collections.emptyList();
+
+        if (isRunAllowed()) {
+            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(filter)
+                        .sorted(EtcdServiceDefinition.COMPARATOR)
+                        .collect(Collectors.toList());
+                }
+            } catch (Exception e) {
+                throw new RuntimeCamelException(e);
+            }
+        }
+
+        return servers;
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/components/camel-etcd/src/main/java/org/apache/camel/component/etcd/cloud/EtcdServiceDiscoveryFactory.java
----------------------------------------------------------------------
diff --git a/components/camel-etcd/src/main/java/org/apache/camel/component/etcd/cloud/EtcdServiceDiscoveryFactory.java b/components/camel-etcd/src/main/java/org/apache/camel/component/etcd/cloud/EtcdServiceDiscoveryFactory.java
new file mode 100644
index 0000000..5bf89e0
--- /dev/null
+++ b/components/camel-etcd/src/main/java/org/apache/camel/component/etcd/cloud/EtcdServiceDiscoveryFactory.java
@@ -0,0 +1,112 @@
+/**
+ * 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.cloud;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.cloud.ServiceDiscovery;
+import org.apache.camel.cloud.ServiceDiscoveryFactory;
+import org.apache.camel.component.etcd.EtcdConfiguration;
+import org.apache.camel.util.ObjectHelper;
+import org.apache.camel.util.jsse.SSLContextParameters;
+
+public class EtcdServiceDiscoveryFactory implements ServiceDiscoveryFactory {
+    private final EtcdConfiguration configuration;
+    private String type;
+
+    public EtcdServiceDiscoveryFactory() {
+        this.configuration = new EtcdConfiguration();
+    }
+
+    // *************************************************************************
+    // Properties
+    // *************************************************************************
+
+    public String getUris() {
+        return configuration.getUris();
+    }
+
+    public void setUris(String uris) {
+        configuration.setUris(uris);
+    }
+
+    public SSLContextParameters getSslContextParameters() {
+        return configuration.getSslContextParameters();
+    }
+
+    public void setSslContextParameters(SSLContextParameters sslContextParameters) {
+        configuration.setSslContextParameters(sslContextParameters);
+    }
+
+    public String getUserName() {
+        return configuration.getUserName();
+    }
+
+    public void setUserName(String userName) {
+        configuration.setUserName(userName);
+    }
+
+    public String getPassword() {
+        return configuration.getPassword();
+    }
+
+    public void setPassword(String password) {
+        configuration.setPassword(password);
+    }
+
+    public Integer getTimeToLive() {
+        return configuration.getTimeToLive();
+    }
+
+    public void setTimeToLive(Integer timeToLive) {
+        configuration.setTimeToLive(timeToLive);
+    }
+
+    public Long getTimeout() {
+        return configuration.getTimeout();
+    }
+
+    public void setTimeout(Long timeout) {
+        configuration.setTimeout(timeout);
+    }
+
+    public String getServicePath() {
+        return configuration.getServicePath();
+    }
+
+    public void setServicePath(String servicePath) {
+        configuration.setServicePath(servicePath);
+    }
+
+    public String getType() {
+        return type;
+    }
+
+    public void setType(String type) {
+        this.type = type;
+    }
+
+    // *************************************************************************
+    // Factory
+    // *************************************************************************
+
+    @Override
+    public ServiceDiscovery newInstance(CamelContext camelContext) throws Exception {
+        return ObjectHelper.equal("watch", type, true)
+            ? new EtcdWatchServiceDiscovery(configuration)
+            : new EtcdOnDemandServiceDiscovery(configuration);
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/components/camel-etcd/src/main/java/org/apache/camel/component/etcd/cloud/EtcdWatchServiceDiscovery.java
----------------------------------------------------------------------
diff --git a/components/camel-etcd/src/main/java/org/apache/camel/component/etcd/cloud/EtcdWatchServiceDiscovery.java b/components/camel-etcd/src/main/java/org/apache/camel/component/etcd/cloud/EtcdWatchServiceDiscovery.java
new file mode 100644
index 0000000..587ee25
--- /dev/null
+++ b/components/camel-etcd/src/main/java/org/apache/camel/component/etcd/cloud/EtcdWatchServiceDiscovery.java
@@ -0,0 +1,122 @@
+/**
+ * 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.cloud;
+
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+import java.util.concurrent.atomic.AtomicLong;
+import java.util.concurrent.atomic.AtomicReference;
+import java.util.stream.Collectors;
+
+import mousio.client.promises.ResponsePromise;
+import mousio.etcd4j.responses.EtcdException;
+import mousio.etcd4j.responses.EtcdKeysResponse;
+import org.apache.camel.RuntimeCamelException;
+import org.apache.camel.cloud.ServiceDefinition;
+import org.apache.camel.component.etcd.EtcdConfiguration;
+import org.apache.camel.component.etcd.EtcdHelper;
+import org.apache.camel.util.ObjectHelper;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class EtcdWatchServiceDiscovery
+        extends EtcdServiceDiscovery
+        implements ResponsePromise.IsSimplePromiseResponseHandler<EtcdKeysResponse> {
+
+    private static final Logger LOGGER = LoggerFactory.getLogger(EtcdWatchServiceDiscovery.class);
+    private final AtomicReference<List<ServiceDefinition>> serversRef;
+    private final AtomicLong index;
+    private final String servicePath;
+
+    public EtcdWatchServiceDiscovery(EtcdConfiguration configuration) throws Exception {
+        super(configuration);
+
+        this.serversRef = new AtomicReference<>();
+        this.index = new AtomicLong(0);
+        this.servicePath = ObjectHelper.notNull(configuration.getServicePath(), "servicePath");
+    }
+
+    @Override
+    public List<ServiceDefinition> getUpdatedListOfServices(String name) {
+        List<ServiceDefinition> servers = serversRef.get();
+        if (servers == null) {
+            serversRef.set(getServices());
+            watch();
+        }
+
+        return serversRef.get().stream()
+            .filter(s -> name.equalsIgnoreCase(s.getName()))
+            .collect(Collectors.toList());
+    }
+
+    // *************************************************************************
+    // Watch
+    // *************************************************************************
+
+    @Override
+    public void onResponse(ResponsePromise<EtcdKeysResponse> promise) {
+        if (!isRunAllowed()) {
+            return;
+        }
+
+        Throwable throwable = promise.getException();
+        if (throwable != null && throwable instanceof EtcdException) {
+            EtcdException exception = (EtcdException) throwable;
+            if (EtcdHelper.isOutdatedIndexException(exception)) {
+                LOGGER.debug("Outdated index, key={}, cause={}", servicePath, exception.etcdCause);
+                index.set(exception.index + 1);
+            }
+        } else {
+            try {
+                EtcdKeysResponse response = promise.get();
+                EtcdHelper.setIndex(index, response);
+
+                serversRef.set(getServices());
+            } catch (TimeoutException e) {
+                LOGGER.debug("Timeout watching for {}", getConfiguration().getServicePath());
+                throwable = null;
+            } catch (Exception e) {
+                throwable = e;
+            }
+        }
+
+        if (throwable == null) {
+            watch();
+        } else {
+            throw new RuntimeCamelException(throwable);
+        }
+    }
+
+    private void watch() {
+        if (!isRunAllowed()) {
+            return;
+        }
+
+        try {
+            getClient().get(servicePath)
+                .recursive()
+                .waitForChange(index.get())
+                .timeout(1, TimeUnit.SECONDS)
+                .send()
+                .addListener(this);
+        } catch (Exception e) {
+            throw new RuntimeCamelException(e);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/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
deleted file mode 100644
index f1200a2..0000000
--- a/components/camel-etcd/src/main/java/org/apache/camel/component/etcd/processor/remote/EtcdServiceCallProcessor.java
+++ /dev/null
@@ -1,42 +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;
-
-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.ServiceCallServerListStrategy;
-
-/**
- * {@link ProcessorFactory} that creates the Etcd implementation of the ServiceCall EIP.
- */
-public class EtcdServiceCallProcessor extends DefaultServiceCallProcessor<EtcdServiceCallServer> {
-    public EtcdServiceCallProcessor(String name, String scheme, String uri, ExchangePattern exchangePattern, EtcdConfiguration conf) {
-        super(name, scheme, uri, exchangePattern);
-    }
-
-    @Override
-    public void setServerListStrategy(ServiceCallServerListStrategy<EtcdServiceCallServer> 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/a811f400/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
deleted file mode 100644
index 370916e..0000000
--- a/components/camel-etcd/src/main/java/org/apache/camel/component/etcd/processor/remote/EtcdServiceCallProcessorFactory.java
+++ /dev/null
@@ -1,69 +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;
-
-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.ServiceCallServerListStrategy;
-import org.apache.camel.util.ObjectHelper;
-
-/**
- * {@link ProcessorFactory} that creates the Etcd implementation of the ServiceCall EIP.
- */
-public class EtcdServiceCallProcessorFactory extends DefaultServiceCallProcessorFactory<EtcdConfiguration, EtcdServiceCallServer> {
-    @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);
-        } else if (ObjectHelper.equal("watch", name, true)) {
-            strategy = new EtcdServiceCallServerListStrategies.OnDemand(conf);
-        }
-
-        return Optional.ofNullable(strategy);
-    }
-
-    @Override
-    protected ServiceCallServerListStrategy<EtcdServiceCallServer> createDefaultServerListStrategy(EtcdConfiguration conf) throws Exception {
-        return new EtcdServiceCallServerListStrategies.OnDemand(conf);
-    }
-}

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/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
deleted file mode 100644
index 648b544..0000000
--- a/components/camel-etcd/src/main/java/org/apache/camel/component/etcd/processor/remote/EtcdServiceCallServer.java
+++ /dev/null
@@ -1,52 +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;
-
-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;
-
-    @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, tags);
-
-        this.name = name;
-    }
-
-    public String getName() {
-        return name;
-    }
-
-    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/a811f400/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
deleted file mode 100644
index d65ced9..0000000
--- a/components/camel-etcd/src/main/java/org/apache/camel/component/etcd/processor/remote/EtcdServiceCallServerListStrategies.java
+++ /dev/null
@@ -1,203 +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;
-
-import java.util.Collections;
-import java.util.List;
-import java.util.Objects;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.TimeoutException;
-import java.util.concurrent.atomic.AtomicLong;
-import java.util.concurrent.atomic.AtomicReference;
-import java.util.function.Predicate;
-import java.util.stream.Collectors;
-
-import mousio.client.promises.ResponsePromise;
-import mousio.etcd4j.requests.EtcdKeyGetRequest;
-import mousio.etcd4j.responses.EtcdException;
-import mousio.etcd4j.responses.EtcdKeysResponse;
-import org.apache.camel.RuntimeCamelException;
-import org.apache.camel.component.etcd.EtcdConfiguration;
-import org.apache.camel.component.etcd.EtcdHelper;
-import org.apache.camel.util.ObjectHelper;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public final class EtcdServiceCallServerListStrategies {
-
-    private abstract static class AbstractStrategy extends EtcdServiceCallServerListStrategy {
-        AbstractStrategy(EtcdConfiguration configuration) throws Exception {
-            super(configuration);
-        }
-
-        protected List<EtcdServiceCallServer> getServers() {
-            return getServers(s -> true);
-        }
-
-        protected List<EtcdServiceCallServer> getServers(Predicate<EtcdServiceCallServer> filter) {
-            List<EtcdServiceCallServer> servers = Collections.emptyList();
-
-            if (isRunAllowed()) {
-                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(filter)
-                            .sorted(EtcdServiceCallServer.COMPARATOR)
-                            .collect(Collectors.toList());
-                    }
-                } catch (Exception e) {
-                    throw new RuntimeCamelException(e);
-                }
-            }
-
-            return servers;
-        }
-    }
-
-    private EtcdServiceCallServerListStrategies() {
-    }
-
-    public static final class OnDemand extends AbstractStrategy {
-        public OnDemand(EtcdConfiguration configuration) throws Exception {
-            super(configuration);
-        }
-
-        @Override
-        public List<EtcdServiceCallServer> getUpdatedListOfServers(String name) {
-            return getServers(s -> name.equalsIgnoreCase(s.getName()));
-        }
-
-        @Override
-        public String toString() {
-            return "EtcdServiceCallServerListStrategy.OnDemand";
-        }
-    }
-
-    public static final class Watch extends AbstractStrategy
-            implements ResponsePromise.IsSimplePromiseResponseHandler<EtcdKeysResponse> {
-
-        private static final Logger LOGGER = LoggerFactory.getLogger(Watch.class);
-        private final AtomicReference<List<EtcdServiceCallServer>> serversRef;
-        private final AtomicLong index;
-        private final String servicePath;
-
-        public Watch(EtcdConfiguration configuration) throws Exception {
-            super(configuration);
-
-            this.serversRef = new AtomicReference<>();
-            this.index = new AtomicLong(0);
-            this.servicePath = ObjectHelper.notNull(configuration.getServicePath(), "servicePath");
-        }
-
-        @Override
-        public List<EtcdServiceCallServer> getUpdatedListOfServers(String name) {
-            List<EtcdServiceCallServer> servers = serversRef.get();
-            if (servers == null) {
-                serversRef.set(getServers());
-                watch();
-            }
-
-            return serversRef.get().stream()
-                .filter(s -> name.equalsIgnoreCase(s.getName()))
-                .collect(Collectors.toList());
-        }
-
-        @Override
-        public String toString() {
-            return "EtcdServiceCallServerListStrategy.Watch";
-        }
-
-        // *************************************************************************
-        // Watch
-        // *************************************************************************
-
-        @Override
-        public void onResponse(ResponsePromise<EtcdKeysResponse> promise) {
-            if (!isRunAllowed()) {
-                return;
-            }
-
-            Throwable throwable = promise.getException();
-            if (throwable != null && throwable instanceof EtcdException) {
-                EtcdException exception = (EtcdException) throwable;
-                if (EtcdHelper.isOutdatedIndexException(exception)) {
-                    LOGGER.debug("Outdated index, key={}, cause={}", servicePath, exception.etcdCause);
-                    index.set(exception.index + 1);
-                }
-            } else {
-                try {
-                    EtcdKeysResponse response = promise.get();
-                    EtcdHelper.setIndex(index, response);
-
-                    serversRef.set(getServers());
-                } catch (TimeoutException e) {
-                    LOGGER.debug("Timeout watching for {}", getConfiguration().getServicePath());
-                    throwable = null;
-                } catch (Exception e) {
-                    throwable = e;
-                }
-            }
-
-            if (throwable == null) {
-                watch();
-            } else {
-                throw new RuntimeCamelException(throwable);
-            }
-        }
-
-        private void watch() {
-            if (!isRunAllowed()) {
-                return;
-            }
-
-            try {
-                getClient().get(servicePath)
-                    .recursive()
-                    .waitForChange(index.get())
-                    .timeout(1, TimeUnit.SECONDS)
-                    .send()
-                    .addListener(this);
-            } catch (Exception e) {
-                throw new RuntimeCamelException(e);
-            }
-        }
-    }
-
-    // *************************************************************************
-    // Helpers
-    // *************************************************************************
-
-    public static EtcdServiceCallServerListStrategy onDemand(EtcdConfiguration configuration) throws Exception {
-        return new OnDemand(configuration);
-    }
-
-    public static EtcdServiceCallServerListStrategy watch(EtcdConfiguration configuration) throws Exception {
-        return new Watch(configuration);
-    }
-}

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/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
deleted file mode 100644
index a91156a..0000000
--- a/components/camel-etcd/src/main/java/org/apache/camel/component/etcd/processor/remote/EtcdServiceCallServerListStrategy.java
+++ /dev/null
@@ -1,73 +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;
-
-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.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class EtcdServiceCallServerListStrategy extends DefaultServiceCallServerListStrategy<EtcdServiceCallServer> {
-    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/a811f400/components/camel-etcd/src/main/resources/META-INF/services/org/apache/camel/cloud/etcd-service-discovery
----------------------------------------------------------------------
diff --git a/components/camel-etcd/src/main/resources/META-INF/services/org/apache/camel/cloud/etcd-service-discovery b/components/camel-etcd/src/main/resources/META-INF/services/org/apache/camel/cloud/etcd-service-discovery
new file mode 100644
index 0000000..4d4505f
--- /dev/null
+++ b/components/camel-etcd/src/main/resources/META-INF/services/org/apache/camel/cloud/etcd-service-discovery
@@ -0,0 +1,17 @@
+#
+# 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.cloud.EtcdServiceDiscoveryFactory
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/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
deleted file mode 100644
index 0cd6c42..0000000
--- a/components/camel-etcd/src/main/resources/META-INF/services/org/apache/camel/model/ServiceCallDefinition
+++ /dev/null
@@ -1,18 +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.
-#
-
-class=org.apache.camel.component.etcd.processor.remote.EtcdServiceCallProcessorFactory

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/components/camel-etcd/src/test/java/org/apache/camel/component/etcd/cloud/EtcdServiceCallRouteTest.java
----------------------------------------------------------------------
diff --git a/components/camel-etcd/src/test/java/org/apache/camel/component/etcd/cloud/EtcdServiceCallRouteTest.java b/components/camel-etcd/src/test/java/org/apache/camel/component/etcd/cloud/EtcdServiceCallRouteTest.java
new file mode 100644
index 0000000..766eeca
--- /dev/null
+++ b/components/camel-etcd/src/test/java/org/apache/camel/component/etcd/cloud/EtcdServiceCallRouteTest.java
@@ -0,0 +1,118 @@
+/**
+ * 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.cloud;
+
+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.cloud.ServiceDiscovery;
+import org.apache.camel.component.etcd.EtcdConfiguration;
+import org.apache.camel.component.etcd.EtcdHelper;
+import org.apache.camel.component.etcd.EtcdTestSupport;
+import org.junit.Test;
+
+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 {
+                EtcdConfiguration configuration = new EtcdConfiguration(null);
+                ServiceDiscovery discovery = new EtcdOnDemandServiceDiscovery(configuration);
+
+                from("direct:start")
+                    .serviceCall()
+                        .name(SERVICE_NAME)
+                        .component("http")
+                        .serviceDiscovery(discovery)
+                        .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/a811f400/components/camel-etcd/src/test/java/org/apache/camel/component/etcd/cloud/EtcdServiceDiscoveryTest.java
----------------------------------------------------------------------
diff --git a/components/camel-etcd/src/test/java/org/apache/camel/component/etcd/cloud/EtcdServiceDiscoveryTest.java b/components/camel-etcd/src/test/java/org/apache/camel/component/etcd/cloud/EtcdServiceDiscoveryTest.java
new file mode 100644
index 0000000..17ec0b2
--- /dev/null
+++ b/components/camel-etcd/src/test/java/org/apache/camel/component/etcd/cloud/EtcdServiceDiscoveryTest.java
@@ -0,0 +1,127 @@
+/**
+ * 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.cloud;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import mousio.etcd4j.EtcdClient;
+import mousio.etcd4j.responses.EtcdException;
+import org.apache.camel.cloud.ServiceDefinition;
+import org.apache.camel.component.etcd.EtcdConfiguration;
+import org.apache.camel.component.etcd.EtcdHelper;
+import org.apache.camel.component.etcd.EtcdTestSupport;
+import org.junit.Test;
+
+public class EtcdServiceDiscoveryTest extends EtcdTestSupport {
+    private static final ObjectMapper MAPPER = EtcdHelper.createObjectMapper();
+    private static final EtcdConfiguration CONFIGURATION = new EtcdConfiguration(null);
+    private static final AtomicInteger PORT = new AtomicInteger(0);
+
+    private EtcdClient client;
+
+    @Override
+    public void doPreSetup() throws Exception {
+        client = getClient();
+        try {
+            client.deleteDir(CONFIGURATION.getServicePath()).recursive().send().get();
+        } catch (EtcdException e) {
+            // Ignore
+        }
+    }
+
+    @Override
+    public void tearDown() throws Exception {
+        try {
+            client.deleteDir(CONFIGURATION.getServicePath()).recursive().send().get();
+            client.close();
+            client = null;
+        } catch (EtcdException e) {
+            // Ignore
+        }
+    }
+
+    @Test
+    public void testOnDemandDiscovery() throws Exception {
+        for (int i = 0; i < 3; i++) {
+            addServer(client, "serviceType-1");
+        }
+        for (int i = 0; i < 2; i++) {
+            addServer(client, "serviceType-2");
+        }
+
+        EtcdOnDemandServiceDiscovery strategy = new EtcdOnDemandServiceDiscovery(CONFIGURATION);
+        strategy.start();
+
+        List<ServiceDefinition> type1 = strategy.getUpdatedListOfServices("serviceType-1");
+        assertEquals(3, type1.size());
+        for (ServiceDefinition service : type1) {
+            assertNotNull(service.getMetadata());
+            assertTrue(service.getMetadata().containsKey("service_name"));
+            assertTrue(service.getMetadata().containsKey("port_delta"));
+        }
+
+        List<ServiceDefinition> type2 = strategy.getUpdatedListOfServices("serviceType-2");
+        assertEquals(2, type2.size());
+        for (ServiceDefinition service : type2) {
+            assertNotNull(service.getMetadata());
+            assertTrue(service.getMetadata().containsKey("service_name"));
+            assertTrue(service.getMetadata().containsKey("port_delta"));
+        }
+
+        strategy.stop();
+    }
+
+    @Test
+    public void testWatchDiscovery() throws Exception {
+        addServer(client, "serviceType-3");
+
+        EtcdWatchServiceDiscovery strategy = new EtcdWatchServiceDiscovery(CONFIGURATION);
+        strategy.start();
+
+        assertEquals(1, strategy.getUpdatedListOfServices("serviceType-3").size());
+
+        addServer(client, "serviceType-3");
+        addServer(client, "serviceType-3");
+        addServer(client, "serviceType-4");
+
+        Thread.sleep(250);
+
+        assertEquals(3, strategy.getUpdatedListOfServices("serviceType-3").size());
+
+        strategy.stop();
+    }
+
+    private void addServer(EtcdClient client, String name) throws Exception {
+        int port = PORT.incrementAndGet();
+
+        Map<String, String> tags = new HashMap<>();
+        tags.put("service_name", name);
+        tags.put("port_delta", Integer.toString(port));
+
+        Map<String, Object> server = new HashMap<>();
+        server.put("name", name);
+        server.put("address", "127.0.0.1");
+        server.put("port", 8000 + port);
+        server.put("tags", tags);
+
+        client.put(CONFIGURATION.getServicePath() + "service-" + port, MAPPER.writeValueAsString(server)).send().get();
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/components/camel-etcd/src/test/java/org/apache/camel/component/etcd/cloud/SpringEtcdServiceCallDefaultRouteTest.java
----------------------------------------------------------------------
diff --git a/components/camel-etcd/src/test/java/org/apache/camel/component/etcd/cloud/SpringEtcdServiceCallDefaultRouteTest.java b/components/camel-etcd/src/test/java/org/apache/camel/component/etcd/cloud/SpringEtcdServiceCallDefaultRouteTest.java
new file mode 100644
index 0000000..1440ba2
--- /dev/null
+++ b/components/camel-etcd/src/test/java/org/apache/camel/component/etcd/cloud/SpringEtcdServiceCallDefaultRouteTest.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.cloud;
+
+import java.net.URI;
+
+import com.fasterxml.jackson.databind.JsonNode;
+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.test.spring.CamelSpringTestSupport;
+import org.junit.Test;
+import org.springframework.context.support.AbstractApplicationContext;
+import org.springframework.context.support.ClassPathXmlApplicationContext;
+
+public class SpringEtcdServiceCallDefaultRouteTest extends CamelSpringTestSupport {
+    private static final ObjectMapper MAPPER = EtcdHelper.createObjectMapper();
+    private static final EtcdConfiguration CONFIGURATION = new EtcdConfiguration();
+    private static final EtcdClient CLIENT = new EtcdClient(URI.create("http://localhost:2379"));
+
+    @Override
+    protected AbstractApplicationContext createApplicationContext() {
+        return new ClassPathXmlApplicationContext("org/apache/camel/component/etcd/cloud/SpringEtcdServiceCallDefaultRouteTest.xml");
+    }
+
+    // *************************************************************************
+    // Setup / tear down
+    // *************************************************************************
+
+    @Override
+    public void doPreSetup() throws Exception {
+        JsonNode service1 = MAPPER.createObjectNode()
+            .put("name", "http-service")
+            .put("address", "127.0.0.1")
+            .put("port", "9091");
+        JsonNode service2 = MAPPER.createObjectNode()
+            .put("name", "http-service")
+            .put("address", "127.0.0.1")
+            .put("port", "9092");
+
+        CLIENT.put(CONFIGURATION.getServicePath() + "service-1", MAPPER.writeValueAsString(service1)).send().get();
+        CLIENT.put(CONFIGURATION.getServicePath() + "service-2", MAPPER.writeValueAsString(service2)).send().get();
+
+        super.doPreSetup();
+    }
+
+    @Override
+    public void tearDown() throws Exception {
+        super.tearDown();
+        CLIENT.deleteDir(CONFIGURATION.getServicePath()).recursive().send().get();
+    }
+
+    // *************************************************************************
+    // Test
+    // *************************************************************************
+
+    @Test
+    public void testServiceCall() throws Exception {
+        getMockEndpoint("mock:result").expectedMessageCount(2);
+        getMockEndpoint("mock:result").expectedBodiesReceivedInAnyOrder("9091", "9092");
+
+        template.sendBody("direct:start", null);
+        template.sendBody("direct:start", null);
+
+        assertMockEndpointsSatisfied();
+    }
+}


[10/10] camel git commit: CAMEL-10638: Refactor ServiceCall EIP

Posted by lb...@apache.org.
CAMEL-10638: Refactor ServiceCall EIP


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

Branch: refs/heads/master
Commit: a811f4004040a6548cadf922f6f89a5268c6ce60
Parents: c928453
Author: lburgazzoli <lb...@gmail.com>
Authored: Thu Dec 22 18:27:11 2016 +0100
Committer: lburgazzoli <lb...@gmail.com>
Committed: Wed Jan 11 13:03:02 2017 +0100

----------------------------------------------------------------------
 camel-core/readme-eip.adoc                      |  17 +-
 .../java/org/apache/camel/CamelContext.java     |  16 +-
 .../org/apache/camel/cloud/LoadBalancer.java    |  29 +
 .../apache/camel/cloud/LoadBalancerFactory.java |  31 +
 .../camel/cloud/LoadBalancerFunction.java       |  25 +
 .../org/apache/camel/cloud/ServiceChooser.java  |  35 +
 .../apache/camel/cloud/ServiceChooserAware.java |  37 +
 .../camel/cloud/ServiceChooserFactory.java      |  31 +
 .../apache/camel/cloud/ServiceDefinition.java   |  52 ++
 .../apache/camel/cloud/ServiceDiscovery.java    |  47 ++
 .../camel/cloud/ServiceDiscoveryAware.java      |  37 +
 .../camel/cloud/ServiceDiscoveryFactory.java    |  31 +
 .../camel/cloud/ServiceExpressionFactory.java   |  33 +
 .../org/apache/camel/cloud/ServiceFilter.java   |  35 +
 .../apache/camel/cloud/ServiceFilterAware.java  |  37 +
 .../camel/cloud/ServiceFilterFactory.java       |  31 +
 .../org/apache/camel/cloud/ServiceHealth.java   |  32 +
 .../apache/camel/impl/DefaultCamelContext.java  |  33 +-
 .../camel/impl/cloud/AllServiceFilter.java      |  32 +
 .../impl/cloud/CachingServiceDiscovery.java     | 104 +++
 .../camel/impl/cloud/DefaultLoadBalancer.java   | 148 ++++
 .../cloud/DefaultServiceCallExpression.java     |  85 +++
 .../impl/cloud/DefaultServiceCallProcessor.java | 153 ++++
 .../impl/cloud/DefaultServiceDefinition.java    |  98 +++
 .../impl/cloud/DefaultServiceDiscovery.java     |  64 ++
 .../camel/impl/cloud/DefaultServiceFilter.java  |  30 +
 .../camel/impl/cloud/DefaultServiceHealth.java  |  57 ++
 .../camel/impl/cloud/HealthyServiceFilter.java  |  33 +
 .../camel/impl/cloud/RandomServiceChooser.java  |  45 ++
 .../impl/cloud/RoundRobinServiceChooser.java    |  41 ++
 .../camel/impl/cloud/ServiceCallConstants.java  |  29 +
 .../impl/cloud/StaticServiceDiscovery.java      | 132 ++++
 .../cloud/StaticServiceDiscoveryFactory.java    |  57 ++
 .../AbstractServiceCallProcessorFactory.java    |  42 --
 .../CachingServiceCallServiceListStrategy.java  | 105 ---
 .../remote/DefaultServiceCallExpression.java    |  48 --
 .../remote/DefaultServiceCallProcessor.java     | 250 -------
 .../DefaultServiceCallProcessorFactory.java     | 289 --------
 .../impl/remote/DefaultServiceCallServer.java   |  62 --
 .../DefaultServiceCallServerListStrategy.java   |  63 --
 .../remote/RandomServiceCallLoadBalancer.java   |  44 --
 .../RoundRobinServiceCallLoadBalancer.java      |  41 --
 .../camel/impl/remote/ServiceCallConstants.java |  24 -
 .../org/apache/camel/impl/remote/package.html   |  25 -
 .../java/org/apache/camel/model/Constants.java  |   2 +-
 .../apache/camel/model/ProcessorDefinition.java |   2 +-
 ...erviceCallServiceDiscoveryConfiguration.java | 258 +++++++
 ...erviceCallServiceDiscoveryConfiguration.java |  88 +++
 ...erviceCallServiceDiscoveryConfiguration.java | 194 +++++
 ...erviceCallServiceDiscoveryConfiguration.java | 421 +++++++++++
 ...bonServiceCallLoadBalancerConfiguration.java |  67 ++
 .../ServiceCallConfigurationDefinition.java     | 407 +++++++++++
 .../camel/model/cloud/ServiceCallConstants.java |  36 +
 .../model/cloud/ServiceCallDefinition.java      | 721 +++++++++++++++++++
 .../ServiceCallExpressionConfiguration.java     | 221 ++++++
 .../ServiceCallLoadBalancerConfiguration.java   | 177 +++++
 .../ServiceCallServiceChooserConfiguration.java | 177 +++++
 ...erviceCallServiceDiscoveryConfiguration.java | 177 +++++
 .../ServiceCallServiceFilterConfiguration.java  | 177 +++++
 ...erviceCallServiceDiscoveryConfiguration.java |  69 ++
 .../apache/camel/model/cloud/package-info.java  |  23 +
 .../remote/ConsulConfigurationDefinition.java   | 232 ------
 .../remote/DnsConfigurationDefinition.java      |  87 ---
 .../remote/EtcdConfigurationDefinition.java     | 159 ----
 .../KubernetesConfigurationDefinition.java      | 364 ----------
 .../remote/RibbonConfigurationDefinition.java   |  48 --
 .../ServiceCallConfigurationDefinition.java     | 222 ------
 .../model/remote/ServiceCallDefinition.java     | 313 --------
 .../remote/ServiceCallProcessorFactory.java     |  22 -
 .../apache/camel/model/remote/package-info.java |  23 -
 .../camel/spi/ServiceCallLoadBalancer.java      |  21 +-
 .../spi/ServiceCallLoadBalancerRequest.java     |  29 +
 .../org/apache/camel/spi/ServiceCallServer.java |  42 --
 .../spi/ServiceCallServerListStrategy.java      |  49 --
 .../apache/camel/spi/ServiceCallService.java    |  47 ++
 .../camel/spi/ServiceCallServiceChooser.java    |  35 +
 .../spi/ServiceCallServiceChooserAware.java     |  37 +
 .../camel/spi/ServiceCallServiceDiscovery.java  |  47 ++
 .../spi/ServiceCallServiceDiscoveryAware.java   |  37 +
 .../support/ServiceCallExpressionSupport.java   |  98 +--
 .../apache/camel/cloud/static-service-discovery |  17 +
 .../org/apache/camel/model/cloud/jaxb.index     |  28 +
 .../org/apache/camel/model/remote/jaxb.index    |  23 -
 ...chingServiceCallServiceListStrategyTest.java |  56 ++
 ...chingServiceCallServiceListStrategyTest.java |  56 --
 .../BlueprintModelJAXBContextFactory.java       |   1 +
 .../blueprint/CamelContextFactoryBean.java      |  26 +-
 .../handler/CamelNamespaceHandler.java          |   2 +-
 .../org/apache/camel/cdi/XmlCdiBeanFactory.java |   4 +-
 .../camel/cdi/xml/CamelContextFactoryBean.java  |  24 +-
 .../test/XmlServiceCallConfigurationTest.java   |  79 ++
 ...camel-context-service-call-configuration.xml |  52 ++
 components/camel-consul/pom.xml                 |   5 +
 .../component/consul/ConsulConfiguration.java   |   4 +
 .../consul/cloud/ConsulServiceDiscovery.java    | 104 +++
 .../cloud/ConsulServiceDiscoveryFactory.java    | 124 ++++
 .../remote/ConsulServiceCallProcessor.java      |  43 --
 .../ConsulServiceCallProcessorFactory.java      |  67 --
 .../ConsulServiceCallServerListStrategies.java  |  65 --
 .../ConsulServiceCallServerListStrategy.java    | 128 ----
 .../apache/camel/cloud/consul-service-discovery |  17 +
 .../apache/camel/model/ServiceCallDefinition    |  18 -
 .../cloud/ConsulServiceCallRouteTest.java       | 118 +++
 .../cloud/ConsulServiceDiscoveryTest.java       |  90 +++
 ...SpringConsulDefaultServiceCallRouteTest.java |  28 +
 .../SpringConsulRibbonServiceCallRouteTest.java |  28 +
 .../cloud/SpringConsulServiceCallRouteTest.java |  96 +++
 .../consul/policy/ConsulRoutePolicyMain.java    |   1 -
 .../remote/ConsulServiceCallRouteTest.java      | 114 ---
 ...nsulServiceCallServerListStrategiesTest.java |  92 ---
 .../SpringConsulDefaultServiceCallRouteTest.xml |  87 +++
 .../SpringConsulRibbonServiceCallRouteTest.xml  |  84 +++
 .../xml/AbstractCamelContextFactoryBean.java    |  14 +
 .../dns/cloud/DnsServiceDiscovery.java          | 102 +++
 .../dns/cloud/DnsServiceDiscoveryFactory.java   |  59 ++
 .../remote/DnsServiceCallProcessor.java         |  42 --
 .../remote/DnsServiceCallProcessorFactory.java  |  68 --
 .../processor/remote/DnsServiceCallServer.java  |  53 --
 .../DnsServiceCallServerListStrategies.java     |  77 --
 .../DnsServiceCallServerListStrategy.java       |  33 -
 .../remote/DnsServiceLookupFactory.java         |  52 --
 .../apache/camel/cloud/dns-service-discovery    |  17 +
 .../apache/camel/model/ServiceCallDefinition    |  18 -
 .../dns/cloud/DnsServiceDiscoveryTest.java      |  48 ++
 .../DnsServiceCallServerListStrategiesTest.java |  47 --
 .../camel/component/etcd/EtcdConfiguration.java |   4 +
 .../cloud/EtcdOnDemandServiceDiscovery.java     |  34 +
 .../etcd/cloud/EtcdServiceDefinition.java       |  45 ++
 .../etcd/cloud/EtcdServiceDiscovery.java        | 120 +++
 .../etcd/cloud/EtcdServiceDiscoveryFactory.java | 112 +++
 .../etcd/cloud/EtcdWatchServiceDiscovery.java   | 122 ++++
 .../remote/EtcdServiceCallProcessor.java        |  42 --
 .../remote/EtcdServiceCallProcessorFactory.java |  69 --
 .../processor/remote/EtcdServiceCallServer.java |  52 --
 .../EtcdServiceCallServerListStrategies.java    | 203 ------
 .../EtcdServiceCallServerListStrategy.java      |  73 --
 .../apache/camel/cloud/etcd-service-discovery   |  17 +
 .../apache/camel/model/ServiceCallDefinition    |  18 -
 .../etcd/cloud/EtcdServiceCallRouteTest.java    | 118 +++
 .../etcd/cloud/EtcdServiceDiscoveryTest.java    | 127 ++++
 .../SpringEtcdServiceCallDefaultRouteTest.java  |  83 +++
 .../cloud/SpringEtcdServiceCallRouteTest.java   |  96 +++
 .../remote/EtcdServiceCallRouteTest.java        | 117 ---
 .../EtcdServiceCallServerListStrategyTest.java  | 128 ----
 .../SpringEtcdServiceCallDefaultRouteTest.xml   |  48 ++
 .../cloud/SpringEtcdServiceCallRouteTest.xml    |  85 +++
 .../cloud/KubernetesClientServiceDiscovery.java | 148 ++++
 .../cloud/KubernetesDnsServiceDiscovery.java    |  48 ++
 .../cloud/KubernetesEnvServiceDiscovery.java    |  47 ++
 .../cloud/KubernetesServiceDiscovery.java       |  69 ++
 .../KubernetesServiceDiscoveryFactory.java      | 187 +++++
 .../KubernetesDnsServiceCallExpression.java     |  80 --
 .../processor/KubernetesProcessorFactory.java   |  74 --
 .../KubernetesServiceCallProcessor.java         |  53 --
 ...bernetesServiceCallServerListStrategies.java | 246 -------
 ...KubernetesServiceCallServerListStrategy.java |  70 --
 .../camel/cloud/kubernetes-service-discovery    |  17 +
 .../apache/camel/model/ServiceCallDefinition    |  18 -
 .../cloud/ServiceCallClientRouteTest.java       |  64 ++
 .../cloud/ServiceCallEnvironmentRouteTest.java  |  60 ++
 .../cloud/SpringServiceCallClientRouteTest.java |  42 ++
 .../cloud/SpringServiceCallDnsRouteTest.java    |  42 ++
 .../SpringServiceCallEnvironmentRouteTest.java  |  42 ++
 .../processor/ServiceCallClientRouteTest.java   |  62 --
 .../ServiceCallEnvironmentRouteTest.java        |  56 --
 .../SpringServiceCallClientRouteTest.java       |  41 --
 .../SpringServiceCallEnvironmentRouteTest.java  |  41 --
 .../cloud/SpringServiceCallClientRouteTest.xml  |  57 ++
 .../cloud/SpringServiceCallDnsRouteTest.xml     |  44 ++
 .../SpringServiceCallEnvironmentRouteTest.xml   |  44 ++
 .../SpringServiceCallClientRouteTest.xml        |  39 -
 .../SpringServiceCallEnvironmentRouteTest.xml   |  38 -
 .../component/ribbon/RibbonConfiguration.java   |  30 +-
 .../ribbon/cloud/RibbonLoadBalancer.java        | 231 ++++++
 .../ribbon/cloud/RibbonLoadBalancerFactory.java |  61 ++
 .../ribbon/cloud/RibbonServiceDefinition.java   |  74 ++
 .../processor/RibbonProcessorFactory.java       | 181 -----
 .../ribbon/processor/RibbonServer.java          |  59 --
 .../processor/RibbonServiceCallProcessor.java   | 250 -------
 ...bbonServiceCallStaticServerListStrategy.java | 108 ---
 .../org/apache/camel/cloud/ribbon-load-balancer |  17 +
 .../apache/camel/model/ServiceCallDefinition    |  18 -
 .../ribbon/cloud/RibbonServerListTest.java      |  56 ++
 .../RibbonServiceCallRegistryRouteTest.java     |  61 ++
 .../cloud/RibbonServiceCallRouteTest.java       |  72 ++
 .../cloud/RibbonServiceCallUpdateRouteTest.java |  99 +++
 .../cloud/SpringBeanServiceCallRouteTest.java   |  31 +
 .../SpringDslRibbonServiceCallRouteTest.java    |  31 +
 .../cloud/SpringRibbonServiceCallRouteTest.java |  40 +
 .../ribbon/processor/RibbonServerListTest.java  |  53 --
 .../RibbonServiceCallRegistryRouteTest.java     |  57 --
 .../processor/RibbonServiceCallRouteTest.java   |  65 --
 .../RibbonServiceCallUpdateRouteTest.java       |  90 ---
 .../SpringRibbonServiceCallRouteTest.java       |  46 --
 .../SpringBeanRibbonServiceCallRouteTest.xml    |  65 ++
 .../SpringDslRibbonServiceCallRouteTest.xml     |  58 ++
 .../SpringRibbonServiceCallRouteTest.xml        |  60 --
 .../spring/cloud/CamelCloudDiscoveryClient.java |  83 +++
 .../spring/cloud/CamelCloudLoadBalancer.java    |  71 ++
 .../cloud/CamelCloudServiceDiscovery.java       |  52 ++
 .../ServiceCallConfigurationProperties.java     | 113 +++
 ...erviceCallLoadBalancerAutoConfiguration.java |  54 ++
 ...viceCallServiceChooserAutoConfiguration.java |  64 ++
 ...ceCallServiceDiscoveryAutoConfiguration.java |  75 ++
 ...rviceCallServiceFilterAutoConfiguration.java |  58 ++
 .../CamelCloudServiceCallAutoConfiguration.java |  95 ---
 ...CloudServiceCallConfigurationProperties.java |  79 --
 .../CamelCloudServiceCallProcessor.java         | 200 -----
 .../CamelCloudServiceCallProcessorFactory.java  | 201 ------
 ...CamelCloudServiceCallServerListStrategy.java |  52 --
 .../apache/camel/model/ServiceCallDefinition    |  18 -
 .../main/resources/META-INF/spring.factories    |   4 +-
 .../CamelCloudServiceCallConfigurationTest.java |  76 ++
 .../cloud/CamelCloudServiceCallRibbonTest.java  |  85 +++
 .../spring/cloud/CamelCloudServiceCallTest.java |  86 +++
 .../remote/CamelCloudDiscoveryClient.java       |  71 --
 .../CamelCloudServiceCallConfigurationTest.java |  69 --
 .../remote/CamelCloudServiceCallRibbonTest.java |  83 ---
 .../remote/CamelCloudServiceCallTest.java       |  99 ---
 .../camel/osgi/CamelNamespaceHandler.java       |   1 +
 .../camel/spring/CamelContextFactoryBean.java   |  31 +-
 .../spring/handler/CamelNamespaceHandler.java   |  12 +-
 .../cloud/ServiceCallConfigurationTest.java     |  59 ++
 .../cloud/ServiceCallConfigurationTest.xml      |  51 ++
 .../cloud/ServiceCallConfigurationTest.java     |  50 ++
 .../cloud/ServiceCallConfigurationTest.xml      |  49 ++
 components/pom.xml                              |   4 +-
 227 files changed, 10338 insertions(+), 7192 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/camel-core/readme-eip.adoc
----------------------------------------------------------------------
diff --git a/camel-core/readme-eip.adoc b/camel-core/readme-eip.adoc
index 1be6f05..1e7285e 100644
--- a/camel-core/readme-eip.adoc
+++ b/camel-core/readme-eip.adoc
@@ -21,9 +21,6 @@ Enterprise Integration Patterns
 | link:src/main/docs/eips/circuitBreaker-eip.adoc[Circuit Breaker] +
 `<circuitBreaker>` | Circuit break load balancer
 
-| link:src/main/docs/eips/consulConfiguration-eip.adoc[Consul Configuration] +
-`<consulConfiguration>` | Consul remote service call configuration
-
 | link:src/main/docs/eips/convertBodyTo-eip.adoc[Convert Body To] +
 `<convertBodyTo>` | Converts the message body to another type
 
@@ -33,18 +30,12 @@ Enterprise Integration Patterns
 | link:src/main/docs/eips/delay-eip.adoc[Delay] +
 `<delay>` | Delays processing for a specified length of time
 
-| link:src/main/docs/eips/dnsConfiguration-eip.adoc[Dns Configuration] +
-`<dnsConfiguration>` | DNS remote service call configuration
-
 | link:src/main/docs/eips/dynamicRouter-eip.adoc[Dynamic Router] +
 `<dynamicRouter>` | Routes messages based on dynamic rules
 
 | link:src/main/docs/eips/enrich-eip.adoc[Enrich] +
 `<enrich>` | Enriches a message with data from a secondary resource
 
-| link:src/main/docs/eips/etcdConfiguration-eip.adoc[Etcd Configuration] +
-`<etcdConfiguration>` | Etcd remote service call configuration
-
 | link:src/main/docs/eips/failover-eip.adoc[Failover] +
 `<failover>` | Failover load balancer
 
@@ -69,9 +60,6 @@ Enterprise Integration Patterns
 | link:src/main/docs/eips/inOut-eip.adoc[In Out] +
 `<inOut>` | Marks the exchange pattern for the route to request/reply
 
-| link:src/main/docs/eips/kubernetesConfiguration-eip.adoc[Kubernetes Configuration] +
-`<kubernetesConfiguration>` | Kubernetes remote service call configuration
-
 | link:src/main/docs/eips/loadBalance-eip.adoc[Load Balance] +
 `<loadBalance>` | Balances message processing among a number of nodes
 
@@ -120,9 +108,6 @@ Enterprise Integration Patterns
 | link:src/main/docs/eips/resequence-eip.adoc[Resequence] +
 `<resequence>` | Resequences (re-order) messages based on an expression
 
-| link:src/main/docs/eips/ribbonConfiguration-eip.adoc[Ribbon Configuration] +
-`<ribbonConfiguration>` | Ribbon remote service call configuration
-
 | link:src/main/docs/eips/rollback-eip.adoc[Rollback] +
 `<rollback>` | Forces a rollback by stopping routing the message
 
@@ -139,7 +124,7 @@ Enterprise Integration Patterns
 `<script>` | Executes a script from a language which does not change the message body.
 
 | link:src/main/docs/eips/serviceCall-eip.adoc[Service Call] +
-`<serviceCall>` | Remote service call
+`<serviceCall>` | Remote service call definition
 
 | link:src/main/docs/eips/serviceCallConfiguration-eip.adoc[Service Call Configuration] +
 `<serviceCallConfiguration>` | Remote service call configuration

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/camel-core/src/main/java/org/apache/camel/CamelContext.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/CamelContext.java b/camel-core/src/main/java/org/apache/camel/CamelContext.java
index 72ad8a5..e37aa17 100644
--- a/camel-core/src/main/java/org/apache/camel/CamelContext.java
+++ b/camel-core/src/main/java/org/apache/camel/CamelContext.java
@@ -33,7 +33,7 @@ import org.apache.camel.model.DataFormatDefinition;
 import org.apache.camel.model.ProcessorDefinition;
 import org.apache.camel.model.RouteDefinition;
 import org.apache.camel.model.RoutesDefinition;
-import org.apache.camel.model.remote.ServiceCallConfigurationDefinition;
+import org.apache.camel.model.cloud.ServiceCallConfigurationDefinition;
 import org.apache.camel.model.rest.RestDefinition;
 import org.apache.camel.model.rest.RestsDefinition;
 import org.apache.camel.model.transformer.TransformerDefinition;
@@ -570,14 +570,13 @@ public interface CamelContext extends SuspendableService, RuntimeConfiguration {
     Collection<RestConfiguration> getRestConfigurations();
 
     /**
-     * Gets the service call configuration by the given name. If no name is given and there is only one configuration
-     * which matches the type then this configuration is returned.
+     * Gets the service call configuration by the given name. If no name is given
+     * the default configuration is returned, see <tt>setServiceCallConfiguration</tt>
      *
      * @param serviceName name of service, or <tt>null</tt> to return the default configuration
-     * @param type implementation of the configuration such as kubernetes, ribbon etc.
      * @return the configuration, or <tt>null</tt> if no configuration has been registered
      */
-    <T extends ServiceCallConfigurationDefinition> T getServiceCallConfiguration(String serviceName, Class<T> type);
+    ServiceCallConfigurationDefinition getServiceCallConfiguration(String serviceName);
 
     /**
      * Sets the default service call configuration
@@ -587,6 +586,13 @@ public interface CamelContext extends SuspendableService, RuntimeConfiguration {
     void setServiceCallConfiguration(ServiceCallConfigurationDefinition configuration);
 
     /**
+     * Sets the service call configurations
+     *
+     * @param configurations the configuration list
+     */
+    void setServiceCallConfigurations(List<ServiceCallConfigurationDefinition> configurations);
+
+    /**
      * Adds the service call configuration
      *
      * @param serviceName name of the service

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/camel-core/src/main/java/org/apache/camel/cloud/LoadBalancer.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/cloud/LoadBalancer.java b/camel-core/src/main/java/org/apache/camel/cloud/LoadBalancer.java
new file mode 100644
index 0000000..5974baf
--- /dev/null
+++ b/camel-core/src/main/java/org/apache/camel/cloud/LoadBalancer.java
@@ -0,0 +1,29 @@
+/**
+ * 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.cloud;
+
+/**
+ * Represents a Load Balancer.
+ *
+ * @see ServiceDiscovery
+ * @see ServiceFilter
+ * @see ServiceChooser
+ */
+@FunctionalInterface
+public interface LoadBalancer {
+    <T> T process(String serviceName, LoadBalancerFunction<T> function) throws Exception;
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/camel-core/src/main/java/org/apache/camel/cloud/LoadBalancerFactory.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/cloud/LoadBalancerFactory.java b/camel-core/src/main/java/org/apache/camel/cloud/LoadBalancerFactory.java
new file mode 100644
index 0000000..3af581f
--- /dev/null
+++ b/camel-core/src/main/java/org/apache/camel/cloud/LoadBalancerFactory.java
@@ -0,0 +1,31 @@
+/**
+ * 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.cloud;
+
+import org.apache.camel.CamelContext;
+
+/**
+ * A factory to create LoadBalancer
+ *
+ * @see LoadBalancer
+ */
+public interface LoadBalancerFactory {
+    /**
+     * Creates an instance of a LoadBalancer.
+     */
+    LoadBalancer newInstance(CamelContext camelContext) throws Exception;
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/camel-core/src/main/java/org/apache/camel/cloud/LoadBalancerFunction.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/cloud/LoadBalancerFunction.java b/camel-core/src/main/java/org/apache/camel/cloud/LoadBalancerFunction.java
new file mode 100644
index 0000000..b1a96d6
--- /dev/null
+++ b/camel-core/src/main/java/org/apache/camel/cloud/LoadBalancerFunction.java
@@ -0,0 +1,25 @@
+/**
+ * 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.cloud;
+
+/**
+ * Represents a load balancer function to be executed by the LoadBalancer.
+ */
+@FunctionalInterface
+public interface LoadBalancerFunction<T> {
+    T apply(ServiceDefinition serviceDefinition) throws Exception;
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/camel-core/src/main/java/org/apache/camel/cloud/ServiceChooser.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/cloud/ServiceChooser.java b/camel-core/src/main/java/org/apache/camel/cloud/ServiceChooser.java
new file mode 100644
index 0000000..7dc4eb3
--- /dev/null
+++ b/camel-core/src/main/java/org/apache/camel/cloud/ServiceChooser.java
@@ -0,0 +1,35 @@
+/**
+ * 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.cloud;
+
+import java.util.List;
+
+/**
+ * Allows SPIs to implement custom Service Chooser.
+ *
+ * @see ServiceDiscovery
+ */
+@FunctionalInterface
+public interface ServiceChooser {
+    /**
+     * Chooses one of the service to use
+     *
+     * @param services  list of services
+     * @return the chosen service to use.
+     */
+    ServiceDefinition choose(List<ServiceDefinition> services);
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/camel-core/src/main/java/org/apache/camel/cloud/ServiceChooserAware.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/cloud/ServiceChooserAware.java b/camel-core/src/main/java/org/apache/camel/cloud/ServiceChooserAware.java
new file mode 100644
index 0000000..a2386de
--- /dev/null
+++ b/camel-core/src/main/java/org/apache/camel/cloud/ServiceChooserAware.java
@@ -0,0 +1,37 @@
+/**
+ * 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.cloud;
+
+/**
+ * An interface to represent an object which wishes to be injected with
+ * a {@link ServiceChooser}
+ */
+public interface ServiceChooserAware {
+    /**
+     * Injects the {@link ServiceChooser}
+     *
+     * @param serviceChooser the ServiceChooser
+     */
+    void setServiceChooser(ServiceChooser serviceChooser);
+
+    /**
+     * Get the {@link ServiceChooser}
+     *
+     * @return the ServiceChooser
+     */
+    ServiceChooser getServiceChooser();
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/camel-core/src/main/java/org/apache/camel/cloud/ServiceChooserFactory.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/cloud/ServiceChooserFactory.java b/camel-core/src/main/java/org/apache/camel/cloud/ServiceChooserFactory.java
new file mode 100644
index 0000000..c3ab07f
--- /dev/null
+++ b/camel-core/src/main/java/org/apache/camel/cloud/ServiceChooserFactory.java
@@ -0,0 +1,31 @@
+/**
+ * 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.cloud;
+
+import org.apache.camel.CamelContext;
+
+/**
+ * A factory to create ServiceChooser
+ *
+ * @see ServiceChooser
+ */
+public interface ServiceChooserFactory {
+    /**
+     * Creates an instance of a ServiceChooser.
+     */
+    ServiceChooser newInstance(CamelContext camelContext) throws Exception;
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/camel-core/src/main/java/org/apache/camel/cloud/ServiceDefinition.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/cloud/ServiceDefinition.java b/camel-core/src/main/java/org/apache/camel/cloud/ServiceDefinition.java
new file mode 100644
index 0000000..f9dac27
--- /dev/null
+++ b/camel-core/src/main/java/org/apache/camel/cloud/ServiceDefinition.java
@@ -0,0 +1,52 @@
+/**
+ * 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.cloud;
+
+import java.util.Map;
+
+/**
+ * Represents a Service.
+ *
+ * @see ServiceChooser
+ * @see ServiceDiscovery
+ */
+public interface ServiceDefinition {
+    /**
+     * Gets the service name.
+     */
+    String getName();
+
+    /**
+     * Gets the IP or hostname of the server hosting the service.
+     */
+    String getHost();
+
+    /**
+     * Gets the port number of the server hosting the service.
+     */
+    int getPort();
+
+    /**
+     * Gets the health.
+     */
+    ServiceHealth getHealth();
+
+    /**
+     * Gets a key/value metadata associated with the service.
+     */
+    Map<String, String> getMetadata();
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/camel-core/src/main/java/org/apache/camel/cloud/ServiceDiscovery.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/cloud/ServiceDiscovery.java b/camel-core/src/main/java/org/apache/camel/cloud/ServiceDiscovery.java
new file mode 100644
index 0000000..28ff8af
--- /dev/null
+++ b/camel-core/src/main/java/org/apache/camel/cloud/ServiceDiscovery.java
@@ -0,0 +1,47 @@
+/**
+ * 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.cloud;
+
+import java.util.List;
+
+/**
+ * Allows SPIs to implement custom Service Discovery.
+ *
+ * @see ServiceChooser
+ * @see ServiceDefinition
+ */
+public interface ServiceDiscovery {
+    /**
+     * Gets the initial list of services.
+     * <p/>
+     * This method may return <tt>null</tt> or an empty list.
+     *
+     * @param name the service name
+     */
+    List<ServiceDefinition> getInitialListOfServices(String name);
+
+    /**
+     * Gets the updated list of services.
+     * <p/>
+     * This method can either be called on-demand prior to a service call, or have
+     * a background job that is scheduled to update the list, or a watcher
+     * that triggers when the list of services changes.
+     *
+     * @param name the service name
+     */
+    List<ServiceDefinition> getUpdatedListOfServices(String name);
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/camel-core/src/main/java/org/apache/camel/cloud/ServiceDiscoveryAware.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/cloud/ServiceDiscoveryAware.java b/camel-core/src/main/java/org/apache/camel/cloud/ServiceDiscoveryAware.java
new file mode 100644
index 0000000..c33971b
--- /dev/null
+++ b/camel-core/src/main/java/org/apache/camel/cloud/ServiceDiscoveryAware.java
@@ -0,0 +1,37 @@
+/**
+ * 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.cloud;
+
+/**
+ * An interface to represent an object which wishes to be injected with
+ * a {@link ServiceDiscovery}
+ */
+public interface ServiceDiscoveryAware {
+    /**
+     * Injects the {@link ServiceDiscovery}
+     *
+     * @param serviceDiscovery the ServiceDiscovery
+     */
+    void setServiceDiscovery(ServiceDiscovery serviceDiscovery);
+
+    /**
+     * Get the {@link ServiceDiscovery}
+     *
+     * @return the ServiceDiscovery
+     */
+    ServiceDiscovery getServiceDiscovery();
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/camel-core/src/main/java/org/apache/camel/cloud/ServiceDiscoveryFactory.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/cloud/ServiceDiscoveryFactory.java b/camel-core/src/main/java/org/apache/camel/cloud/ServiceDiscoveryFactory.java
new file mode 100644
index 0000000..44edfa9
--- /dev/null
+++ b/camel-core/src/main/java/org/apache/camel/cloud/ServiceDiscoveryFactory.java
@@ -0,0 +1,31 @@
+/**
+ * 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.cloud;
+
+import org.apache.camel.CamelContext;
+
+/**
+ * A factory to create ServiceDiscovery
+ *
+ * @see ServiceDiscovery
+ */
+public interface ServiceDiscoveryFactory {
+    /**
+     * Creates an instance of a ServiceDiscovery.
+     */
+    ServiceDiscovery newInstance(CamelContext camelContext) throws Exception;
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/camel-core/src/main/java/org/apache/camel/cloud/ServiceExpressionFactory.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/cloud/ServiceExpressionFactory.java b/camel-core/src/main/java/org/apache/camel/cloud/ServiceExpressionFactory.java
new file mode 100644
index 0000000..bcdbd52
--- /dev/null
+++ b/camel-core/src/main/java/org/apache/camel/cloud/ServiceExpressionFactory.java
@@ -0,0 +1,33 @@
+/**
+ * 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.cloud;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.Expression;
+
+/**
+ * A factory to create Expression
+ *
+ * @see Expression
+ */
+public interface ServiceExpressionFactory {
+    /**
+     * Creates an instance of a ServiceChooser.
+     */
+    Expression newInstance(CamelContext camelContext) throws Exception;
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/camel-core/src/main/java/org/apache/camel/cloud/ServiceFilter.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/cloud/ServiceFilter.java b/camel-core/src/main/java/org/apache/camel/cloud/ServiceFilter.java
new file mode 100644
index 0000000..a8d61b3
--- /dev/null
+++ b/camel-core/src/main/java/org/apache/camel/cloud/ServiceFilter.java
@@ -0,0 +1,35 @@
+/**
+ * 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.cloud;
+
+import java.util.List;
+
+/**
+ * Allows SPIs to implement custom Service Filter.
+ *
+ * @see ServiceDiscovery
+ */
+@FunctionalInterface
+public interface ServiceFilter {
+    /**
+     * Chooses one of the service to use
+     *
+     * @param services  list of services
+     * @return the chosen service to use.
+     */
+    <T extends ServiceDefinition> List<T> apply(List<T> services);
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/camel-core/src/main/java/org/apache/camel/cloud/ServiceFilterAware.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/cloud/ServiceFilterAware.java b/camel-core/src/main/java/org/apache/camel/cloud/ServiceFilterAware.java
new file mode 100644
index 0000000..ab0a21e
--- /dev/null
+++ b/camel-core/src/main/java/org/apache/camel/cloud/ServiceFilterAware.java
@@ -0,0 +1,37 @@
+/**
+ * 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.cloud;
+
+/**
+ * An interface to represent an object which wishes to be injected with
+ * a {@link ServiceFilter}
+ */
+public interface ServiceFilterAware {
+    /**
+     * Injects the {@link ServiceFilter}
+     *
+     * @param serviceFilter the ServiceFilter
+     */
+    void setServiceFilter(ServiceFilter serviceFilter);
+
+    /**
+     * Get the {@link ServiceFilter}
+     *
+     * @return the ServiceFilter
+     */
+    ServiceFilter getServiceFilter();
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/camel-core/src/main/java/org/apache/camel/cloud/ServiceFilterFactory.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/cloud/ServiceFilterFactory.java b/camel-core/src/main/java/org/apache/camel/cloud/ServiceFilterFactory.java
new file mode 100644
index 0000000..f098351
--- /dev/null
+++ b/camel-core/src/main/java/org/apache/camel/cloud/ServiceFilterFactory.java
@@ -0,0 +1,31 @@
+/**
+ * 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.cloud;
+
+import org.apache.camel.CamelContext;
+
+/**
+ * A factory to create ServiceFilter
+ *
+ * @see ServiceFilter
+ */
+public interface ServiceFilterFactory {
+    /**
+     * Creates an instance of a ServiceFilter.
+     */
+    ServiceFilter newInstance(CamelContext camelContext) throws Exception;
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/camel-core/src/main/java/org/apache/camel/cloud/ServiceHealth.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/cloud/ServiceHealth.java b/camel-core/src/main/java/org/apache/camel/cloud/ServiceHealth.java
new file mode 100644
index 0000000..56257c6
--- /dev/null
+++ b/camel-core/src/main/java/org/apache/camel/cloud/ServiceHealth.java
@@ -0,0 +1,32 @@
+/**
+ * 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.cloud;
+
+import java.util.Map;
+
+public interface ServiceHealth {
+
+    /**
+     * Gets a key/value metadata associated with the service.
+     */
+    Map<String, String> getMetadata();
+
+    /**
+     * States if the service is healthy or not
+     */
+    boolean isHealthy();
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/camel-core/src/main/java/org/apache/camel/impl/DefaultCamelContext.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/impl/DefaultCamelContext.java b/camel-core/src/main/java/org/apache/camel/impl/DefaultCamelContext.java
index 788dc14..dc41670 100644
--- a/camel-core/src/main/java/org/apache/camel/impl/DefaultCamelContext.java
+++ b/camel-core/src/main/java/org/apache/camel/impl/DefaultCamelContext.java
@@ -104,7 +104,7 @@ import org.apache.camel.model.ProcessorDefinitionHelper;
 import org.apache.camel.model.RouteDefinition;
 import org.apache.camel.model.RouteDefinitionHelper;
 import org.apache.camel.model.RoutesDefinition;
-import org.apache.camel.model.remote.ServiceCallConfigurationDefinition;
+import org.apache.camel.model.cloud.ServiceCallConfigurationDefinition;
 import org.apache.camel.model.rest.RestDefinition;
 import org.apache.camel.model.rest.RestsDefinition;
 import org.apache.camel.model.transformer.TransformerDefinition;
@@ -2598,33 +2598,30 @@ public class DefaultCamelContext extends ServiceSupport implements ModelCamelCon
         return config;
     }
 
-    @SuppressWarnings("unchecked")
-    public <T extends ServiceCallConfigurationDefinition> T getServiceCallConfiguration(String serviceName, Class<T> type) {
+    @Override
+    public ServiceCallConfigurationDefinition getServiceCallConfiguration(String serviceName) {
         if (serviceName == null) {
             serviceName = "";
         }
 
-        ServiceCallConfigurationDefinition config = serviceCallConfigurations.get(serviceName);
-        if (config == null) {
-            for (ServiceCallConfigurationDefinition candidate : serviceCallConfigurations.values()) {
-                if (type == null || type.isInstance(candidate)) {
-                    config = candidate;
-                    break;
-                }
-            }
-        }
-
-        if (config != null) {
-            return type != null ? type.cast(config) : (T) config;
-        } else {
-            return null;
-        }
+        return serviceCallConfigurations.get(serviceName);
     }
 
+    @Override
     public void setServiceCallConfiguration(ServiceCallConfigurationDefinition configuration) {
         serviceCallConfigurations.put("", configuration);
     }
 
+    @Override
+    public void setServiceCallConfigurations(List<ServiceCallConfigurationDefinition> configurations) {
+        if (configurations != null) {
+            for (ServiceCallConfigurationDefinition configuration : configurations) {
+                serviceCallConfigurations.put(configuration.getId(), configuration);
+            }
+        }
+    }
+
+    @Override
     public void addServiceCallConfiguration(String serviceName, ServiceCallConfigurationDefinition configuration) {
         serviceCallConfigurations.put(serviceName, configuration);
     }

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/camel-core/src/main/java/org/apache/camel/impl/cloud/AllServiceFilter.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/impl/cloud/AllServiceFilter.java b/camel-core/src/main/java/org/apache/camel/impl/cloud/AllServiceFilter.java
new file mode 100644
index 0000000..0635b33
--- /dev/null
+++ b/camel-core/src/main/java/org/apache/camel/impl/cloud/AllServiceFilter.java
@@ -0,0 +1,32 @@
+/**
+ * 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.impl.cloud;
+
+import java.util.List;
+
+import org.apache.camel.cloud.ServiceDefinition;
+import org.apache.camel.cloud.ServiceFilter;
+
+public class AllServiceFilter implements ServiceFilter {
+    public static final ServiceFilter INSTANCE = new AllServiceFilter();
+
+    @Override
+    public <T extends ServiceDefinition> List<T> apply(List<T> services) {
+        return services;
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/camel-core/src/main/java/org/apache/camel/impl/cloud/CachingServiceDiscovery.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/impl/cloud/CachingServiceDiscovery.java b/camel-core/src/main/java/org/apache/camel/impl/cloud/CachingServiceDiscovery.java
new file mode 100644
index 0000000..39394bb
--- /dev/null
+++ b/camel-core/src/main/java/org/apache/camel/impl/cloud/CachingServiceDiscovery.java
@@ -0,0 +1,104 @@
+/**
+ * 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.impl.cloud;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+
+import org.apache.camel.cloud.ServiceDefinition;
+import org.apache.camel.cloud.ServiceDiscovery;
+import org.apache.camel.util.ObjectHelper;
+
+public class CachingServiceDiscovery implements ServiceDiscovery {
+    private final ServiceDiscovery delegate;
+    private List<ServiceDefinition> services;
+    private long lastUpdate;
+    private long timeout;
+
+    public CachingServiceDiscovery(ServiceDiscovery delegate) {
+        this.delegate = ObjectHelper.notNull(delegate, "delegate");
+        this.lastUpdate = 0;
+        this.services = Collections.emptyList();
+        this.timeout = 60 * 1000; // 1 min;
+    }
+
+    public void setTimeout(long timeout) {
+        this.timeout = timeout;
+    }
+
+    public void setTimeout(long timeout, TimeUnit unit) {
+        this.timeout = unit.toMillis(timeout);
+    }
+
+    public long getTimeout() {
+        return timeout;
+    }
+
+    public CachingServiceDiscovery timeout(long timeout) {
+        setTimeout(timeout);
+        return this;
+    }
+
+    public CachingServiceDiscovery timeout(long timeout, TimeUnit unit) {
+        setTimeout(timeout, unit);
+        return this;
+    }
+
+    @Override
+    public List<ServiceDefinition> getInitialListOfServices(String name) {
+        return delegate.getInitialListOfServices(name);
+    }
+
+    @Override
+    public List<ServiceDefinition> getUpdatedListOfServices(String name) {
+        long now = System.currentTimeMillis();
+
+        if (lastUpdate == 0 || now > lastUpdate + timeout) {
+            List<ServiceDefinition> updatedList = delegate.getUpdatedListOfServices(name);
+            if (updatedList.isEmpty()) {
+                services = Collections.emptyList();
+            } else {
+                // List is copied as the delegated ServiceCallServiceDiscovery
+                // may update the list
+                services = Collections.unmodifiableList(new ArrayList<>(updatedList));
+            }
+
+            lastUpdate = now;
+        }
+
+        return services;
+    }
+
+    // **********************
+    // Helpers
+    // **********************
+
+    public static CachingServiceDiscovery wrap(ServiceDiscovery delegate) {
+        return new CachingServiceDiscovery(delegate);
+    }
+
+    public static CachingServiceDiscovery wrap(ServiceDiscovery delegate, long timeout) {
+        return new CachingServiceDiscovery(delegate).timeout(timeout);
+    }
+
+    public static CachingServiceDiscovery wrap(ServiceDiscovery delegate, long timeout, TimeUnit unit) {
+        return new CachingServiceDiscovery(delegate).timeout(timeout, unit);
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/camel-core/src/main/java/org/apache/camel/impl/cloud/DefaultLoadBalancer.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/impl/cloud/DefaultLoadBalancer.java b/camel-core/src/main/java/org/apache/camel/impl/cloud/DefaultLoadBalancer.java
new file mode 100644
index 0000000..2e45ce2
--- /dev/null
+++ b/camel-core/src/main/java/org/apache/camel/impl/cloud/DefaultLoadBalancer.java
@@ -0,0 +1,148 @@
+/**
+ * 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.impl.cloud;
+
+import java.util.List;
+import java.util.concurrent.RejectedExecutionException;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.CamelContextAware;
+import org.apache.camel.cloud.LoadBalancer;
+import org.apache.camel.cloud.LoadBalancerFunction;
+import org.apache.camel.cloud.ServiceChooser;
+import org.apache.camel.cloud.ServiceChooserAware;
+import org.apache.camel.cloud.ServiceDefinition;
+import org.apache.camel.cloud.ServiceDiscovery;
+import org.apache.camel.cloud.ServiceDiscoveryAware;
+import org.apache.camel.cloud.ServiceFilter;
+import org.apache.camel.cloud.ServiceFilterAware;
+import org.apache.camel.support.ServiceSupport;
+import org.apache.camel.util.ObjectHelper;
+import org.apache.camel.util.ServiceHelper;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class DefaultLoadBalancer
+        extends ServiceSupport
+        implements CamelContextAware, ServiceDiscoveryAware, ServiceChooserAware, ServiceFilterAware, LoadBalancer {
+
+    private static final Logger LOGGER = LoggerFactory.getLogger(DefaultLoadBalancer.class);
+
+    private CamelContext camelContext;
+    private ServiceDiscovery serviceDiscovery;
+    private ServiceChooser serviceChooser;
+    private ServiceFilter serviceFilter;
+
+    public DefaultLoadBalancer() {
+    }
+
+    // *************************************
+    // Bean
+    // *************************************
+
+    @Override
+    public CamelContext getCamelContext() {
+        return camelContext;
+    }
+
+    @Override
+    public void setCamelContext(CamelContext camelContext) {
+        this.camelContext = camelContext;
+    }
+
+    @Override
+    public ServiceDiscovery getServiceDiscovery() {
+        return serviceDiscovery;
+    }
+
+    @Override
+    public void setServiceDiscovery(ServiceDiscovery serverDiscovery) {
+        this.serviceDiscovery = serverDiscovery;
+    }
+
+    @Override
+    public ServiceChooser getServiceChooser() {
+        return serviceChooser;
+    }
+
+    @Override
+    public void setServiceChooser(ServiceChooser serverChooser) {
+        this.serviceChooser = serverChooser;
+    }
+
+    @Override
+    public void setServiceFilter(ServiceFilter serviceFilter) {
+        this.serviceFilter = serviceFilter;
+    }
+
+    @Override
+    public ServiceFilter getServiceFilter() {
+        return serviceFilter;
+    }
+
+    // *************************************
+    // Lifecycle
+    // *************************************
+
+    @Override
+    protected void doStart() throws Exception {
+        ObjectHelper.notNull(camelContext, "camel context");
+        ObjectHelper.notNull(serviceDiscovery, "service discovery");
+        ObjectHelper.notNull(serviceChooser, "service chooser");
+        ObjectHelper.notNull(serviceFilter, "service serviceFilter");
+
+        LOGGER.info("ServiceCall is using default load balancer with service discovery type: {}, service filter type: {} and service chooser type: {}",
+            serviceDiscovery.getClass(),
+            serviceFilter.getClass(),
+            serviceChooser.getClass());
+
+        ServiceHelper.startService(serviceChooser);
+        ServiceHelper.startService(serviceDiscovery);
+    }
+
+    @Override
+    protected void doStop() throws Exception {
+        // Stop services if needed
+        ServiceHelper.stopService(serviceDiscovery);
+        ServiceHelper.stopService(serviceChooser);
+    }
+
+    // *************************************
+    // Load Balancer
+    // *************************************
+
+    @Override
+    public <T> T process(String serviceName, LoadBalancerFunction<T> function) throws Exception {
+        ServiceDefinition service;
+
+        List<ServiceDefinition> services = serviceDiscovery.getUpdatedListOfServices(serviceName);
+        if (services == null || services.isEmpty()) {
+            throw new RejectedExecutionException("No active services with name " + serviceName);
+        } else {
+            // filter services
+            services = serviceFilter.apply(services);
+            // let the client service chooser find which server to use
+            service = services.size() > 1 ? serviceChooser.choose(services) : services.get(0);
+            if (service == null) {
+                throw new RejectedExecutionException("No active services with name " + serviceName);
+            }
+        }
+
+        return function.apply(service);
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/camel-core/src/main/java/org/apache/camel/impl/cloud/DefaultServiceCallExpression.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/impl/cloud/DefaultServiceCallExpression.java b/camel-core/src/main/java/org/apache/camel/impl/cloud/DefaultServiceCallExpression.java
new file mode 100644
index 0000000..b642912
--- /dev/null
+++ b/camel-core/src/main/java/org/apache/camel/impl/cloud/DefaultServiceCallExpression.java
@@ -0,0 +1,85 @@
+/**
+ * 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.impl.cloud;
+
+import org.apache.camel.model.cloud.ServiceCallDefinition;
+import org.apache.camel.support.ServiceCallExpressionSupport;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Support class for custom implementations of {@link ServiceCallDefinition ServiceCall EIP} components.
+ * <p/>
+ * Below are some examples how to call a service and what Camel endpoint URI is constructed based on the input:
+ * <pre>
+ serviceCall("myService") -> http://hostname:port
+ serviceCall("myService/foo") -> http://hostname:port/foo
+ serviceCall("http:myService/foo") -> http:hostname:port/foo
+ serviceCall("myService", "http:myService.host:myService.port/foo") -> http:hostname:port/foo
+ serviceCall("myService", "netty4:tcp:myService?connectTimeout=1000") -> netty:tcp:hostname:port?connectTimeout=1000
+ * </pre>
+ */
+public class DefaultServiceCallExpression extends ServiceCallExpressionSupport {
+    private static final Logger LOGGER = LoggerFactory.getLogger(DefaultServiceCallExpression.class);
+
+    @Override
+    protected String buildCamelEndpointUri(String name, String host, Integer port, String uri, String contextPath, String scheme) {
+        // build basic uri if none provided
+        String answer = uri;
+        if (answer == null) {
+            if (scheme == null) {
+                // use http/https by default if no scheme or port have been configured
+                if (port == null) {
+                    scheme = "http";
+                } else if (port == 443) {
+                    scheme = "https";
+                } else {
+                    scheme = "http";
+                }
+            }
+            answer = scheme + "://" + host;
+            if (port != null) {
+                answer = answer + ":" + port;
+            }
+            if (contextPath != null) {
+                if (!contextPath.startsWith("/")) {
+                    contextPath = "/" + contextPath;
+                }
+
+                answer += contextPath;
+            }
+        } else {
+            // we have existing uri, then replace the serviceName with ip:port
+            if (answer.contains(name + ".host")) {
+                answer = answer.replaceFirst(name + "\\.host", host);
+            }
+            if (answer.contains(name + ".port") && port != null) {
+                answer = answer.replaceFirst(name + "\\.port", "" + port);
+            }
+            if (answer.contains(name) && port != null) {
+                answer = answer.replaceFirst(name, host + ":" + port);
+            }
+            if (answer.contains(name) && port == null) {
+                answer = answer.replaceFirst(name, host);
+            }
+        }
+
+        LOGGER.debug("Camel endpoint uri: {} for calling service: {} on server {}:{}", answer, name, host, port);
+        return answer;
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/camel-core/src/main/java/org/apache/camel/impl/cloud/DefaultServiceCallProcessor.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/impl/cloud/DefaultServiceCallProcessor.java b/camel-core/src/main/java/org/apache/camel/impl/cloud/DefaultServiceCallProcessor.java
new file mode 100644
index 0000000..edf1f6a
--- /dev/null
+++ b/camel-core/src/main/java/org/apache/camel/impl/cloud/DefaultServiceCallProcessor.java
@@ -0,0 +1,153 @@
+/**
+ * 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.impl.cloud;
+
+import org.apache.camel.AsyncCallback;
+import org.apache.camel.AsyncProcessor;
+import org.apache.camel.CamelContext;
+import org.apache.camel.Exchange;
+import org.apache.camel.ExchangePattern;
+import org.apache.camel.Expression;
+import org.apache.camel.Message;
+import org.apache.camel.cloud.LoadBalancer;
+import org.apache.camel.cloud.ServiceDefinition;
+import org.apache.camel.processor.SendDynamicProcessor;
+import org.apache.camel.support.ServiceSupport;
+import org.apache.camel.util.AsyncProcessorHelper;
+import org.apache.camel.util.ObjectHelper;
+import org.apache.camel.util.ServiceHelper;
+import org.apache.camel.util.StringHelper;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class DefaultServiceCallProcessor extends ServiceSupport implements AsyncProcessor {
+    private static final Logger LOGGER = LoggerFactory.getLogger(DefaultServiceCallProcessor.class);
+
+    private final ExchangePattern exchangePattern;
+    private final String name;
+    private final String scheme;
+    private final String uri;
+    private final String contextPath;
+    private final CamelContext camelContext;
+    private final LoadBalancer loadBalancer;
+    private final Expression expression;
+    private SendDynamicProcessor processor;
+
+    public DefaultServiceCallProcessor(
+        CamelContext camelContext, String name, String scheme, String uri, ExchangePattern exchangePattern,
+        LoadBalancer loadBalancer, Expression expression) {
+
+        this.uri = uri;
+        this.exchangePattern = exchangePattern;
+        this.camelContext = camelContext;
+        this.loadBalancer = loadBalancer;
+
+        // setup from the provided name which can contain scheme and context-path information as well
+        String serviceName;
+        if (name.contains("/")) {
+            serviceName = StringHelper.before(name, "/");
+            this.contextPath = StringHelper.after(name, "/");
+        } else if (name.contains("?")) {
+            serviceName = StringHelper.before(name, "?");
+            this.contextPath = StringHelper.after(name, "?");
+        } else {
+            serviceName = name;
+            this.contextPath = null;
+        }
+        if (serviceName.contains(":")) {
+            this.scheme = StringHelper.before(serviceName, ":");
+            this.name = StringHelper.after(serviceName, ":");
+        } else {
+            this.scheme = scheme;
+            this.name = serviceName;
+        }
+
+        this.expression = expression;
+    }
+
+    // *************************************
+    // Lifecycle
+    // *************************************
+
+    @Override
+    protected void doStart() throws Exception {
+        StringHelper.notEmpty(name, "name", "service name");
+        ObjectHelper.notNull(camelContext, "camel context");
+        ObjectHelper.notNull(expression, "expression");
+        ObjectHelper.notNull(loadBalancer, "load balancer");
+
+        processor = new SendDynamicProcessor(uri, expression);
+        processor.setCamelContext(camelContext);
+        if (exchangePattern != null) {
+            processor.setPattern(exchangePattern);
+        }
+
+        // Start services if needed
+        ServiceHelper.startService(processor);
+        ServiceHelper.startService(loadBalancer);
+    }
+
+    @Override
+    protected void doStop() throws Exception {
+        // Stop services if needed
+        ServiceHelper.stopService(loadBalancer);
+        ServiceHelper.stopService(processor);
+    }
+
+    // *************************************
+    // Processor
+    // *************************************
+
+    @Override
+    public void process(Exchange exchange) throws Exception {
+        AsyncProcessorHelper.process(this, exchange);
+    }
+
+    @Override
+    public boolean process(final Exchange exchange, final AsyncCallback callback) {
+        Message message = exchange.getIn();
+        message.setHeader(ServiceCallConstants.SERVICE_CALL_URI, uri);
+        message.setHeader(ServiceCallConstants.SERVICE_CALL_CONTEXT_PATH, contextPath);
+        message.setHeader(ServiceCallConstants.SERVICE_CALL_SCHEME, scheme);
+
+        String serviceName = message.getHeader(ServiceCallConstants.SERVICE_NAME, name, String.class);
+
+        try {
+            return loadBalancer.process(serviceName, server -> execute(server, exchange, callback));
+        } catch (Exception e) {
+            exchange.setException(e);
+            return true;
+        }
+    }
+
+    private boolean execute(ServiceDefinition server, Exchange exchange, AsyncCallback callback) throws Exception {
+        String host = server.getHost();
+        int port = server.getPort();
+
+        LOGGER.debug("Service {} active at server: {}:{}", name, host, port);
+
+        // set selected server as header
+        exchange.getIn().setHeader(ServiceCallConstants.SERVICE_HOST, host);
+        exchange.getIn().setHeader(ServiceCallConstants.SERVICE_PORT, port > 0 ? port : null);
+        exchange.getIn().setHeader(ServiceCallConstants.SERVICE_NAME, server.getName());
+        exchange.getIn().setHeader(ServiceCallConstants.SERVICE_META, server.getMetadata());
+
+        // use the dynamic send processor to call the service
+        return processor.process(exchange, callback);
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/camel-core/src/main/java/org/apache/camel/impl/cloud/DefaultServiceDefinition.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/impl/cloud/DefaultServiceDefinition.java b/camel-core/src/main/java/org/apache/camel/impl/cloud/DefaultServiceDefinition.java
new file mode 100644
index 0000000..d510847
--- /dev/null
+++ b/camel-core/src/main/java/org/apache/camel/impl/cloud/DefaultServiceDefinition.java
@@ -0,0 +1,98 @@
+/**
+ * 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.impl.cloud;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.camel.cloud.ServiceDefinition;
+import org.apache.camel.cloud.ServiceHealth;
+
+public class DefaultServiceDefinition implements ServiceDefinition {
+
+    private final String name;
+    private final String host;
+    private final int port;
+    private final Map<String, String> meta;
+    private final ServiceHealth health;
+
+    public DefaultServiceDefinition(String name, String host, int port) {
+        this.name = name;
+        this.host = host;
+        this.port = port;
+        this.meta = Collections.emptyMap();
+        this.health = DefaultServiceHealth.INSTANCE;
+    }
+
+    public DefaultServiceDefinition(String name, String host, int port, ServiceHealth health) {
+        this.name = name;
+        this.host = host;
+        this.port = port;
+        this.meta = Collections.emptyMap();
+        this.health = health;
+    }
+
+    public DefaultServiceDefinition(String name, String host, int port, Map<String, String> meta) {
+        this.name = name;
+        this.host = host;
+        this.port = port;
+        this.meta = meta != null ? Collections.unmodifiableMap(new HashMap<>(meta)) : Collections.emptyMap();
+        this.health = DefaultServiceHealth.INSTANCE;
+    }
+
+    public DefaultServiceDefinition(String name, String host, int port, Map<String, String> meta, ServiceHealth health) {
+        this.name = name;
+        this.host = host;
+        this.port = port;
+        this.meta = meta != null ? Collections.unmodifiableMap(new HashMap<>(meta)) : Collections.emptyMap();
+        this.health = health;
+    }
+
+    @Override
+    public String getName() {
+        return name;
+    }
+
+    @Override
+    public String getHost() {
+        return host;
+    }
+
+    @Override
+    public int getPort() {
+        return port;
+    }
+
+    @Override
+    public ServiceHealth getHealth() {
+        return health;
+    }
+
+    @Override
+    public Map<String, String> getMetadata() {
+        return this.meta;
+    }
+
+    @Override
+    public String toString() {
+        return "DefaultServiceCallService[" + name + "@" + host + ":" + port + "]";
+    }
+
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/camel-core/src/main/java/org/apache/camel/impl/cloud/DefaultServiceDiscovery.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/impl/cloud/DefaultServiceDiscovery.java b/camel-core/src/main/java/org/apache/camel/impl/cloud/DefaultServiceDiscovery.java
new file mode 100644
index 0000000..cf4fb1b
--- /dev/null
+++ b/camel-core/src/main/java/org/apache/camel/impl/cloud/DefaultServiceDiscovery.java
@@ -0,0 +1,64 @@
+/**
+ * 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.impl.cloud;
+
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.CamelContextAware;
+import org.apache.camel.cloud.ServiceDefinition;
+import org.apache.camel.cloud.ServiceDiscovery;
+import org.apache.camel.support.ServiceSupport;
+
+
+public class DefaultServiceDiscovery
+    extends ServiceSupport implements ServiceDiscovery, CamelContextAware {
+
+    private CamelContext camelContext;
+
+    @Override
+    public List<ServiceDefinition> getInitialListOfServices(String name) {
+        return getUpdatedListOfServices(name);
+    }
+
+    @Override
+    public List<ServiceDefinition> getUpdatedListOfServices(String name) {
+        return Collections.emptyList();
+    }
+
+    @Override
+    public void setCamelContext(CamelContext camelContext) {
+        this.camelContext = camelContext;
+    }
+
+    @Override
+    public CamelContext getCamelContext() {
+        return camelContext;
+    }
+
+    @Override
+    protected void doStart() throws Exception {
+        // nop
+    }
+
+    @Override
+    protected void doStop() throws Exception {
+        // nop
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/camel-core/src/main/java/org/apache/camel/impl/cloud/DefaultServiceFilter.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/impl/cloud/DefaultServiceFilter.java b/camel-core/src/main/java/org/apache/camel/impl/cloud/DefaultServiceFilter.java
new file mode 100644
index 0000000..2b58032
--- /dev/null
+++ b/camel-core/src/main/java/org/apache/camel/impl/cloud/DefaultServiceFilter.java
@@ -0,0 +1,30 @@
+/**
+ * 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.impl.cloud;
+
+import java.util.List;
+
+import org.apache.camel.cloud.ServiceDefinition;
+import org.apache.camel.cloud.ServiceFilter;
+
+public class DefaultServiceFilter implements ServiceFilter {
+    @Override
+    public <T extends ServiceDefinition> List<T> apply(List<T> services) {
+        return services;
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/camel-core/src/main/java/org/apache/camel/impl/cloud/DefaultServiceHealth.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/impl/cloud/DefaultServiceHealth.java b/camel-core/src/main/java/org/apache/camel/impl/cloud/DefaultServiceHealth.java
new file mode 100644
index 0000000..f83b5ec
--- /dev/null
+++ b/camel-core/src/main/java/org/apache/camel/impl/cloud/DefaultServiceHealth.java
@@ -0,0 +1,57 @@
+/**
+ * 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.impl.cloud;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.camel.cloud.ServiceHealth;
+
+public class DefaultServiceHealth implements ServiceHealth {
+    public static final ServiceHealth INSTANCE = new DefaultServiceHealth();
+
+    private final boolean healthy;
+    private final Map<String, String> meta;
+
+    public DefaultServiceHealth() {
+        this(true, null);
+    }
+    public DefaultServiceHealth(boolean healthy) {
+        this(healthy, null);
+    }
+
+    public DefaultServiceHealth(Map<String, String> meta) {
+        this(true, meta);
+    }
+
+    public DefaultServiceHealth(boolean healthy, Map<String, String> meta) {
+        this.healthy = healthy;
+        this.meta = meta != null ? Collections.unmodifiableMap(new HashMap<>(meta)) : Collections.emptyMap();
+    }
+
+    @Override
+    public boolean isHealthy() {
+        return this.healthy;
+    }
+
+    @Override
+    public Map<String, String> getMetadata() {
+        return this.meta;
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/camel-core/src/main/java/org/apache/camel/impl/cloud/HealthyServiceFilter.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/impl/cloud/HealthyServiceFilter.java b/camel-core/src/main/java/org/apache/camel/impl/cloud/HealthyServiceFilter.java
new file mode 100644
index 0000000..deb55ae
--- /dev/null
+++ b/camel-core/src/main/java/org/apache/camel/impl/cloud/HealthyServiceFilter.java
@@ -0,0 +1,33 @@
+/**
+ * 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.impl.cloud;
+
+import java.util.List;
+import java.util.stream.Collectors;
+
+import org.apache.camel.cloud.ServiceDefinition;
+import org.apache.camel.cloud.ServiceFilter;
+
+public class HealthyServiceFilter implements ServiceFilter {
+    public static final ServiceFilter INSTANCE = new HealthyServiceFilter();
+
+    @Override
+    public <T extends ServiceDefinition> List<T> apply(List<T> services) {
+        return services.stream().filter(s -> s.getHealth().isHealthy()).collect(Collectors.toList());
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/camel-core/src/main/java/org/apache/camel/impl/cloud/RandomServiceChooser.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/impl/cloud/RandomServiceChooser.java b/camel-core/src/main/java/org/apache/camel/impl/cloud/RandomServiceChooser.java
new file mode 100644
index 0000000..00c4af1
--- /dev/null
+++ b/camel-core/src/main/java/org/apache/camel/impl/cloud/RandomServiceChooser.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.impl.cloud;
+
+import java.util.List;
+import java.util.Random;
+
+import org.apache.camel.cloud.ServiceChooser;
+import org.apache.camel.cloud.ServiceDefinition;
+
+public class RandomServiceChooser implements ServiceChooser {
+    private final Random random;
+
+    public RandomServiceChooser() {
+        this.random = new Random();
+    }
+
+    @Override
+    public ServiceDefinition choose(List<ServiceDefinition> servers) {
+        int size = servers.size();
+        int index = (size > 1) ? random.nextInt(size) : 0;
+
+        return servers.get(index);
+    }
+
+    @Override
+    public String toString() {
+        return "RandomServiceCallServiceChooser";
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/camel-core/src/main/java/org/apache/camel/impl/cloud/RoundRobinServiceChooser.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/impl/cloud/RoundRobinServiceChooser.java b/camel-core/src/main/java/org/apache/camel/impl/cloud/RoundRobinServiceChooser.java
new file mode 100644
index 0000000..79d6e39
--- /dev/null
+++ b/camel-core/src/main/java/org/apache/camel/impl/cloud/RoundRobinServiceChooser.java
@@ -0,0 +1,41 @@
+/**
+ * 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.impl.cloud;
+
+import java.util.List;
+
+import org.apache.camel.cloud.ServiceChooser;
+import org.apache.camel.cloud.ServiceDefinition;
+
+public class RoundRobinServiceChooser implements ServiceChooser {
+    private int counter = -1;
+
+    @Override
+    public ServiceDefinition choose(List<ServiceDefinition> servers) {
+        int size = servers.size();
+        if (size == 1 || ++counter >= size) {
+            counter = 0;
+        }
+        return servers.get(counter);
+    }
+
+    @Override
+    public String toString() {
+        return "RoundRobinServiceCallServiceChooser";
+    }
+}


[04/10] camel git commit: CAMEL-10638: Refactor ServiceCall EIP

Posted by lb...@apache.org.
http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/components/camel-etcd/src/test/java/org/apache/camel/component/etcd/cloud/SpringEtcdServiceCallRouteTest.java
----------------------------------------------------------------------
diff --git a/components/camel-etcd/src/test/java/org/apache/camel/component/etcd/cloud/SpringEtcdServiceCallRouteTest.java b/components/camel-etcd/src/test/java/org/apache/camel/component/etcd/cloud/SpringEtcdServiceCallRouteTest.java
new file mode 100644
index 0000000..2b959ea
--- /dev/null
+++ b/components/camel-etcd/src/test/java/org/apache/camel/component/etcd/cloud/SpringEtcdServiceCallRouteTest.java
@@ -0,0 +1,96 @@
+/**
+ * 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.cloud;
+
+import java.net.URI;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import mousio.etcd4j.EtcdClient;
+import org.apache.camel.component.etcd.EtcdHelper;
+import org.apache.camel.test.spring.CamelSpringTestSupport;
+import org.junit.Test;
+import org.springframework.context.support.AbstractApplicationContext;
+import org.springframework.context.support.ClassPathXmlApplicationContext;
+
+public class SpringEtcdServiceCallRouteTest extends CamelSpringTestSupport {
+    private static final ObjectMapper MAPPER = EtcdHelper.createObjectMapper();
+    private static final EtcdClient CLIENT = new EtcdClient(URI.create("http://localhost:2379"));
+
+    @Override
+    protected AbstractApplicationContext createApplicationContext() {
+        return new ClassPathXmlApplicationContext("org/apache/camel/component/etcd/cloud/SpringEtcdServiceCallRouteTest.xml");
+    }
+
+    // *************************************************************************
+    // Setup / tear down
+    // *************************************************************************
+
+    @Override
+    public void doPreSetup() throws Exception {
+        JsonNode service1 = MAPPER.createObjectNode()
+            .put("name", "http-service")
+            .put("address", "127.0.0.1")
+            .put("port", "9091");
+        JsonNode service2 = MAPPER.createObjectNode()
+            .put("name", "http-service")
+            .put("address", "127.0.0.1")
+            .put("port", "9092");
+        JsonNode service3 = MAPPER.createObjectNode()
+            .put("name", "http-service")
+            .put("address", "127.0.0.1")
+            .put("port", "9093");
+        JsonNode service4 = MAPPER.createObjectNode()
+            .put("name", "http-service")
+            .put("address", "127.0.0.1")
+            .put("port", "9094");
+
+        CLIENT.put("/etcd-services-1/" + "service-1", MAPPER.writeValueAsString(service1)).send().get();
+        CLIENT.put("/etcd-services-1/" + "service-2", MAPPER.writeValueAsString(service2)).send().get();
+        CLIENT.put("/etcd-services-2/" + "service-3", MAPPER.writeValueAsString(service3)).send().get();
+        CLIENT.put("/etcd-services-2/" + "service-4", MAPPER.writeValueAsString(service4)).send().get();
+
+        super.doPreSetup();
+    }
+
+    @Override
+    public void tearDown() throws Exception {
+        super.tearDown();
+        CLIENT.deleteDir("/etcd-services-1/").recursive().send().get();
+        CLIENT.deleteDir("/etcd-services-2/").recursive().send().get();
+    }
+
+    // *************************************************************************
+    // Test
+    // *************************************************************************
+
+    @Test
+    public void testServiceCall() throws Exception {
+        getMockEndpoint("mock:result-1").expectedMessageCount(2);
+        getMockEndpoint("mock:result-1").expectedBodiesReceivedInAnyOrder("service-1 9091", "service-1 9092");
+        getMockEndpoint("mock:result-2").expectedMessageCount(2);
+        getMockEndpoint("mock:result-2").expectedBodiesReceivedInAnyOrder("service-2 9093", "service-2 9094");
+
+        template.sendBody("direct:start", "service-1");
+        template.sendBody("direct:start", "service-1");
+        template.sendBody("direct:start", "service-2");
+        template.sendBody("direct:start", "service-2");
+
+        assertMockEndpointsSatisfied();
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/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
deleted file mode 100644
index 7987ec4..0000000
--- a/components/camel-etcd/src/test/java/org/apache/camel/component/etcd/processor/remote/EtcdServiceCallRouteTest.java
+++ /dev/null
@@ -1,117 +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;
-
-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("An etcd server is needed for this test ")
-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/a811f400/components/camel-etcd/src/test/java/org/apache/camel/component/etcd/processor/remote/EtcdServiceCallServerListStrategyTest.java
----------------------------------------------------------------------
diff --git a/components/camel-etcd/src/test/java/org/apache/camel/component/etcd/processor/remote/EtcdServiceCallServerListStrategyTest.java b/components/camel-etcd/src/test/java/org/apache/camel/component/etcd/processor/remote/EtcdServiceCallServerListStrategyTest.java
deleted file mode 100644
index 837f057..0000000
--- a/components/camel-etcd/src/test/java/org/apache/camel/component/etcd/processor/remote/EtcdServiceCallServerListStrategyTest.java
+++ /dev/null
@@ -1,128 +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;
-
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.atomic.AtomicInteger;
-
-import com.fasterxml.jackson.databind.ObjectMapper;
-import mousio.etcd4j.EtcdClient;
-import mousio.etcd4j.responses.EtcdException;
-import org.apache.camel.component.etcd.EtcdConfiguration;
-import org.apache.camel.component.etcd.EtcdHelper;
-import org.apache.camel.component.etcd.EtcdTestSupport;
-import org.junit.Ignore;
-import org.junit.Test;
-
-@Ignore("An etcd server is needed for this test ")
-public class EtcdServiceCallServerListStrategyTest extends EtcdTestSupport {
-    private static final ObjectMapper MAPPER = EtcdHelper.createObjectMapper();
-    private static final EtcdConfiguration CONFIGURATION = new EtcdConfiguration(null);
-    private static final AtomicInteger PORT = new AtomicInteger(0);
-
-    private EtcdClient client;
-
-    @Override
-    public void doPreSetup() throws Exception {
-        client = getClient();
-        try {
-            client.deleteDir(CONFIGURATION.getServicePath()).recursive().send().get();
-        } catch (EtcdException e) {
-            // Ignore
-        }
-    }
-
-    @Override
-    public void tearDown() throws Exception {
-        try {
-            client.deleteDir(CONFIGURATION.getServicePath()).recursive().send().get();
-            client.close();
-            client = null;
-        } catch (EtcdException e) {
-            // Ignore
-        }
-    }
-
-    @Test
-    public void testOnDemandStrategy() throws Exception {
-        for (int i = 0; i < 3; i++) {
-            addServer(client, "serviceType-1");
-        }
-        for (int i = 0; i < 2; i++) {
-            addServer(client, "serviceType-2");
-        }
-
-        EtcdServiceCallServerListStrategy strategy = EtcdServiceCallServerListStrategies.onDemand(CONFIGURATION);
-        strategy.start();
-
-        List<EtcdServiceCallServer> type1 = strategy.getUpdatedListOfServers("serviceType-1");
-        assertEquals(3, type1.size());
-        for (EtcdServiceCallServer server : type1) {
-            assertNotNull(server.getMetadata());
-            assertTrue(server.getMetadata().containsKey("service_name"));
-            assertTrue(server.getMetadata().containsKey("port_delta"));
-        }
-
-        List<EtcdServiceCallServer> type2 = strategy.getUpdatedListOfServers("serviceType-2");
-        assertEquals(2, type2.size());
-        for (EtcdServiceCallServer server : type2) {
-            assertNotNull(server.getMetadata());
-            assertTrue(server.getMetadata().containsKey("service_name"));
-            assertTrue(server.getMetadata().containsKey("port_delta"));
-        }
-
-        strategy.stop();
-    }
-
-    @Test
-    public void testWatchStrategy() throws Exception {
-        addServer(client, "serviceType-3");
-
-        EtcdServiceCallServerListStrategy strategy = EtcdServiceCallServerListStrategies.watch(CONFIGURATION);
-        strategy.start();
-
-        assertEquals(1, strategy.getUpdatedListOfServers("serviceType-3").size());
-
-        addServer(client, "serviceType-3");
-        addServer(client, "serviceType-3");
-        addServer(client, "serviceType-4");
-
-        Thread.sleep(250);
-
-        assertEquals(3, strategy.getUpdatedListOfServers("serviceType-3").size());
-
-        strategy.stop();
-    }
-
-    private void addServer(EtcdClient client, String name) throws Exception {
-        int port = PORT.incrementAndGet();
-
-        Map<String, String> tags = new HashMap<>();
-        tags.put("service_name", name);
-        tags.put("port_delta", Integer.toString(port));
-
-        Map<String, Object> server = new HashMap<>();
-        server.put("name", name);
-        server.put("address", "127.0.0.1");
-        server.put("port", 8000 + port);
-        server.put("tags", tags);
-
-        client.put(CONFIGURATION.getServicePath() + "service-" + port, MAPPER.writeValueAsString(server)).send().get();
-    }
-}

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/components/camel-etcd/src/test/resources/org/apache/camel/component/etcd/cloud/SpringEtcdServiceCallDefaultRouteTest.xml
----------------------------------------------------------------------
diff --git a/components/camel-etcd/src/test/resources/org/apache/camel/component/etcd/cloud/SpringEtcdServiceCallDefaultRouteTest.xml b/components/camel-etcd/src/test/resources/org/apache/camel/component/etcd/cloud/SpringEtcdServiceCallDefaultRouteTest.xml
new file mode 100644
index 0000000..d0194c8
--- /dev/null
+++ b/components/camel-etcd/src/test/resources/org/apache/camel/component/etcd/cloud/SpringEtcdServiceCallDefaultRouteTest.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ 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.
+  -->
+<beans xmlns="http://www.springframework.org/schema/beans"
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xsi:schemaLocation="
+         http://www.springframework.org/schema/beans
+         http://www.springframework.org/schema/beans/spring-beans.xsd
+         http://camel.apache.org/schema/spring
+         http://camel.apache.org/schema/spring/camel-spring.xsd">
+
+  <camelContext xmlns="http://camel.apache.org/schema/spring">
+    <route>
+      <from uri="direct:start"/>
+      <serviceCall name="http-service"/>
+      <to uri="mock:result"/>
+    </route>
+
+    <route>
+      <from uri="jetty:http://localhost:9091"/>
+      <transform>
+        <constant>9091</constant>
+      </transform>
+    </route>
+
+    <route>
+      <from uri="jetty:http://localhost:9092"/>
+      <transform>
+        <constant>9092</constant>
+      </transform>
+    </route>
+  </camelContext>
+
+</beans>

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/components/camel-etcd/src/test/resources/org/apache/camel/component/etcd/cloud/SpringEtcdServiceCallRouteTest.xml
----------------------------------------------------------------------
diff --git a/components/camel-etcd/src/test/resources/org/apache/camel/component/etcd/cloud/SpringEtcdServiceCallRouteTest.xml b/components/camel-etcd/src/test/resources/org/apache/camel/component/etcd/cloud/SpringEtcdServiceCallRouteTest.xml
new file mode 100644
index 0000000..57acf03
--- /dev/null
+++ b/components/camel-etcd/src/test/resources/org/apache/camel/component/etcd/cloud/SpringEtcdServiceCallRouteTest.xml
@@ -0,0 +1,85 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ 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.
+  -->
+<beans xmlns="http://www.springframework.org/schema/beans"
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xsi:schemaLocation="
+         http://www.springframework.org/schema/beans
+         http://www.springframework.org/schema/beans/spring-beans.xsd
+         http://camel.apache.org/schema/spring
+         http://camel.apache.org/schema/spring/camel-spring.xsd">
+
+  <camelContext xmlns="http://camel.apache.org/schema/spring">
+    <serviceCallConfiguration id="service-0">
+      <etcdServiceDiscovery servicePath="/etcd-services-0/"/>
+    </serviceCallConfiguration>
+
+    <route>
+      <from uri="direct:start"/>
+      <choice>
+        <when>
+          <simple>${body} == 'service-0'</simple>
+          <serviceCall name="http-service" configurationRef="service-0"/>
+          <to uri="mock:result-0"/>
+        </when>
+        <when>
+          <simple>${body} == 'service-1'</simple>
+          <serviceCall name="http-service">
+            <etcdServiceDiscovery servicePath="/etcd-services-1/"/>
+          </serviceCall>
+          <to uri="mock:result-1"/>
+        </when>
+        <when>
+          <simple>${body} == 'service-2'</simple>
+          <serviceCall name="http-service">
+            <etcdServiceDiscovery servicePath="/etcd-services-2/"/>
+          </serviceCall>
+          <to uri="mock:result-2"/>
+        </when>
+      </choice>
+    </route>
+
+    <route>
+      <from uri="jetty:http://localhost:9091"/>
+      <transform>
+        <simple>${body} 9091</simple>
+      </transform>
+    </route>
+
+    <route>
+      <from uri="jetty:http://localhost:9092"/>
+      <transform>
+        <simple>${body} 9092</simple>
+      </transform>
+    </route>
+
+    <route>
+      <from uri="jetty:http://localhost:9093"/>
+      <transform>
+        <simple>${body} 9093</simple>
+      </transform>
+    </route>
+
+    <route>
+      <from uri="jetty:http://localhost:9094"/>
+      <transform>
+        <simple>${body} 9094</simple>
+      </transform>
+    </route>
+  </camelContext>
+
+</beans>

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/components/camel-kubernetes/src/main/java/org/apache/camel/component/kubernetes/cloud/KubernetesClientServiceDiscovery.java
----------------------------------------------------------------------
diff --git a/components/camel-kubernetes/src/main/java/org/apache/camel/component/kubernetes/cloud/KubernetesClientServiceDiscovery.java b/components/camel-kubernetes/src/main/java/org/apache/camel/component/kubernetes/cloud/KubernetesClientServiceDiscovery.java
new file mode 100644
index 0000000..0557cb1
--- /dev/null
+++ b/components/camel-kubernetes/src/main/java/org/apache/camel/component/kubernetes/cloud/KubernetesClientServiceDiscovery.java
@@ -0,0 +1,148 @@
+/**
+ * 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.kubernetes.cloud;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import io.fabric8.kubernetes.api.model.EndpointAddress;
+import io.fabric8.kubernetes.api.model.EndpointPort;
+import io.fabric8.kubernetes.api.model.EndpointSubset;
+import io.fabric8.kubernetes.api.model.Endpoints;
+import io.fabric8.kubernetes.client.AutoAdaptableKubernetesClient;
+import io.fabric8.kubernetes.client.ConfigBuilder;
+import org.apache.camel.cloud.ServiceDefinition;
+import org.apache.camel.component.kubernetes.KubernetesConfiguration;
+import org.apache.camel.impl.cloud.DefaultServiceDefinition;
+import org.apache.camel.util.IOHelper;
+import org.apache.camel.util.ObjectHelper;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class KubernetesClientServiceDiscovery extends KubernetesServiceDiscovery {
+    private static final Logger LOG = LoggerFactory.getLogger(KubernetesClientServiceDiscovery.class);
+    private static final int FIRST = 0;
+
+    private AutoAdaptableKubernetesClient client;
+
+    public KubernetesClientServiceDiscovery(KubernetesConfiguration configuration) {
+        super(configuration);
+        this.client = null;
+    }
+
+    @Override
+    public List<ServiceDefinition> getUpdatedListOfServices(String name) {
+        LOG.debug("Discovering endpoints from namespace: {} with name: {}", getNamespace(), name);
+        Endpoints endpoints = client.endpoints().inNamespace(getNamespace()).withName(name).get();
+        List<ServiceDefinition> result = new ArrayList<>();
+        if (endpoints != null) {
+            if (LOG.isDebugEnabled()) {
+                LOG.debug("Found {} endpoints in namespace: {} for name: {} and portName: {}",
+                    endpoints.getSubsets().size(), getNamespace(), name, getPortName());
+            }
+            for (EndpointSubset subset : endpoints.getSubsets()) {
+                if (subset.getPorts().size() == 1) {
+                    addServers(name, result, subset.getPorts().get(FIRST), subset);
+                } else {
+                    final List<EndpointPort> ports = subset.getPorts();
+                    final int portSize = ports.size();
+
+                    EndpointPort port;
+                    for (int p = 0; p < portSize; p++) {
+                        port = ports.get(p);
+                        if (ObjectHelper.isEmpty(getPortName()) || getPortName().endsWith(port.getName())) {
+                            addServers(name, result, port, subset);
+                        }
+                    }
+                }
+            }
+        }
+
+        return result;
+    }
+
+    protected void addServers(String name, List<ServiceDefinition> servers, EndpointPort port, EndpointSubset subset) {
+        final List<EndpointAddress> addresses = subset.getAddresses();
+        final int size = addresses.size();
+
+        for (int i = 0; i < size; i++) {
+            servers.add(new DefaultServiceDefinition(name, addresses.get(i).getIp(), port.getPort()));
+        }
+    }
+
+    @Override
+    protected void doStart() throws Exception {
+        if (client != null) {
+            return;
+        }
+
+        final KubernetesConfiguration configuration = getConfiguration();
+
+        ConfigBuilder builder = new ConfigBuilder();
+        builder.withMasterUrl(configuration.getMasterUrl());
+
+        if ((ObjectHelper.isNotEmpty(configuration.getUsername())
+            && ObjectHelper.isNotEmpty(configuration.getPassword()))
+            && ObjectHelper.isEmpty(configuration.getOauthToken())) {
+            builder.withUsername(configuration.getUsername());
+            builder.withPassword(configuration.getPassword());
+        } else {
+            builder.withOauthToken(configuration.getOauthToken());
+        }
+        if (ObjectHelper.isNotEmpty(configuration.getCaCertData())) {
+            builder.withCaCertData(configuration.getCaCertData());
+        }
+        if (ObjectHelper.isNotEmpty(configuration.getCaCertFile())) {
+            builder.withCaCertFile(configuration.getCaCertFile());
+        }
+        if (ObjectHelper.isNotEmpty(configuration.getClientCertData())) {
+            builder.withClientCertData(configuration.getClientCertData());
+        }
+        if (ObjectHelper.isNotEmpty(configuration.getClientCertFile())) {
+            builder.withClientCertFile(configuration.getClientCertFile());
+        }
+        if (ObjectHelper.isNotEmpty(configuration.getApiVersion())) {
+            builder.withApiVersion(configuration.getApiVersion());
+        }
+        if (ObjectHelper.isNotEmpty(configuration.getClientKeyAlgo())) {
+            builder.withClientKeyAlgo(configuration.getClientKeyAlgo());
+        }
+        if (ObjectHelper.isNotEmpty(configuration.getClientKeyData())) {
+            builder.withClientKeyData(configuration.getClientKeyData());
+        }
+        if (ObjectHelper.isNotEmpty(configuration.getClientKeyFile())) {
+            builder.withClientKeyFile(configuration.getClientKeyFile());
+        }
+        if (ObjectHelper.isNotEmpty(configuration.getClientKeyPassphrase())) {
+            builder.withClientKeyPassphrase(configuration.getClientKeyPassphrase());
+        }
+        if (ObjectHelper.isNotEmpty(configuration.getTrustCerts())) {
+            builder.withTrustCerts(configuration.getTrustCerts());
+        }
+
+        client = new AutoAdaptableKubernetesClient(builder.build());
+    }
+
+    @Override
+    protected void doStop() throws Exception {
+        if (client != null) {
+            IOHelper.close(client);
+            client = null;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/components/camel-kubernetes/src/main/java/org/apache/camel/component/kubernetes/cloud/KubernetesDnsServiceDiscovery.java
----------------------------------------------------------------------
diff --git a/components/camel-kubernetes/src/main/java/org/apache/camel/component/kubernetes/cloud/KubernetesDnsServiceDiscovery.java b/components/camel-kubernetes/src/main/java/org/apache/camel/component/kubernetes/cloud/KubernetesDnsServiceDiscovery.java
new file mode 100644
index 0000000..003bbdc
--- /dev/null
+++ b/components/camel-kubernetes/src/main/java/org/apache/camel/component/kubernetes/cloud/KubernetesDnsServiceDiscovery.java
@@ -0,0 +1,48 @@
+/**
+ * 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.kubernetes.cloud;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+
+import org.apache.camel.cloud.ServiceDefinition;
+import org.apache.camel.component.kubernetes.KubernetesConfiguration;
+import org.apache.camel.impl.cloud.DefaultServiceDefinition;
+
+public class KubernetesDnsServiceDiscovery extends KubernetesServiceDiscovery {
+    private ConcurrentMap<String, List<ServiceDefinition>> cache;
+
+    public KubernetesDnsServiceDiscovery(KubernetesConfiguration configuration) {
+        super(configuration);
+        this.cache = new ConcurrentHashMap<>();
+    }
+
+    @Override
+    public List<ServiceDefinition> getUpdatedListOfServices(String name) {
+        return this.cache.computeIfAbsent(name, key -> Collections.singletonList(newService(name)));
+    }
+
+    private ServiceDefinition newService(String name) {
+        return new DefaultServiceDefinition(
+            name,
+            name + "." + getConfiguration().getNamespace() + ".svc." + getConfiguration().getDnsDomain(),
+            -1);
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/components/camel-kubernetes/src/main/java/org/apache/camel/component/kubernetes/cloud/KubernetesEnvServiceDiscovery.java
----------------------------------------------------------------------
diff --git a/components/camel-kubernetes/src/main/java/org/apache/camel/component/kubernetes/cloud/KubernetesEnvServiceDiscovery.java b/components/camel-kubernetes/src/main/java/org/apache/camel/component/kubernetes/cloud/KubernetesEnvServiceDiscovery.java
new file mode 100644
index 0000000..4a01318
--- /dev/null
+++ b/components/camel-kubernetes/src/main/java/org/apache/camel/component/kubernetes/cloud/KubernetesEnvServiceDiscovery.java
@@ -0,0 +1,47 @@
+/**
+ * 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.kubernetes.cloud;
+
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.RuntimeCamelException;
+import org.apache.camel.cloud.ServiceDefinition;
+import org.apache.camel.component.kubernetes.KubernetesConfiguration;
+import org.apache.camel.impl.cloud.DefaultServiceDefinition;
+
+public class KubernetesEnvServiceDiscovery extends KubernetesServiceDiscovery {
+    public KubernetesEnvServiceDiscovery(KubernetesConfiguration configuration) {
+        super(configuration);
+    }
+
+    @Override
+    public List<ServiceDefinition> getUpdatedListOfServices(String name) {
+        try {
+            final CamelContext ctx = getCamelContext();
+            final String host = ctx.resolvePropertyPlaceholders("{{service.host:" + name + "}}");
+            final String num = ctx.resolvePropertyPlaceholders("{{service.port:" + name + "}}");
+            final int port = ctx.getTypeConverter().tryConvertTo(int.class, num);
+
+            return Collections.singletonList(new DefaultServiceDefinition(name, host, port));
+        } catch (Exception e) {
+            throw new RuntimeCamelException(e);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/components/camel-kubernetes/src/main/java/org/apache/camel/component/kubernetes/cloud/KubernetesServiceDiscovery.java
----------------------------------------------------------------------
diff --git a/components/camel-kubernetes/src/main/java/org/apache/camel/component/kubernetes/cloud/KubernetesServiceDiscovery.java b/components/camel-kubernetes/src/main/java/org/apache/camel/component/kubernetes/cloud/KubernetesServiceDiscovery.java
new file mode 100644
index 0000000..b6899c7
--- /dev/null
+++ b/components/camel-kubernetes/src/main/java/org/apache/camel/component/kubernetes/cloud/KubernetesServiceDiscovery.java
@@ -0,0 +1,69 @@
+/**
+ * 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.kubernetes.cloud;
+
+import io.fabric8.kubernetes.api.model.EndpointAddress;
+import io.fabric8.kubernetes.api.model.EndpointPort;
+import io.fabric8.kubernetes.client.AutoAdaptableKubernetesClient;
+import org.apache.camel.cloud.ServiceDefinition;
+import org.apache.camel.component.kubernetes.KubernetesConfiguration;
+import org.apache.camel.impl.cloud.DefaultServiceDefinition;
+import org.apache.camel.impl.cloud.DefaultServiceDiscovery;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Discovers where services are running on which servers in Kubernetes.
+ */
+abstract class KubernetesServiceDiscovery extends DefaultServiceDiscovery {
+    private static final Logger LOG = LoggerFactory.getLogger(KubernetesServiceDiscovery.class);
+    private static final int FIRST = 0;
+
+    private final KubernetesConfiguration configuration;
+    private final String namespace;
+    private final String portName;
+    private AutoAdaptableKubernetesClient client;
+
+    KubernetesServiceDiscovery(KubernetesConfiguration configuration) {
+        this.configuration = configuration;
+        this.namespace = configuration.getNamespace() != null ? configuration.getNamespace() : System.getenv("KUBERNETES_NAMESPACE");
+        this.portName = configuration.getPortName();
+        this.client = null;
+    }
+
+    @Override
+    public String toString() {
+        return "KubernetesServiceDiscovery";
+    }
+
+    protected ServiceDefinition newServer(String serviceName, EndpointAddress address, EndpointPort port) {
+        return new DefaultServiceDefinition(serviceName, address.getIp(), port.getPort());
+    }
+
+    protected KubernetesConfiguration getConfiguration() {
+        return this.configuration;
+    }
+
+    public String getNamespace() {
+        return namespace;
+    }
+
+    public String getPortName() {
+        return portName;
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/components/camel-kubernetes/src/main/java/org/apache/camel/component/kubernetes/cloud/KubernetesServiceDiscoveryFactory.java
----------------------------------------------------------------------
diff --git a/components/camel-kubernetes/src/main/java/org/apache/camel/component/kubernetes/cloud/KubernetesServiceDiscoveryFactory.java b/components/camel-kubernetes/src/main/java/org/apache/camel/component/kubernetes/cloud/KubernetesServiceDiscoveryFactory.java
new file mode 100644
index 0000000..37bdff1
--- /dev/null
+++ b/components/camel-kubernetes/src/main/java/org/apache/camel/component/kubernetes/cloud/KubernetesServiceDiscoveryFactory.java
@@ -0,0 +1,187 @@
+/**
+ * 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.kubernetes.cloud;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.cloud.ServiceDiscovery;
+import org.apache.camel.cloud.ServiceDiscoveryFactory;
+import org.apache.camel.component.kubernetes.KubernetesConfiguration;
+import org.apache.camel.util.ObjectHelper;
+
+public class KubernetesServiceDiscoveryFactory implements ServiceDiscoveryFactory {
+    private final KubernetesConfiguration configuration;
+    private String lookup;
+
+    public KubernetesServiceDiscoveryFactory() {
+        this.configuration = new KubernetesConfiguration();
+    }
+
+    // *************************************************************************
+    // Properties
+    // *************************************************************************
+
+    public String getMasterUrl() {
+        return configuration.getMasterUrl();
+    }
+
+    public void setMasterUrl(String masterUrl) {
+        configuration.setMasterUrl(masterUrl);
+    }
+
+    public String getUsername() {
+        return configuration.getUsername();
+    }
+
+    public void setUsername(String username) {
+        configuration.setUsername(username);
+    }
+
+    public String getPassword() {
+        return configuration.getPassword();
+    }
+
+    public void setPassword(String password) {
+        configuration.setPassword(password);
+    }
+
+    public String getApiVersion() {
+        return configuration.getApiVersion();
+    }
+
+    public void setApiVersion(String apiVersion) {
+        configuration.setApiVersion(apiVersion);
+    }
+
+    public String getCaCertData() {
+        return configuration.getCaCertData();
+    }
+
+    public void setCaCertData(String caCertData) {
+        configuration.setCaCertData(caCertData);
+    }
+
+    public String getCaCertFile() {
+        return configuration.getCaCertFile();
+    }
+
+    public void setCaCertFile(String caCertFile) {
+        configuration.setCaCertFile(caCertFile);
+    }
+
+    public String getClientCertData() {
+        return configuration.getClientCertData();
+    }
+
+    public void setClientCertData(String clientCertData) {
+        configuration.setClientCertData(clientCertData);
+    }
+
+    public String getClientCertFile() {
+        return configuration.getClientCertFile();
+    }
+
+    public void setClientCertFile(String clientCertFile) {
+        configuration.setClientCertFile(clientCertFile);
+    }
+
+    public String getClientKeyAlgo() {
+        return configuration.getClientKeyAlgo();
+    }
+
+    public void setClientKeyAlgo(String clientKeyAlgo) {
+        configuration.setClientKeyAlgo(clientKeyAlgo);
+    }
+
+    public String getClientKeyData() {
+        return configuration.getClientKeyData();
+    }
+
+    public void setClientKeyData(String clientKeyData) {
+        configuration.setClientKeyData(clientKeyData);
+    }
+
+    public String getClientKeyFile() {
+        return configuration.getClientKeyFile();
+    }
+
+    public void setClientKeyFile(String clientKeyFile) {
+        configuration.setClientKeyFile(clientKeyFile);
+    }
+
+    public String getClientKeyPassphrase() {
+        return configuration.getClientKeyPassphrase();
+    }
+
+    public void setClientKeyPassphrase(String clientKeyPassphrase) {
+        configuration.setClientKeyPassphrase(clientKeyPassphrase);
+    }
+
+    public String getOauthToken() {
+        return configuration.getOauthToken();
+    }
+
+    public void setOauthToken(String oauthToken) {
+        configuration.setOauthToken(oauthToken);
+    }
+
+    public Boolean getTrustCerts() {
+        return configuration.getTrustCerts();
+    }
+
+    public void setTrustCerts(Boolean trustCerts) {
+        configuration.setTrustCerts(trustCerts);
+    }
+
+    public String getNamespace() {
+        return configuration.getNamespace();
+    }
+
+    public void setNamespace(String namespace) {
+        configuration.setNamespace(namespace);
+    }
+
+    public String getDnsDomain() {
+        return configuration.getDnsDomain();
+    }
+
+    public void setDnsDomain(String dnsDomain) {
+        configuration.setDnsDomain(dnsDomain);
+    }
+
+    public String getLookup() {
+        return lookup;
+    }
+
+    public void setLookup(String lookup) {
+        this.lookup = lookup;
+    }
+
+    // *************************************************************************
+    // Factory
+    // *************************************************************************
+
+    @Override
+    public ServiceDiscovery newInstance(CamelContext camelContext) throws Exception {
+        if (ObjectHelper.equal("dns", lookup)) {
+            return new KubernetesDnsServiceDiscovery(configuration);
+        } else if (ObjectHelper.equal("client", lookup)) {
+            return new KubernetesClientServiceDiscovery(configuration);
+        }
+
+        return new KubernetesEnvServiceDiscovery(configuration);
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/components/camel-kubernetes/src/main/java/org/apache/camel/component/kubernetes/processor/KubernetesDnsServiceCallExpression.java
----------------------------------------------------------------------
diff --git a/components/camel-kubernetes/src/main/java/org/apache/camel/component/kubernetes/processor/KubernetesDnsServiceCallExpression.java b/components/camel-kubernetes/src/main/java/org/apache/camel/component/kubernetes/processor/KubernetesDnsServiceCallExpression.java
deleted file mode 100644
index 42903e1..0000000
--- a/components/camel-kubernetes/src/main/java/org/apache/camel/component/kubernetes/processor/KubernetesDnsServiceCallExpression.java
+++ /dev/null
@@ -1,80 +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.kubernetes.processor;
-
-import org.apache.camel.Exchange;
-import org.apache.camel.impl.remote.ServiceCallConstants;
-import org.apache.camel.support.ExpressionAdapter;
-import org.apache.camel.util.ObjectHelper;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class KubernetesDnsServiceCallExpression extends ExpressionAdapter {
-    private static final Logger LOG = LoggerFactory.getLogger(KubernetesDnsServiceCallExpression.class);
-
-    private final String name;
-    private final String scheme;
-    private final String contextPath;
-    private final String uri;
-
-    public KubernetesDnsServiceCallExpression(String name, String scheme, String contextPath, String uri) {
-        this.name = name;
-        this.scheme = scheme;
-        this.contextPath = contextPath;
-        this.uri = uri;
-    }
-
-    @Override
-    public Object evaluate(Exchange exchange) {
-        try {
-            return buildCamelEndpointUri(
-                name,
-                uri,
-                contextPath,
-                scheme,
-                ObjectHelper.notNull(
-                    exchange.getIn().getHeader(ServiceCallConstants.SERVER_IP, String.class),
-                    ServiceCallConstants.SERVER_IP)
-            );
-        } catch (Exception e) {
-            throw ObjectHelper.wrapRuntimeCamelException(e);
-        }
-    }
-
-    protected static String buildCamelEndpointUri(String name, String uri, String contextPath, String scheme, String dnsServicePart) {
-        // build basic uri if none provided
-        String answer = uri;
-        if (answer == null) {
-            if (scheme == null) {
-                // use http by default if no scheme has been configured
-                scheme = "http";
-            }
-            answer = scheme + "://" + dnsServicePart;
-            if (contextPath != null) {
-                answer += "/" + contextPath;
-            }
-        } else {
-            // we have existing uri, then replace the serviceName with name.namespace.svc.dnsDomain
-            if (answer.contains(name)) {
-                answer = answer.replaceFirst(name, dnsServicePart);
-            }
-        }
-
-        LOG.debug("Camel endpoint uri: {} for calling service: {}", answer, name);
-        return answer;
-    }
-}

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/components/camel-kubernetes/src/main/java/org/apache/camel/component/kubernetes/processor/KubernetesProcessorFactory.java
----------------------------------------------------------------------
diff --git a/components/camel-kubernetes/src/main/java/org/apache/camel/component/kubernetes/processor/KubernetesProcessorFactory.java b/components/camel-kubernetes/src/main/java/org/apache/camel/component/kubernetes/processor/KubernetesProcessorFactory.java
deleted file mode 100644
index 86b8aa7..0000000
--- a/components/camel-kubernetes/src/main/java/org/apache/camel/component/kubernetes/processor/KubernetesProcessorFactory.java
+++ /dev/null
@@ -1,74 +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.kubernetes.processor;
-
-import java.util.Map;
-import java.util.Optional;
-
-import org.apache.camel.ExchangePattern;
-import org.apache.camel.component.kubernetes.KubernetesConfiguration;
-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 Kubernetes implementation of the ServiceCall EIP.
- */
-public class KubernetesProcessorFactory extends DefaultServiceCallProcessorFactory<KubernetesConfiguration, ServiceCallServer> {
-
-    @Override
-    protected KubernetesConfiguration createConfiguration(RouteContext routeContext) throws Exception {
-        return new KubernetesConfiguration();
-    }
-
-    @Override
-    protected DefaultServiceCallProcessor createProcessor(
-            String name,
-            String component,
-            String uri,
-            ExchangePattern mep,
-            KubernetesConfiguration conf,
-            Map<String, String> properties) throws Exception {
-
-        return new KubernetesServiceCallProcessor(name, component, uri, mep, conf);
-    }
-
-    @Override
-    protected Optional<ServiceCallServerListStrategy> builtInServerListStrategy(KubernetesConfiguration conf, String name) throws Exception {
-        ServiceCallServerListStrategy strategy = null;
-        if (ObjectHelper.equal("client", name, true)) {
-            strategy = new KubernetesServiceCallServerListStrategies.Client(conf);
-        } else if (ObjectHelper.equal("environment", name, true)) {
-            strategy = new KubernetesServiceCallServerListStrategies.Environment(conf);
-        } else if (ObjectHelper.equal("env", name, true)) {
-            strategy = new KubernetesServiceCallServerListStrategies.Environment(conf);
-        } else if (ObjectHelper.equal("dns", name, true)) {
-            strategy = new KubernetesServiceCallServerListStrategies.DNS(conf);
-        }
-
-        return Optional.ofNullable(strategy);
-    }
-
-    @Override
-    protected ServiceCallServerListStrategy<ServiceCallServer> createDefaultServerListStrategy(KubernetesConfiguration conf) throws Exception {
-        return new KubernetesServiceCallServerListStrategies.Client(conf);
-    }
-}

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/components/camel-kubernetes/src/main/java/org/apache/camel/component/kubernetes/processor/KubernetesServiceCallProcessor.java
----------------------------------------------------------------------
diff --git a/components/camel-kubernetes/src/main/java/org/apache/camel/component/kubernetes/processor/KubernetesServiceCallProcessor.java b/components/camel-kubernetes/src/main/java/org/apache/camel/component/kubernetes/processor/KubernetesServiceCallProcessor.java
deleted file mode 100644
index f6e27e9..0000000
--- a/components/camel-kubernetes/src/main/java/org/apache/camel/component/kubernetes/processor/KubernetesServiceCallProcessor.java
+++ /dev/null
@@ -1,53 +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.kubernetes.processor;
-
-import org.apache.camel.ExchangePattern;
-import org.apache.camel.component.kubernetes.KubernetesConfiguration;
-import org.apache.camel.impl.remote.DefaultServiceCallProcessor;
-import org.apache.camel.spi.ServiceCallServer;
-import org.apache.camel.spi.ServiceCallServerListStrategy;
-
-public class KubernetesServiceCallProcessor extends DefaultServiceCallProcessor<ServiceCallServer> {
-    public KubernetesServiceCallProcessor(String name, String scheme, String uri, ExchangePattern exchangePattern, KubernetesConfiguration conf) {
-        super(name, scheme, uri, exchangePattern);
-    }
-
-    @Override
-    public void setServerListStrategy(ServiceCallServerListStrategy<ServiceCallServer> serverListStrategy) {
-        if (!(serverListStrategy instanceof KubernetesServiceCallServerListStrategy)) {
-            throw new IllegalArgumentException("ServerListStrategy is not an instance of KubernetesServiceCallServerListStrategy");
-        }
-
-        super.setServerListStrategy(serverListStrategy);
-    }
-
-    @Override
-    protected void doStart() throws Exception {
-        ServiceCallServerListStrategy<ServiceCallServer> strategy = getServerListStrategy();
-        if (strategy != null && strategy instanceof KubernetesServiceCallServerListStrategies.DNS) {
-            setServiceCallExpression(new KubernetesDnsServiceCallExpression(
-                getName(),
-                getScheme(),
-                getContextPath(),
-                getUri()
-            ));
-        }
-
-        super.doStart();
-    }
-}

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/components/camel-kubernetes/src/main/java/org/apache/camel/component/kubernetes/processor/KubernetesServiceCallServerListStrategies.java
----------------------------------------------------------------------
diff --git a/components/camel-kubernetes/src/main/java/org/apache/camel/component/kubernetes/processor/KubernetesServiceCallServerListStrategies.java b/components/camel-kubernetes/src/main/java/org/apache/camel/component/kubernetes/processor/KubernetesServiceCallServerListStrategies.java
deleted file mode 100644
index ec04359..0000000
--- a/components/camel-kubernetes/src/main/java/org/apache/camel/component/kubernetes/processor/KubernetesServiceCallServerListStrategies.java
+++ /dev/null
@@ -1,246 +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.kubernetes.processor;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-
-import io.fabric8.kubernetes.api.model.EndpointAddress;
-import io.fabric8.kubernetes.api.model.EndpointPort;
-import io.fabric8.kubernetes.api.model.EndpointSubset;
-import io.fabric8.kubernetes.api.model.Endpoints;
-import io.fabric8.kubernetes.client.AutoAdaptableKubernetesClient;
-import io.fabric8.kubernetes.client.ConfigBuilder;
-import org.apache.camel.CamelContext;
-import org.apache.camel.RuntimeCamelException;
-import org.apache.camel.component.kubernetes.KubernetesConfiguration;
-import org.apache.camel.impl.remote.DefaultServiceCallServer;
-import org.apache.camel.spi.ServiceCallServer;
-import org.apache.camel.util.IOHelper;
-import org.apache.camel.util.ObjectHelper;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public final class KubernetesServiceCallServerListStrategies {
-    private KubernetesServiceCallServerListStrategies() {
-    }
-
-    // *************************************************************************
-    // Client
-    // *************************************************************************
-
-    public static final class Client extends KubernetesServiceCallServerListStrategy {
-        private static final Logger LOG = LoggerFactory.getLogger(Client.class);
-        private static final int FIRST = 0;
-
-        private AutoAdaptableKubernetesClient client;
-
-        public Client(KubernetesConfiguration configuration) {
-            super(configuration);
-
-            this.client = null;
-        }
-
-        public List<ServiceCallServer> getUpdatedListOfServers(String name) {
-            LOG.debug("Discovering endpoints from namespace: {} with name: {}", getNamespace(), name);
-            Endpoints endpoints = client.endpoints().inNamespace(getNamespace()).withName(name).get();
-            List<ServiceCallServer> result = new ArrayList<>();
-            if (endpoints != null) {
-                if (LOG.isDebugEnabled()) {
-                    LOG.debug("Found {} endpoints in namespace: {} for name: {} and portName: {}",
-                        endpoints.getSubsets().size(), getNamespace(), name, getPortName());
-                }
-                for (EndpointSubset subset : endpoints.getSubsets()) {
-                    if (subset.getPorts().size() == 1) {
-                        addServers(result, subset.getPorts().get(FIRST), subset);
-                    } else {
-                        final List<EndpointPort> ports = subset.getPorts();
-                        final int portSize = ports.size();
-
-                        EndpointPort port;
-                        for (int p = 0; p < portSize; p++) {
-                            port = ports.get(p);
-                            if (ObjectHelper.isEmpty(getPortName()) || getPortName().endsWith(port.getName())) {
-                                addServers(result, port, subset);
-                            }
-                        }
-                    }
-                }
-            }
-
-            return result;
-        }
-
-        protected void addServers(List<ServiceCallServer> servers, EndpointPort port, EndpointSubset subset) {
-            final List<EndpointAddress> addresses = subset.getAddresses();
-            final int size = addresses.size();
-
-            for (int i = 0; i < size; i++) {
-                servers.add(new DefaultServiceCallServer(addresses.get(i).getIp(), port.getPort()));
-            }
-        }
-
-        @Override
-        protected void doStart() throws Exception {
-            if (client != null) {
-                return;
-            }
-
-            final KubernetesConfiguration configuration = getConfiguration();
-
-            ConfigBuilder builder = new ConfigBuilder();
-            builder.withMasterUrl(configuration.getMasterUrl());
-
-            if ((ObjectHelper.isNotEmpty(configuration.getUsername())
-                && ObjectHelper.isNotEmpty(configuration.getPassword()))
-                && ObjectHelper.isEmpty(configuration.getOauthToken())) {
-                builder.withUsername(configuration.getUsername());
-                builder.withPassword(configuration.getPassword());
-            } else {
-                builder.withOauthToken(configuration.getOauthToken());
-            }
-            if (ObjectHelper.isNotEmpty(configuration.getCaCertData())) {
-                builder.withCaCertData(configuration.getCaCertData());
-            }
-            if (ObjectHelper.isNotEmpty(configuration.getCaCertFile())) {
-                builder.withCaCertFile(configuration.getCaCertFile());
-            }
-            if (ObjectHelper.isNotEmpty(configuration.getClientCertData())) {
-                builder.withClientCertData(configuration.getClientCertData());
-            }
-            if (ObjectHelper.isNotEmpty(configuration.getClientCertFile())) {
-                builder.withClientCertFile(configuration.getClientCertFile());
-            }
-            if (ObjectHelper.isNotEmpty(configuration.getApiVersion())) {
-                builder.withApiVersion(configuration.getApiVersion());
-            }
-            if (ObjectHelper.isNotEmpty(configuration.getClientKeyAlgo())) {
-                builder.withClientKeyAlgo(configuration.getClientKeyAlgo());
-            }
-            if (ObjectHelper.isNotEmpty(configuration.getClientKeyData())) {
-                builder.withClientKeyData(configuration.getClientKeyData());
-            }
-            if (ObjectHelper.isNotEmpty(configuration.getClientKeyFile())) {
-                builder.withClientKeyFile(configuration.getClientKeyFile());
-            }
-            if (ObjectHelper.isNotEmpty(configuration.getClientKeyPassphrase())) {
-                builder.withClientKeyPassphrase(configuration.getClientKeyPassphrase());
-            }
-            if (ObjectHelper.isNotEmpty(configuration.getTrustCerts())) {
-                builder.withTrustCerts(configuration.getTrustCerts());
-            }
-
-            client = new AutoAdaptableKubernetesClient(builder.build());
-        }
-
-        @Override
-        protected void doStop() throws Exception {
-            if (client != null) {
-                IOHelper.close(client);
-                client = null;
-            }
-        }
-
-        @Override
-        public String toString() {
-            return "KubernetesServiceDiscovery.Client";
-        }
-    }
-
-    // *************************************************************************
-    // DNS
-    // *************************************************************************
-
-    private abstract static class StaticServerListStrategy extends KubernetesServiceCallServerListStrategy {
-        private Map<String, List<ServiceCallServer>> servers;
-
-        StaticServerListStrategy(KubernetesConfiguration configuration) {
-            super(configuration);
-
-            servers = new ConcurrentHashMap<>();
-        }
-
-        @Override
-        public List<ServiceCallServer> getUpdatedListOfServers(String name) {
-            List<ServiceCallServer> list = servers.get(name);
-            if (list == null) {
-                synchronized (servers) {
-                    list = servers.computeIfAbsent(name, this::createServerList);
-                }
-            }
-
-            return list;
-        }
-
-        protected abstract List<ServiceCallServer> createServerList(String name);
-    }
-
-    // *************************************************************************
-    // DNS
-    // *************************************************************************
-
-    public static final class DNS extends StaticServerListStrategy {
-        public DNS(KubernetesConfiguration configuration) {
-            super(configuration);
-        }
-
-        @Override
-        protected List<ServiceCallServer> createServerList(String name) {
-            return Collections.singletonList(new DefaultServiceCallServer(
-                name + "." + getConfiguration().getNamespace() + ".svc." + getConfiguration().getDnsDomain(),
-                -1)
-            );
-        }
-
-        @Override
-        public String toString() {
-            return "KubernetesServiceDiscovery.DNS";
-        }
-    }
-
-    // *************************************************************************
-    // Environment
-    // *************************************************************************
-
-    public static final class Environment extends StaticServerListStrategy {
-        public Environment(KubernetesConfiguration configuration) {
-            super(configuration);
-        }
-
-        @Override
-        protected List<ServiceCallServer> createServerList(String name) {
-            try {
-                final CamelContext ctx = getCamelContext();
-                final String ip = ctx.resolvePropertyPlaceholders("{{service.host:" + name + "}}");
-                final String num = ctx.resolvePropertyPlaceholders("{{service.port:" + name + "}}");
-                final int port = ctx.getTypeConverter().tryConvertTo(int.class, num);
-
-                return Collections.singletonList(new DefaultServiceCallServer(ip, port));
-            } catch (Exception e) {
-                throw new RuntimeCamelException(e);
-            }
-        }
-
-        @Override
-        public String toString() {
-            return "KubernetesServiceDiscovery.Environment";
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/components/camel-kubernetes/src/main/java/org/apache/camel/component/kubernetes/processor/KubernetesServiceCallServerListStrategy.java
----------------------------------------------------------------------
diff --git a/components/camel-kubernetes/src/main/java/org/apache/camel/component/kubernetes/processor/KubernetesServiceCallServerListStrategy.java b/components/camel-kubernetes/src/main/java/org/apache/camel/component/kubernetes/processor/KubernetesServiceCallServerListStrategy.java
deleted file mode 100644
index e9358f0..0000000
--- a/components/camel-kubernetes/src/main/java/org/apache/camel/component/kubernetes/processor/KubernetesServiceCallServerListStrategy.java
+++ /dev/null
@@ -1,70 +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.kubernetes.processor;
-
-import io.fabric8.kubernetes.api.model.EndpointAddress;
-import io.fabric8.kubernetes.api.model.EndpointPort;
-import io.fabric8.kubernetes.client.AutoAdaptableKubernetesClient;
-import org.apache.camel.component.kubernetes.KubernetesConfiguration;
-import org.apache.camel.impl.remote.DefaultServiceCallServer;
-import org.apache.camel.impl.remote.DefaultServiceCallServerListStrategy;
-import org.apache.camel.spi.ServiceCallServer;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * Discovers where services are running on which servers in Kubernetes.
- */
-public abstract class KubernetesServiceCallServerListStrategy extends DefaultServiceCallServerListStrategy<ServiceCallServer> {
-
-    private static final Logger LOG = LoggerFactory.getLogger(KubernetesServiceCallServerListStrategy.class);
-    private static final int FIRST = 0;
-
-    private final KubernetesConfiguration configuration;
-    private final String namespace;
-    private final String portName;
-    private AutoAdaptableKubernetesClient client;
-
-
-    public KubernetesServiceCallServerListStrategy(KubernetesConfiguration configuration) {
-        this.configuration = configuration;
-        this.namespace = configuration.getNamespace() != null ? configuration.getNamespace() : System.getenv("KUBERNETES_NAMESPACE");
-        this.portName = configuration.getPortName();
-        this.client = null;
-    }
-
-    @Override
-    public String toString() {
-        return "KubernetesServiceDiscovery";
-    }
-
-    protected ServiceCallServer newServer(EndpointAddress address, EndpointPort port) {
-        return new DefaultServiceCallServer(address.getIp(), port.getPort());
-    }
-
-    protected KubernetesConfiguration getConfiguration() {
-        return this.configuration;
-    }
-
-    public String getNamespace() {
-        return namespace;
-    }
-
-    public String getPortName() {
-        return portName;
-    }
-}

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/components/camel-kubernetes/src/main/resources/META-INF/services/org/apache/camel/cloud/kubernetes-service-discovery
----------------------------------------------------------------------
diff --git a/components/camel-kubernetes/src/main/resources/META-INF/services/org/apache/camel/cloud/kubernetes-service-discovery b/components/camel-kubernetes/src/main/resources/META-INF/services/org/apache/camel/cloud/kubernetes-service-discovery
new file mode 100644
index 0000000..db3d36a
--- /dev/null
+++ b/components/camel-kubernetes/src/main/resources/META-INF/services/org/apache/camel/cloud/kubernetes-service-discovery
@@ -0,0 +1,17 @@
+#
+# 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.kubernetes.cloud.KubernetesServiceDiscoveryFactory

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/components/camel-kubernetes/src/main/resources/META-INF/services/org/apache/camel/model/ServiceCallDefinition
----------------------------------------------------------------------
diff --git a/components/camel-kubernetes/src/main/resources/META-INF/services/org/apache/camel/model/ServiceCallDefinition b/components/camel-kubernetes/src/main/resources/META-INF/services/org/apache/camel/model/ServiceCallDefinition
deleted file mode 100644
index acf5be8..0000000
--- a/components/camel-kubernetes/src/main/resources/META-INF/services/org/apache/camel/model/ServiceCallDefinition
+++ /dev/null
@@ -1,18 +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.
-#
-
-class=org.apache.camel.component.kubernetes.processor.KubernetesProcessorFactory

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/components/camel-kubernetes/src/test/java/org/apache/camel/component/kubernetes/cloud/ServiceCallClientRouteTest.java
----------------------------------------------------------------------
diff --git a/components/camel-kubernetes/src/test/java/org/apache/camel/component/kubernetes/cloud/ServiceCallClientRouteTest.java b/components/camel-kubernetes/src/test/java/org/apache/camel/component/kubernetes/cloud/ServiceCallClientRouteTest.java
new file mode 100644
index 0000000..bb42272
--- /dev/null
+++ b/components/camel-kubernetes/src/test/java/org/apache/camel/component/kubernetes/cloud/ServiceCallClientRouteTest.java
@@ -0,0 +1,64 @@
+/**
+ * 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.kubernetes.cloud;
+
+import org.apache.camel.RoutesBuilder;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.kubernetes.KubernetesConfiguration;
+import org.apache.camel.model.cloud.ServiceCallConfigurationDefinition;
+import org.apache.camel.test.junit4.CamelTestSupport;
+import org.junit.Ignore;
+import org.junit.Test;
+
+@Ignore("Manual test")
+public class ServiceCallClientRouteTest extends CamelTestSupport {
+
+    @Test
+    public void testServiceCall() throws Exception {
+        getMockEndpoint("mock:result").expectedMessageCount(1);
+
+        template.sendBody("direct:start", "Hello World");
+
+        assertMockEndpointsSatisfied();
+    }
+
+    @Override
+    protected RoutesBuilder createRouteBuilder() throws Exception {
+        return new RouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                KubernetesConfiguration kubernetesConfiguration = new KubernetesConfiguration();
+                kubernetesConfiguration.setMasterUrl("http://172.28.128.80:8080");
+                kubernetesConfiguration.setUsername("admin");
+                kubernetesConfiguration.setPassword("admin");
+                kubernetesConfiguration.setNamespace("default");
+
+                ServiceCallConfigurationDefinition config = new ServiceCallConfigurationDefinition();
+                config.setServiceDiscovery(new KubernetesEnvServiceDiscovery(kubernetesConfiguration));
+
+                // register configuration
+                context.setServiceCallConfiguration(config);
+
+                from("direct:start")
+                    .serviceCall("cdi-camel-jetty")
+                    .serviceCall("cdi-camel-jetty")
+                    .to("mock:result");
+            }
+        };
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/components/camel-kubernetes/src/test/java/org/apache/camel/component/kubernetes/cloud/ServiceCallEnvironmentRouteTest.java
----------------------------------------------------------------------
diff --git a/components/camel-kubernetes/src/test/java/org/apache/camel/component/kubernetes/cloud/ServiceCallEnvironmentRouteTest.java b/components/camel-kubernetes/src/test/java/org/apache/camel/component/kubernetes/cloud/ServiceCallEnvironmentRouteTest.java
new file mode 100644
index 0000000..b194d67
--- /dev/null
+++ b/components/camel-kubernetes/src/test/java/org/apache/camel/component/kubernetes/cloud/ServiceCallEnvironmentRouteTest.java
@@ -0,0 +1,60 @@
+/**
+ * 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.kubernetes.cloud;
+
+import org.apache.camel.RoutesBuilder;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.kubernetes.KubernetesConfiguration;
+import org.apache.camel.model.cloud.ServiceCallConfigurationDefinition;
+import org.apache.camel.test.junit4.CamelTestSupport;
+import org.junit.Ignore;
+import org.junit.Test;
+
+@Ignore("Manual test")
+public class ServiceCallEnvironmentRouteTest extends CamelTestSupport {
+
+    @Test
+    public void testServiceCall() throws Exception {
+        getMockEndpoint("mock:result").expectedMessageCount(1);
+
+        template.sendBody("direct:start", "Hello World");
+
+        assertMockEndpointsSatisfied();
+    }
+
+    @Override
+    protected RoutesBuilder createRouteBuilder() throws Exception {
+        return new RouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                KubernetesConfiguration kubernetesConfiguration = new KubernetesConfiguration();
+
+                ServiceCallConfigurationDefinition config = new ServiceCallConfigurationDefinition();
+                config.setServiceDiscovery(new KubernetesEnvServiceDiscovery(kubernetesConfiguration));
+
+                // register configuration
+                context.setServiceCallConfiguration(config);
+
+                from("direct:start")
+                    .serviceCall("cdi-camel-jetty")
+                    .serviceCall("cdi-camel-jetty")
+                    .to("mock:result");
+            }
+        };
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/components/camel-kubernetes/src/test/java/org/apache/camel/component/kubernetes/cloud/SpringServiceCallClientRouteTest.java
----------------------------------------------------------------------
diff --git a/components/camel-kubernetes/src/test/java/org/apache/camel/component/kubernetes/cloud/SpringServiceCallClientRouteTest.java b/components/camel-kubernetes/src/test/java/org/apache/camel/component/kubernetes/cloud/SpringServiceCallClientRouteTest.java
new file mode 100644
index 0000000..0983519
--- /dev/null
+++ b/components/camel-kubernetes/src/test/java/org/apache/camel/component/kubernetes/cloud/SpringServiceCallClientRouteTest.java
@@ -0,0 +1,42 @@
+/**
+ * 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.kubernetes.cloud;
+
+import org.apache.camel.test.spring.CamelSpringTestSupport;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.springframework.context.support.AbstractApplicationContext;
+import org.springframework.context.support.ClassPathXmlApplicationContext;
+
+@Ignore("Manual test")
+public class SpringServiceCallClientRouteTest extends CamelSpringTestSupport {
+
+    @Override
+    protected AbstractApplicationContext createApplicationContext() {
+        return new ClassPathXmlApplicationContext("org/apache/camel/component/kubernetes/cloud/SpringServiceCallClientRouteTest.xml");
+    }
+
+    @Test
+    public void testServiceCall() throws Exception {
+        getMockEndpoint("mock:result").expectedMessageCount(1);
+
+        template.sendBody("direct:start", "Hello World");
+
+        assertMockEndpointsSatisfied();
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/components/camel-kubernetes/src/test/java/org/apache/camel/component/kubernetes/cloud/SpringServiceCallDnsRouteTest.java
----------------------------------------------------------------------
diff --git a/components/camel-kubernetes/src/test/java/org/apache/camel/component/kubernetes/cloud/SpringServiceCallDnsRouteTest.java b/components/camel-kubernetes/src/test/java/org/apache/camel/component/kubernetes/cloud/SpringServiceCallDnsRouteTest.java
new file mode 100644
index 0000000..23d48c6
--- /dev/null
+++ b/components/camel-kubernetes/src/test/java/org/apache/camel/component/kubernetes/cloud/SpringServiceCallDnsRouteTest.java
@@ -0,0 +1,42 @@
+/**
+ * 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.kubernetes.cloud;
+
+import org.apache.camel.test.spring.CamelSpringTestSupport;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.springframework.context.support.AbstractApplicationContext;
+import org.springframework.context.support.ClassPathXmlApplicationContext;
+
+@Ignore("Manual test")
+public class SpringServiceCallDnsRouteTest extends CamelSpringTestSupport {
+
+    @Override
+    protected AbstractApplicationContext createApplicationContext() {
+        return new ClassPathXmlApplicationContext("org/apache/camel/component/kubernetes/cloud/SpringServiceCallDnsRouteTest.xml");
+    }
+
+    @Test
+    public void testServiceCall() throws Exception {
+        getMockEndpoint("mock:result").expectedMessageCount(1);
+
+        template.sendBody("direct:start", "Hello World");
+
+        assertMockEndpointsSatisfied();
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/components/camel-kubernetes/src/test/java/org/apache/camel/component/kubernetes/cloud/SpringServiceCallEnvironmentRouteTest.java
----------------------------------------------------------------------
diff --git a/components/camel-kubernetes/src/test/java/org/apache/camel/component/kubernetes/cloud/SpringServiceCallEnvironmentRouteTest.java b/components/camel-kubernetes/src/test/java/org/apache/camel/component/kubernetes/cloud/SpringServiceCallEnvironmentRouteTest.java
new file mode 100644
index 0000000..cc9f21e
--- /dev/null
+++ b/components/camel-kubernetes/src/test/java/org/apache/camel/component/kubernetes/cloud/SpringServiceCallEnvironmentRouteTest.java
@@ -0,0 +1,42 @@
+/**
+ * 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.kubernetes.cloud;
+
+import org.apache.camel.test.spring.CamelSpringTestSupport;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.springframework.context.support.AbstractApplicationContext;
+import org.springframework.context.support.ClassPathXmlApplicationContext;
+
+@Ignore("Manual test")
+public class SpringServiceCallEnvironmentRouteTest extends CamelSpringTestSupport {
+
+    @Override
+    protected AbstractApplicationContext createApplicationContext() {
+        return new ClassPathXmlApplicationContext("org/apache/camel/component/kubernetes/cloud/SpringServiceCallEnvironmentRouteTest.xml");
+    }
+
+    @Test
+    public void testServiceCall() throws Exception {
+        getMockEndpoint("mock:result").expectedMessageCount(1);
+
+        template.sendBody("direct:start", "Hello World");
+
+        assertMockEndpointsSatisfied();
+    }
+}


[03/10] camel git commit: CAMEL-10638: Refactor ServiceCall EIP

Posted by lb...@apache.org.
http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/components/camel-kubernetes/src/test/java/org/apache/camel/component/kubernetes/processor/ServiceCallClientRouteTest.java
----------------------------------------------------------------------
diff --git a/components/camel-kubernetes/src/test/java/org/apache/camel/component/kubernetes/processor/ServiceCallClientRouteTest.java b/components/camel-kubernetes/src/test/java/org/apache/camel/component/kubernetes/processor/ServiceCallClientRouteTest.java
deleted file mode 100644
index b5e03e3..0000000
--- a/components/camel-kubernetes/src/test/java/org/apache/camel/component/kubernetes/processor/ServiceCallClientRouteTest.java
+++ /dev/null
@@ -1,62 +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.kubernetes.processor;
-
-import org.apache.camel.RoutesBuilder;
-import org.apache.camel.builder.RouteBuilder;
-import org.apache.camel.model.remote.KubernetesConfigurationDefinition;
-import org.apache.camel.test.junit4.CamelTestSupport;
-import org.junit.Ignore;
-import org.junit.Test;
-
-@Ignore("Manual test")
-public class ServiceCallClientRouteTest extends CamelTestSupport {
-
-    @Test
-    public void testServiceCall() throws Exception {
-        getMockEndpoint("mock:result").expectedMessageCount(1);
-
-        template.sendBody("direct:start", "Hello World");
-
-        assertMockEndpointsSatisfied();
-    }
-
-    @Override
-    protected RoutesBuilder createRouteBuilder() throws Exception {
-        return new RouteBuilder() {
-            @Override
-            public void configure() throws Exception {
-                KubernetesConfigurationDefinition config = new KubernetesConfigurationDefinition();
-                config.setMasterUrl("http://172.28.128.80:8080");
-                config.setUsername("admin");
-                config.setPassword("admin");
-                config.setNamespace("default");
-                config.setLookup("client");
-                // lets use the built-in round robin (random is default)
-                config.setLoadBalancerRef("roundrobin");
-
-                // register configuration
-                context.setServiceCallConfiguration(config);
-
-                from("direct:start")
-                    .serviceCall("cdi-camel-jetty")
-                    .serviceCall("cdi-camel-jetty")
-                    .to("mock:result");
-            }
-        };
-    }
-}

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/components/camel-kubernetes/src/test/java/org/apache/camel/component/kubernetes/processor/ServiceCallEnvironmentRouteTest.java
----------------------------------------------------------------------
diff --git a/components/camel-kubernetes/src/test/java/org/apache/camel/component/kubernetes/processor/ServiceCallEnvironmentRouteTest.java b/components/camel-kubernetes/src/test/java/org/apache/camel/component/kubernetes/processor/ServiceCallEnvironmentRouteTest.java
deleted file mode 100644
index 1e34cb5..0000000
--- a/components/camel-kubernetes/src/test/java/org/apache/camel/component/kubernetes/processor/ServiceCallEnvironmentRouteTest.java
+++ /dev/null
@@ -1,56 +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.kubernetes.processor;
-
-import org.apache.camel.RoutesBuilder;
-import org.apache.camel.builder.RouteBuilder;
-import org.apache.camel.model.remote.KubernetesConfigurationDefinition;
-import org.apache.camel.test.junit4.CamelTestSupport;
-import org.junit.Ignore;
-import org.junit.Test;
-
-@Ignore("Manual test")
-public class ServiceCallEnvironmentRouteTest extends CamelTestSupport {
-
-    @Test
-    public void testServiceCall() throws Exception {
-        getMockEndpoint("mock:result").expectedMessageCount(1);
-
-        template.sendBody("direct:start", "Hello World");
-
-        assertMockEndpointsSatisfied();
-    }
-
-    @Override
-    protected RoutesBuilder createRouteBuilder() throws Exception {
-        return new RouteBuilder() {
-            @Override
-            public void configure() throws Exception {
-                KubernetesConfigurationDefinition config = new KubernetesConfigurationDefinition();
-                config.setLookup("environment");
-
-                // register configuration
-                context.setServiceCallConfiguration(config);
-
-                from("direct:start")
-                    .serviceCall("cdi-camel-jetty")
-                    .serviceCall("cdi-camel-jetty")
-                    .to("mock:result");
-            }
-        };
-    }
-}

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/components/camel-kubernetes/src/test/java/org/apache/camel/component/kubernetes/processor/SpringServiceCallClientRouteTest.java
----------------------------------------------------------------------
diff --git a/components/camel-kubernetes/src/test/java/org/apache/camel/component/kubernetes/processor/SpringServiceCallClientRouteTest.java b/components/camel-kubernetes/src/test/java/org/apache/camel/component/kubernetes/processor/SpringServiceCallClientRouteTest.java
deleted file mode 100644
index 3e8fcba3..0000000
--- a/components/camel-kubernetes/src/test/java/org/apache/camel/component/kubernetes/processor/SpringServiceCallClientRouteTest.java
+++ /dev/null
@@ -1,41 +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.kubernetes.processor;
-
-import org.apache.camel.test.spring.CamelSpringTestSupport;
-import org.junit.Ignore;
-import org.junit.Test;
-import org.springframework.context.support.AbstractApplicationContext;
-import org.springframework.context.support.ClassPathXmlApplicationContext;
-
-@Ignore("Manual test")
-public class SpringServiceCallClientRouteTest extends CamelSpringTestSupport {
-
-    @Override
-    protected AbstractApplicationContext createApplicationContext() {
-        return new ClassPathXmlApplicationContext("org/apache/camel/component/kubernetes/processor/SpringServiceCallClientRouteTest.xml");
-    }
-
-    @Test
-    public void testServiceCall() throws Exception {
-        getMockEndpoint("mock:result").expectedMessageCount(1);
-
-        template.sendBody("direct:start", "Hello World");
-
-        assertMockEndpointsSatisfied();
-    }
-}

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/components/camel-kubernetes/src/test/java/org/apache/camel/component/kubernetes/processor/SpringServiceCallEnvironmentRouteTest.java
----------------------------------------------------------------------
diff --git a/components/camel-kubernetes/src/test/java/org/apache/camel/component/kubernetes/processor/SpringServiceCallEnvironmentRouteTest.java b/components/camel-kubernetes/src/test/java/org/apache/camel/component/kubernetes/processor/SpringServiceCallEnvironmentRouteTest.java
deleted file mode 100644
index bd09c31..0000000
--- a/components/camel-kubernetes/src/test/java/org/apache/camel/component/kubernetes/processor/SpringServiceCallEnvironmentRouteTest.java
+++ /dev/null
@@ -1,41 +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.kubernetes.processor;
-
-import org.apache.camel.test.spring.CamelSpringTestSupport;
-import org.junit.Ignore;
-import org.junit.Test;
-import org.springframework.context.support.AbstractApplicationContext;
-import org.springframework.context.support.ClassPathXmlApplicationContext;
-
-@Ignore("Manual test")
-public class SpringServiceCallEnvironmentRouteTest extends CamelSpringTestSupport {
-
-    @Override
-    protected AbstractApplicationContext createApplicationContext() {
-        return new ClassPathXmlApplicationContext("org/apache/camel/component/kubernetes/processor/SpringServiceCallEnvironmentRouteTest.xml");
-    }
-
-    @Test
-    public void testServiceCall() throws Exception {
-        getMockEndpoint("mock:result").expectedMessageCount(1);
-
-        template.sendBody("direct:start", "Hello World");
-
-        assertMockEndpointsSatisfied();
-    }
-}

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/components/camel-kubernetes/src/test/resources/org/apache/camel/component/kubernetes/cloud/SpringServiceCallClientRouteTest.xml
----------------------------------------------------------------------
diff --git a/components/camel-kubernetes/src/test/resources/org/apache/camel/component/kubernetes/cloud/SpringServiceCallClientRouteTest.xml b/components/camel-kubernetes/src/test/resources/org/apache/camel/component/kubernetes/cloud/SpringServiceCallClientRouteTest.xml
new file mode 100644
index 0000000..1e98b25
--- /dev/null
+++ b/components/camel-kubernetes/src/test/resources/org/apache/camel/component/kubernetes/cloud/SpringServiceCallClientRouteTest.xml
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ 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.
+  -->
+<beans xmlns="http://www.springframework.org/schema/beans"
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xsi:schemaLocation="
+         http://www.springframework.org/schema/beans
+         http://www.springframework.org/schema/beans/spring-beans.xsd
+         http://camel.apache.org/schema/spring
+         http://camel.apache.org/schema/spring/camel-spring.xsd">
+
+  <camelContext xmlns="http://camel.apache.org/schema/spring">
+    <!--
+    <serviceCallConfiguration id="kubernetes">
+        <kubernetesServiceDiscovery masterUrl="http://172.28.128.80:8080"
+                                    username="admin"
+                                    password="admin"
+                                    namespace="default"
+                                    lookup="client"/>
+    </serviceCallConfiguration
+    -->
+
+    <route>
+      <from uri="direct:start"/>
+      <serviceCall name="cdi-camel-jetty">
+        <kubernetesServiceDiscovery masterUrl="http://172.28.128.80:8080"
+                                    username="admin"
+                                    password="admin"
+                                    namespace="default"
+                                    lookup="client"/>
+      </serviceCall>
+      <serviceCall name="cdi-camel-jetty">
+        <kubernetesServiceDiscovery masterUrl="http://172.28.128.80:8080"
+                                    username="admin"
+                                    password="admin"
+                                    namespace="default"
+                                    lookup="client"/>
+      </serviceCall>
+      <to uri="mock:result"/>
+    </route>
+  </camelContext>
+
+</beans>

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/components/camel-kubernetes/src/test/resources/org/apache/camel/component/kubernetes/cloud/SpringServiceCallDnsRouteTest.xml
----------------------------------------------------------------------
diff --git a/components/camel-kubernetes/src/test/resources/org/apache/camel/component/kubernetes/cloud/SpringServiceCallDnsRouteTest.xml b/components/camel-kubernetes/src/test/resources/org/apache/camel/component/kubernetes/cloud/SpringServiceCallDnsRouteTest.xml
new file mode 100644
index 0000000..b8be867
--- /dev/null
+++ b/components/camel-kubernetes/src/test/resources/org/apache/camel/component/kubernetes/cloud/SpringServiceCallDnsRouteTest.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ 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.
+  -->
+<beans xmlns="http://www.springframework.org/schema/beans"
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xsi:schemaLocation="
+         http://www.springframework.org/schema/beans
+         http://www.springframework.org/schema/beans/spring-beans.xsd
+         http://camel.apache.org/schema/spring
+         http://camel.apache.org/schema/spring/camel-spring.xsd">
+  <camelContext xmlns="http://camel.apache.org/schema/spring">
+    <!--
+    <serviceCallConfiguration id="kubernetes">
+      <kubernetesServiceDiscovery lookup="dns"/>
+    </serviceCallConfiguration>
+    -->
+
+    <route>
+      <from uri="direct:start"/>
+      <serviceCall name="cdi-camel-jetty">
+        <kubernetesServiceDiscovery lookup="dns"/>
+      </serviceCall>
+      <serviceCall name="cdi-camel-jetty">
+        <kubernetesServiceDiscovery lookup="dns"/>
+      </serviceCall>
+      <to uri="mock:result"/>
+    </route>
+  </camelContext>
+
+</beans>

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/components/camel-kubernetes/src/test/resources/org/apache/camel/component/kubernetes/cloud/SpringServiceCallEnvironmentRouteTest.xml
----------------------------------------------------------------------
diff --git a/components/camel-kubernetes/src/test/resources/org/apache/camel/component/kubernetes/cloud/SpringServiceCallEnvironmentRouteTest.xml b/components/camel-kubernetes/src/test/resources/org/apache/camel/component/kubernetes/cloud/SpringServiceCallEnvironmentRouteTest.xml
new file mode 100644
index 0000000..8a8686f
--- /dev/null
+++ b/components/camel-kubernetes/src/test/resources/org/apache/camel/component/kubernetes/cloud/SpringServiceCallEnvironmentRouteTest.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ 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.
+  -->
+<beans xmlns="http://www.springframework.org/schema/beans"
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xsi:schemaLocation="
+         http://www.springframework.org/schema/beans
+         http://www.springframework.org/schema/beans/spring-beans.xsd
+         http://camel.apache.org/schema/spring
+         http://camel.apache.org/schema/spring/camel-spring.xsd">
+  <camelContext xmlns="http://camel.apache.org/schema/spring">
+    <!--
+    <serviceCallConfiguration id="kubernetes">
+      <kubernetesServiceDiscovery lookup="environment"/>
+    </serviceCallConfiguration>
+    -->
+
+    <route>
+      <from uri="direct:start"/>
+      <serviceCall name="cdi-camel-jetty">
+        <kubernetesServiceDiscovery lookup="environment"/>
+      </serviceCall>
+      <serviceCall name="cdi-camel-jetty">
+        <kubernetesServiceDiscovery lookup="environment"/>
+      </serviceCall>
+      <to uri="mock:result"/>
+    </route>
+  </camelContext>
+
+</beans>

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/components/camel-kubernetes/src/test/resources/org/apache/camel/component/kubernetes/processor/SpringServiceCallClientRouteTest.xml
----------------------------------------------------------------------
diff --git a/components/camel-kubernetes/src/test/resources/org/apache/camel/component/kubernetes/processor/SpringServiceCallClientRouteTest.xml b/components/camel-kubernetes/src/test/resources/org/apache/camel/component/kubernetes/processor/SpringServiceCallClientRouteTest.xml
deleted file mode 100644
index 87162d9..0000000
--- a/components/camel-kubernetes/src/test/resources/org/apache/camel/component/kubernetes/processor/SpringServiceCallClientRouteTest.xml
+++ /dev/null
@@ -1,39 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-    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.
--->
-<beans xmlns="http://www.springframework.org/schema/beans"
-       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-       xsi:schemaLocation="
-       http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
-       http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd
-    ">
-
-  <camelContext xmlns="http://camel.apache.org/schema/spring">
-
-    <!-- use client to lookup the service, which requires to setup a number of options -->
-    <kubernetesConfiguration id="kubernetes" masterUrl="http://172.28.128.80:8080" lookup="client"
-                             username="admin" password="admin" namespace="default" loadBalancerRef="roundrobin"/>
-
-    <route>
-      <from uri="direct:start"/>
-      <serviceCall name="cdi-camel-jetty"/>
-      <serviceCall name="cdi-camel-jetty"/>
-      <to uri="mock:result"/>
-    </route>
-  </camelContext>
-
-</beans>

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/components/camel-kubernetes/src/test/resources/org/apache/camel/component/kubernetes/processor/SpringServiceCallEnvironmentRouteTest.xml
----------------------------------------------------------------------
diff --git a/components/camel-kubernetes/src/test/resources/org/apache/camel/component/kubernetes/processor/SpringServiceCallEnvironmentRouteTest.xml b/components/camel-kubernetes/src/test/resources/org/apache/camel/component/kubernetes/processor/SpringServiceCallEnvironmentRouteTest.xml
deleted file mode 100644
index 6f2f028..0000000
--- a/components/camel-kubernetes/src/test/resources/org/apache/camel/component/kubernetes/processor/SpringServiceCallEnvironmentRouteTest.xml
+++ /dev/null
@@ -1,38 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-    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.
--->
-<beans xmlns="http://www.springframework.org/schema/beans"
-       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-       xsi:schemaLocation="
-       http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
-       http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd
-    ">
-
-  <camelContext xmlns="http://camel.apache.org/schema/spring">
-
-    <!-- use environment variables to lookup the service -->
-    <kubernetesConfiguration id="kubernetes" lookup="environment"/>
-
-    <route>
-      <from uri="direct:start"/>
-      <serviceCall name="cdi-camel-jetty"/>
-      <serviceCall name="cdi-camel-jetty"/>
-      <to uri="mock:result"/>
-    </route>
-  </camelContext>
-
-</beans>

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/components/camel-ribbon/src/main/java/org/apache/camel/component/ribbon/RibbonConfiguration.java
----------------------------------------------------------------------
diff --git a/components/camel-ribbon/src/main/java/org/apache/camel/component/ribbon/RibbonConfiguration.java b/components/camel-ribbon/src/main/java/org/apache/camel/component/ribbon/RibbonConfiguration.java
index 4931a5b..40bcb31 100644
--- a/components/camel-ribbon/src/main/java/org/apache/camel/component/ribbon/RibbonConfiguration.java
+++ b/components/camel-ribbon/src/main/java/org/apache/camel/component/ribbon/RibbonConfiguration.java
@@ -16,16 +16,20 @@
  */
 package org.apache.camel.component.ribbon;
 
+import java.util.Map;
+import java.util.function.Supplier;
+
 import com.netflix.loadbalancer.IPing;
 import com.netflix.loadbalancer.IRule;
 
 public class RibbonConfiguration {
-
     private String namespace;
     private String username;
     private String password;
     private IRule rule;
     private IPing ping;
+    private String clientName;
+    private Map<String, String> clientConfig;
 
     public String getNamespace() {
         return namespace;
@@ -55,6 +59,10 @@ public class RibbonConfiguration {
         return rule;
     }
 
+    public IRule getRuleOrDefault(Supplier<IRule> supplier) {
+        return rule != null ? rule : supplier.get();
+    }
+
     public void setRule(IRule rule) {
         this.rule = rule;
     }
@@ -63,7 +71,27 @@ public class RibbonConfiguration {
         return ping;
     }
 
+    public IPing getPingOrDefault(Supplier<IPing> supplier) {
+        return ping != null ? ping : supplier.get();
+    }
+
     public void setPing(IPing ping) {
         this.ping = ping;
     }
+
+    public String getClientName() {
+        return clientName;
+    }
+
+    public void setClientName(String clientName) {
+        this.clientName = clientName;
+    }
+
+    public Map<String, String> getClientConfig() {
+        return clientConfig;
+    }
+
+    public void setClientConfig(Map<String, String> clientConfig) {
+        this.clientConfig = clientConfig;
+    }
 }

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/components/camel-ribbon/src/main/java/org/apache/camel/component/ribbon/cloud/RibbonLoadBalancer.java
----------------------------------------------------------------------
diff --git a/components/camel-ribbon/src/main/java/org/apache/camel/component/ribbon/cloud/RibbonLoadBalancer.java b/components/camel-ribbon/src/main/java/org/apache/camel/component/ribbon/cloud/RibbonLoadBalancer.java
new file mode 100644
index 0000000..eb23c1b
--- /dev/null
+++ b/components/camel-ribbon/src/main/java/org/apache/camel/component/ribbon/cloud/RibbonLoadBalancer.java
@@ -0,0 +1,231 @@
+/**
+ * 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.ribbon.cloud;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.RejectedExecutionException;
+
+import com.netflix.client.config.IClientConfig;
+import com.netflix.client.config.IClientConfigKey;
+import com.netflix.loadbalancer.DummyPing;
+import com.netflix.loadbalancer.ILoadBalancer;
+import com.netflix.loadbalancer.PollingServerListUpdater;
+import com.netflix.loadbalancer.RoundRobinRule;
+import com.netflix.loadbalancer.ServerList;
+import com.netflix.loadbalancer.ServerListFilter;
+import com.netflix.loadbalancer.ZoneAwareLoadBalancer;
+import org.apache.camel.CamelContext;
+import org.apache.camel.CamelContextAware;
+import org.apache.camel.cloud.LoadBalancer;
+import org.apache.camel.cloud.LoadBalancerFunction;
+import org.apache.camel.cloud.ServiceDefinition;
+import org.apache.camel.cloud.ServiceDiscovery;
+import org.apache.camel.cloud.ServiceDiscoveryAware;
+import org.apache.camel.cloud.ServiceFilter;
+import org.apache.camel.cloud.ServiceFilterAware;
+import org.apache.camel.component.ribbon.RibbonConfiguration;
+import org.apache.camel.support.ServiceSupport;
+import org.apache.camel.util.ObjectHelper;
+import org.apache.camel.util.ServiceHelper;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class RibbonLoadBalancer
+        extends ServiceSupport
+        implements CamelContextAware, ServiceDiscoveryAware, ServiceFilterAware, LoadBalancer {
+
+    private static final Logger LOGGER = LoggerFactory.getLogger(RibbonLoadBalancer.class);
+
+    private final RibbonConfiguration configuration;
+    private final ConcurrentMap<String, ZoneAwareLoadBalancer<RibbonServiceDefinition>> loadBalancers;
+    private CamelContext camelContext;
+    private ServiceDiscovery serviceDiscovery;
+    private ServiceFilter serviceFilter;
+
+    public RibbonLoadBalancer(RibbonConfiguration configuration) {
+        this.configuration = configuration;
+        this.loadBalancers = new ConcurrentHashMap<>();
+    }
+
+    @Override
+    public CamelContext getCamelContext() {
+        return camelContext;
+    }
+
+    @Override
+    public void setCamelContext(CamelContext camelContext) {
+        this.camelContext = camelContext;
+    }
+
+    @Override
+    public ServiceDiscovery getServiceDiscovery() {
+        return serviceDiscovery;
+    }
+
+    @Override
+    public void setServiceDiscovery(ServiceDiscovery serviceDiscovery) {
+        this.serviceDiscovery = serviceDiscovery;
+    }
+
+    @Override
+    public ServiceFilter getServiceFilter() {
+        return serviceFilter;
+    }
+
+    @Override
+    public void setServiceFilter(ServiceFilter serviceFilter) {
+        this.serviceFilter = serviceFilter;
+    }
+
+    // ************************
+    // lifecycle
+    // ************************
+
+    @Override
+    protected void doStart() throws Exception {
+        ObjectHelper.notNull(configuration, "configuration");
+        ObjectHelper.notNull(camelContext, "camel context");
+        ObjectHelper.notNull(serviceDiscovery, "service discovery");
+        ObjectHelper.notNull(serviceFilter, "service filter");
+
+        LOGGER.info("ServiceCall is using ribbon load balancer with service discovery type: {} and service filter type: {}",
+            serviceDiscovery.getClass(),
+            serviceFilter.getClass());
+
+        ServiceHelper.startService(serviceDiscovery);
+    }
+
+    @Override
+    protected void doStop() throws Exception {
+        loadBalancers.values().forEach(ZoneAwareLoadBalancer::stopServerListRefreshing);
+        loadBalancers.clear();
+
+        ServiceHelper.stopService(serviceDiscovery);
+    }
+
+    // ************************
+    // Processor
+    // ************************
+
+    @Override
+    public <T> T process(String serviceName, LoadBalancerFunction<T> request) throws Exception {
+        ILoadBalancer loadBalancer = loadBalancers.computeIfAbsent(serviceName, key -> createLoadBalancer(key, serviceDiscovery));
+        RibbonServiceDefinition service = (RibbonServiceDefinition)loadBalancer.chooseServer(serviceName);
+
+        if (service == null) {
+            throw new RejectedExecutionException("No active services with name " + serviceName);
+        }
+
+        return request.apply(service);
+    }
+
+    // ************************
+    // Helpers
+    // ************************
+
+    private ZoneAwareLoadBalancer<RibbonServiceDefinition> createLoadBalancer(String serviceName, ServiceDiscovery serviceDiscovery) {
+        // setup client config
+        IClientConfig config = configuration.getClientName() != null
+            ? IClientConfig.Builder.newBuilder(configuration.getClientName()).build()
+            : IClientConfig.Builder.newBuilder().build();
+
+        if (configuration.getClientConfig() != null) {
+            for (Map.Entry<String, String> entry : configuration.getClientConfig().entrySet()) {
+                IClientConfigKey key = IClientConfigKey.Keys.valueOf(entry.getKey());
+                String value = entry.getValue();
+
+                LOGGER.debug("RibbonClientConfig: {}={}", key.key(), value);
+                config.set(key, value);
+            }
+        }
+
+        return new ZoneAwareLoadBalancer<>(
+            config,
+            configuration.getRuleOrDefault(RoundRobinRule::new),
+            configuration.getPingOrDefault(DummyPing::new),
+            new RibbonServerList(serviceName, serviceDiscovery),
+            new RibbonServerFilter(serviceFilter),
+            new PollingServerListUpdater(config));
+    }
+
+    static final class RibbonServerList implements ServerList<RibbonServiceDefinition>  {
+        private final String serviceName;
+        private final ServiceDiscovery serviceDiscovery;
+
+        RibbonServerList(String serviceName, ServiceDiscovery serviceDiscovery) {
+            this.serviceName = serviceName;
+            this.serviceDiscovery = serviceDiscovery;
+        }
+
+        @Override
+        public List<RibbonServiceDefinition> getInitialListOfServers() {
+            return asRibbonServerList(
+                serviceDiscovery.getInitialListOfServices(serviceName)
+            );
+        }
+
+        @Override
+        public List<RibbonServiceDefinition> getUpdatedListOfServers() {
+            return asRibbonServerList(
+                serviceDiscovery.getUpdatedListOfServices(serviceName)
+            );
+        }
+
+        private List<RibbonServiceDefinition> asRibbonServerList(List<ServiceDefinition> services) {
+            List<RibbonServiceDefinition> ribbonServers = new ArrayList<>();
+
+            for (ServiceDefinition service : services) {
+                if (service instanceof RibbonServiceDefinition) {
+                    ribbonServers.add((RibbonServiceDefinition)service);
+                } else {
+                    RibbonServiceDefinition serviceDef = new RibbonServiceDefinition(
+                        serviceName,
+                        service.getHost(),
+                        service.getPort(),
+                        service.getHealth()
+                    );
+
+                    String zone = serviceDef.getMetadata().get("zone");
+                    if (zone != null) {
+                        serviceDef.setZone(zone);
+                    }
+
+                    ribbonServers.add(serviceDef);
+                }
+            }
+
+            return ribbonServers;
+        }
+    }
+
+    static final class RibbonServerFilter implements ServerListFilter<RibbonServiceDefinition> {
+        private final ServiceFilter serviceFilter;
+
+        RibbonServerFilter(ServiceFilter serviceFilter) {
+            this.serviceFilter = serviceFilter;
+        }
+
+        public List<RibbonServiceDefinition> getFilteredListOfServers(List<RibbonServiceDefinition> servers) {
+            return serviceFilter.apply(servers);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/components/camel-ribbon/src/main/java/org/apache/camel/component/ribbon/cloud/RibbonLoadBalancerFactory.java
----------------------------------------------------------------------
diff --git a/components/camel-ribbon/src/main/java/org/apache/camel/component/ribbon/cloud/RibbonLoadBalancerFactory.java b/components/camel-ribbon/src/main/java/org/apache/camel/component/ribbon/cloud/RibbonLoadBalancerFactory.java
new file mode 100644
index 0000000..86874f0
--- /dev/null
+++ b/components/camel-ribbon/src/main/java/org/apache/camel/component/ribbon/cloud/RibbonLoadBalancerFactory.java
@@ -0,0 +1,61 @@
+/**
+ * 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.ribbon.cloud;
+
+import java.util.Map;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.cloud.LoadBalancer;
+import org.apache.camel.cloud.LoadBalancerFactory;
+import org.apache.camel.component.ribbon.RibbonConfiguration;
+
+public class RibbonLoadBalancerFactory implements LoadBalancerFactory {
+    private final RibbonConfiguration configuration;
+
+    public RibbonLoadBalancerFactory() {
+        this.configuration = new RibbonConfiguration();
+    }
+
+    // *************************************************************************
+    // Properties
+    // *************************************************************************
+
+    public String getClientName() {
+        return configuration.getClientName();
+    }
+
+    public void setClientName(String clientName) {
+        configuration.setClientName(clientName);
+    }
+
+    public Map<String, String> getProperies() {
+        return configuration.getClientConfig();
+    }
+
+    public void setProperties(Map<String, String> clientConfig) {
+        configuration.setClientConfig(clientConfig);
+    }
+
+    // *************************************************************************
+    // Factory
+    // *************************************************************************
+
+    @Override
+    public LoadBalancer newInstance(CamelContext camelContext) throws Exception {
+        return new RibbonLoadBalancer(configuration);
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/components/camel-ribbon/src/main/java/org/apache/camel/component/ribbon/cloud/RibbonServiceDefinition.java
----------------------------------------------------------------------
diff --git a/components/camel-ribbon/src/main/java/org/apache/camel/component/ribbon/cloud/RibbonServiceDefinition.java b/components/camel-ribbon/src/main/java/org/apache/camel/component/ribbon/cloud/RibbonServiceDefinition.java
new file mode 100644
index 0000000..d9d5772
--- /dev/null
+++ b/components/camel-ribbon/src/main/java/org/apache/camel/component/ribbon/cloud/RibbonServiceDefinition.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.ribbon.cloud;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import com.netflix.loadbalancer.Server;
+import org.apache.camel.cloud.ServiceDefinition;
+import org.apache.camel.cloud.ServiceHealth;
+import org.apache.camel.impl.cloud.DefaultServiceHealth;
+import org.apache.camel.util.ObjectHelper;
+
+public class RibbonServiceDefinition extends Server implements ServiceDefinition {
+    private String name;
+    private ServiceHealth health;
+
+    public RibbonServiceDefinition(String name, String host, int port) {
+        this(name, host, port, DefaultServiceHealth.INSTANCE);
+    }
+
+    public RibbonServiceDefinition(String name, String host, int port, ServiceHealth healt) {
+        super(host, port);
+        this.name = name;
+        this.health = healt;
+    }
+
+    @Override
+    public String getName() {
+        return name;
+    }
+
+    @Override
+    public String getHost() {
+        return super.getHost();
+    }
+
+    @Override
+    public int getPort() {
+        return super.getPort();
+    }
+
+    @Override
+    public ServiceHealth getHealth() {
+        return health;
+    }
+
+    @Override
+    public Map<String, String> getMetadata() {
+        Map<String, String> meta = new HashMap<>();
+        ObjectHelper.ifNotEmpty(super.getId(), val -> meta.put("id", val));
+        ObjectHelper.ifNotEmpty(super.getZone(), val -> meta.put("zone", val));
+        ObjectHelper.ifNotEmpty(super.isAlive(), val -> meta.put("is_alive", Boolean.toString(val)));
+        ObjectHelper.ifNotEmpty(super.isReadyToServe(), val -> meta.put("ready_to_server", Boolean.toString(val)));
+
+        return Collections.unmodifiableMap(meta);
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/components/camel-ribbon/src/main/java/org/apache/camel/component/ribbon/processor/RibbonProcessorFactory.java
----------------------------------------------------------------------
diff --git a/components/camel-ribbon/src/main/java/org/apache/camel/component/ribbon/processor/RibbonProcessorFactory.java b/components/camel-ribbon/src/main/java/org/apache/camel/component/ribbon/processor/RibbonProcessorFactory.java
deleted file mode 100644
index 00e9c52..0000000
--- a/components/camel-ribbon/src/main/java/org/apache/camel/component/ribbon/processor/RibbonProcessorFactory.java
+++ /dev/null
@@ -1,181 +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.ribbon.processor;
-
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Set;
-
-import com.netflix.loadbalancer.IRule;
-import org.apache.camel.ExchangePattern;
-import org.apache.camel.Processor;
-import org.apache.camel.component.ribbon.RibbonConfiguration;
-import org.apache.camel.impl.remote.DefaultServiceCallProcessorFactory;
-import org.apache.camel.model.remote.RibbonConfigurationDefinition;
-import org.apache.camel.model.remote.ServiceCallConfigurationDefinition;
-import org.apache.camel.model.remote.ServiceCallDefinition;
-import org.apache.camel.spi.ProcessorFactory;
-import org.apache.camel.spi.RouteContext;
-import org.apache.camel.spi.ServiceCallServerListStrategy;
-import org.apache.camel.util.CamelContextHelper;
-import org.apache.camel.util.IntrospectionSupport;
-
-/**
- * {@link ProcessorFactory} that creates the Ribbon implementation of the ServiceCall EIP.
- */
-public class RibbonProcessorFactory extends DefaultServiceCallProcessorFactory<RibbonConfiguration, RibbonServer> {
-
-
-    @Override
-    protected Processor createProcessor(RouteContext routeContext, ServiceCallDefinition definition, RibbonConfiguration cfg) throws Exception {
-        String name = definition.getName();
-        String uri = definition.getUri();
-        ExchangePattern mep = definition.getPattern();
-
-        RibbonConfigurationDefinition config = (RibbonConfigurationDefinition) definition.getServiceCallConfiguration();
-        RibbonConfigurationDefinition configRef = null;
-        if (definition.getServiceCallConfigurationRef() != null) {
-            // lookup in registry first
-            configRef = CamelContextHelper.lookup(routeContext.getCamelContext(), definition.getServiceCallConfigurationRef(), RibbonConfigurationDefinition.class);
-            if (configRef == null) {
-                // and fallback as service configuration
-                routeContext.getCamelContext().getServiceCallConfiguration(definition.getServiceCallConfigurationRef(), RibbonConfigurationDefinition.class);
-            }
-        }
-
-        // if no configuration explicit configured then use default
-        if (config == null && configRef == null) {
-            config = routeContext.getCamelContext().getServiceCallConfiguration(null, RibbonConfigurationDefinition.class);
-        }
-        if (config == null) {
-            // if no default then try to find if there configuration in the registry of the given type
-            Set<RibbonConfigurationDefinition> set = routeContext.getCamelContext().getRegistry().findByType(RibbonConfigurationDefinition.class);
-            if (set.size() == 1) {
-                config = set.iterator().next();
-            }
-        }
-
-        if (config == null && configRef == null) {
-            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);
-        }
-
-        // and set them on the kubernetes configuration class
-        IntrospectionSupport.setProperties(cfg, parameters);
-
-        // lookup the load balancer to use (configured on EIP takes precedence vs configured on configuration)
-        Object lb = configureLoadBalancer(routeContext, definition);
-        if (lb == null && config != null) {
-            lb = configureLoadBalancer(routeContext, config);
-        }
-        if (lb == null && configRef != null) {
-            lb = configureLoadBalancer(routeContext, configRef);
-        }
-
-        // lookup the server list strategy to use (configured on EIP takes precedence vs configured on configuration)
-        ServiceCallServerListStrategy sl = configureServerListStrategy(routeContext, definition);
-        if (sl == null && config != null) {
-            sl = configureServerListStrategy(routeContext, config);
-        }
-        if (sl == null && configRef != null) {
-            sl = configureServerListStrategy(routeContext, configRef);
-        }
-
-        // must be a ribbon load balancer
-        if (lb != null && !(lb instanceof IRule)) {
-            throw new IllegalArgumentException("Load balancer must be of type: " + IRule.class + " but is of type: " + lb.getClass().getName());
-        }
-
-        // The component is used to configure what the default scheme to use (eg camel component name).
-        // The component configured on EIP takes precedence vs configured on configuration.
-        String component = definition.getComponent();
-        if (component == null) {
-            component = config != null ? config.getComponent() : null;
-            if (component == null && configRef != null) {
-                component = configRef.getComponent();
-            }
-        }
-
-        Map<String, String> properties = configureProperties(routeContext, config, configRef);
-
-        RibbonServiceCallProcessor processor = new RibbonServiceCallProcessor(name, uri, component, mep, cfg);
-        processor.setRule((IRule) lb);
-        processor.setServerListStrategy(sl);
-        processor.setRibbonClientConfig(properties);
-        return processor;
-    }
-
-    @Override
-    protected RibbonConfiguration createConfiguration(RouteContext routeContext) throws Exception {
-        return new RibbonConfiguration();
-    }
-
-    private Object configureLoadBalancer(RouteContext routeContext, ServiceCallDefinition sd) {
-        Object lb = null;
-
-        if (sd != null) {
-            lb = sd.getLoadBalancer();
-            if (lb == null && sd.getLoadBalancerRef() != null) {
-                String ref = sd.getLoadBalancerRef();
-                lb = CamelContextHelper.mandatoryLookup(routeContext.getCamelContext(), ref);
-            }
-        }
-
-        return lb;
-    }
-
-    private Object configureLoadBalancer(RouteContext routeContext, ServiceCallConfigurationDefinition config) {
-        Object lb = config.getLoadBalancer();
-        if (lb == null && config.getLoadBalancerRef() != null) {
-            String ref = config.getLoadBalancerRef();
-            lb = CamelContextHelper.mandatoryLookup(routeContext.getCamelContext(), ref);
-        }
-        return lb;
-    }
-
-    private ServiceCallServerListStrategy configureServerListStrategy(RouteContext routeContext, ServiceCallDefinition sd) {
-        ServiceCallServerListStrategy lb = null;
-
-        if (sd != null) {
-            lb = sd.getServerListStrategy();
-            if (lb == null && sd.getServerListStrategyRef() != null) {
-                lb = CamelContextHelper.mandatoryLookup(routeContext.getCamelContext(), sd.getServerListStrategyRef(), ServiceCallServerListStrategy.class);
-            }
-        }
-
-        return lb;
-    }
-
-    private ServiceCallServerListStrategy configureServerListStrategy(RouteContext routeContext, ServiceCallConfigurationDefinition config) {
-        ServiceCallServerListStrategy lb = config.getServerListStrategy();
-        if (lb == null && config.getServerListStrategyRef() != null) {
-            String ref = config.getServerListStrategyRef();
-            lb = CamelContextHelper.mandatoryLookup(routeContext.getCamelContext(), ref, ServiceCallServerListStrategy.class);
-        }
-        return lb;
-    }
-
-}
-

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/components/camel-ribbon/src/main/java/org/apache/camel/component/ribbon/processor/RibbonServer.java
----------------------------------------------------------------------
diff --git a/components/camel-ribbon/src/main/java/org/apache/camel/component/ribbon/processor/RibbonServer.java b/components/camel-ribbon/src/main/java/org/apache/camel/component/ribbon/processor/RibbonServer.java
deleted file mode 100644
index d30d656..0000000
--- a/components/camel-ribbon/src/main/java/org/apache/camel/component/ribbon/processor/RibbonServer.java
+++ /dev/null
@@ -1,59 +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.ribbon.processor;
-
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Map;
-
-import com.netflix.loadbalancer.Server;
-import org.apache.camel.spi.ServiceCallServer;
-
-import static org.apache.camel.util.ObjectHelper.ifNotEmpty;
-
-public class RibbonServer extends Server implements ServiceCallServer {
-
-    public RibbonServer(String host, int port) {
-        super(host, port);
-    }
-
-    @Override
-    public String getIp() {
-        return super.getHost();
-    }
-
-    @Override
-    public int getPort() {
-        return super.getPort();
-    }
-
-    @Override
-    public Map<String, String> getMetadata() {
-        Map<String, String> meta = new HashMap<>();
-        ifNotEmpty(super.getId(), val -> meta.put("id", val));
-        ifNotEmpty(super.getZone(), val -> meta.put("zone", val));
-
-        if (super.getMetaInfo() != null) {
-            ifNotEmpty(super.getMetaInfo().getAppName(), val -> meta.put("app_name", val));
-            ifNotEmpty(super.getMetaInfo().getServiceIdForDiscovery(),  val -> meta.put("discovery_id", val));
-            ifNotEmpty(super.getMetaInfo().getInstanceId(),  val -> meta.put("instance_id", val));
-            ifNotEmpty(super.getMetaInfo().getServerGroup(), val -> meta.put("server_group", val));
-        }
-
-        return Collections.unmodifiableMap(meta);
-    }
-}

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/components/camel-ribbon/src/main/java/org/apache/camel/component/ribbon/processor/RibbonServiceCallProcessor.java
----------------------------------------------------------------------
diff --git a/components/camel-ribbon/src/main/java/org/apache/camel/component/ribbon/processor/RibbonServiceCallProcessor.java b/components/camel-ribbon/src/main/java/org/apache/camel/component/ribbon/processor/RibbonServiceCallProcessor.java
deleted file mode 100644
index f701ba0..0000000
--- a/components/camel-ribbon/src/main/java/org/apache/camel/component/ribbon/processor/RibbonServiceCallProcessor.java
+++ /dev/null
@@ -1,250 +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.ribbon.processor;
-
-import java.util.Map;
-import java.util.concurrent.RejectedExecutionException;
-
-import com.netflix.client.config.IClientConfig;
-import com.netflix.client.config.IClientConfigKey;
-import com.netflix.loadbalancer.DummyPing;
-import com.netflix.loadbalancer.IPing;
-import com.netflix.loadbalancer.IRule;
-import com.netflix.loadbalancer.PollingServerListUpdater;
-import com.netflix.loadbalancer.RoundRobinRule;
-import com.netflix.loadbalancer.Server;
-import com.netflix.loadbalancer.ServerList;
-import com.netflix.loadbalancer.ServerListUpdater;
-import com.netflix.loadbalancer.ZoneAwareLoadBalancer;
-import org.apache.camel.AsyncCallback;
-import org.apache.camel.AsyncProcessor;
-import org.apache.camel.CamelContext;
-import org.apache.camel.CamelContextAware;
-import org.apache.camel.Exchange;
-import org.apache.camel.ExchangePattern;
-import org.apache.camel.Traceable;
-import org.apache.camel.component.ribbon.RibbonConfiguration;
-import org.apache.camel.impl.remote.DefaultServiceCallExpression;
-import org.apache.camel.impl.remote.ServiceCallConstants;
-import org.apache.camel.processor.SendDynamicProcessor;
-import org.apache.camel.spi.IdAware;
-import org.apache.camel.spi.ServiceCallServerListStrategy;
-import org.apache.camel.support.ServiceSupport;
-import org.apache.camel.util.AsyncProcessorHelper;
-import org.apache.camel.util.ServiceHelper;
-import org.apache.camel.util.StringHelper;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * Ribbon based implementation of the the ServiceCall EIP.
- */
-public class RibbonServiceCallProcessor extends ServiceSupport implements AsyncProcessor, CamelContextAware, Traceable, IdAware {
-
-    private static final Logger LOG = LoggerFactory.getLogger(RibbonServiceCallProcessor.class);
-
-    private CamelContext camelContext;
-    private String id;
-    private final String name;
-    private final String scheme;
-    private final String contextPath;
-    private final String uri;
-    private final ExchangePattern exchangePattern;
-    private final RibbonConfiguration configuration;
-    private ServiceCallServerListStrategy<RibbonServer> serverListStrategy;
-    private ZoneAwareLoadBalancer<RibbonServer> ribbonLoadBalancer;
-    private IRule rule;
-    private IPing ping;
-    private final DefaultServiceCallExpression serviceCallExpression;
-    private Map<String, String> ribbonClientConfig;
-    private SendDynamicProcessor processor;
-
-    public RibbonServiceCallProcessor(String name, String uri, String scheme, ExchangePattern exchangePattern, RibbonConfiguration configuration) {
-        // setup from the provided name which can contain scheme and context-path information as well
-        String serviceName;
-        if (name.contains("/")) {
-            serviceName = StringHelper.before(name, "/");
-            this.contextPath = StringHelper.after(name, "/");
-        } else if (name.contains("?")) {
-            serviceName = StringHelper.before(name, "?");
-            this.contextPath = StringHelper.after(name, "?");
-        } else {
-            serviceName = name;
-            this.contextPath = null;
-        }
-        if (serviceName.contains(":")) {
-            this.scheme = StringHelper.before(serviceName, ":");
-            this.name = StringHelper.after(serviceName, ":");
-        } else {
-            this.scheme = scheme;
-            this.name = serviceName;
-        }
-
-        this.uri = uri;
-        this.exchangePattern = exchangePattern;
-        this.configuration = configuration;
-        this.rule = configuration.getRule();
-        this.ping = configuration.getPing();
-        this.serviceCallExpression = new DefaultServiceCallExpression(this.name, this.scheme, this.contextPath, this.uri);
-    }
-
-    @Override
-    public void process(Exchange exchange) throws Exception {
-        AsyncProcessorHelper.process(this, exchange);
-    }
-
-    @Override
-    public boolean process(Exchange exchange, AsyncCallback callback) {
-        Server server = null;
-        try {
-            // let the client load balancer chose which server to use
-            server = ribbonLoadBalancer.chooseServer();
-            if (server == null) {
-                exchange.setException(new RejectedExecutionException("No active services with name " + name));
-            }
-        } catch (Throwable e) {
-            exchange.setException(e);
-        }
-
-        if (exchange.getException() != null) {
-            callback.done(true);
-            return true;
-        }
-
-        String ip = server.getHost();
-        int port = server.getPort();
-        LOG.debug("Service {} active at server: {}:{}", name, ip, port);
-
-        // set selected server as header
-        exchange.getIn().setHeader(ServiceCallConstants.SERVER_IP, ip);
-        exchange.getIn().setHeader(ServiceCallConstants.SERVER_PORT, port);
-        exchange.getIn().setHeader(ServiceCallConstants.SERVICE_NAME, name);
-
-        // use the dynamic send processor to call the service
-        return processor.process(exchange, callback);
-    }
-
-    @Override
-    public CamelContext getCamelContext() {
-        return camelContext;
-    }
-
-    @Override
-    public void setCamelContext(CamelContext camelContext) {
-        this.camelContext = camelContext;
-    }
-
-    @Override
-    public String getId() {
-        return id;
-    }
-
-    @Override
-    public void setId(String id) {
-        this.id = id;
-    }
-
-    @Override
-    public String getTraceLabel() {
-        return "kubernetes";
-    }
-
-    public ServiceCallServerListStrategy getServerListStrategy() {
-        return serverListStrategy;
-    }
-
-    public void setServerListStrategy(ServiceCallServerListStrategy serverListStrategy) {
-        this.serverListStrategy = serverListStrategy;
-    }
-
-    public IRule getRule() {
-        return rule;
-    }
-
-    public void setRule(IRule rule) {
-        this.rule = rule;
-    }
-
-    public IPing getPing() {
-        return ping;
-    }
-
-    public void setPing(IPing ping) {
-        this.ping = ping;
-    }
-
-    public Map<String, String> getRibbonClientConfig() {
-        return ribbonClientConfig;
-    }
-
-    public void setRibbonClientConfig(Map<String, String> ribbonClientConfig) {
-        this.ribbonClientConfig = ribbonClientConfig;
-    }
-
-    @Override
-    @SuppressWarnings("unchecked")
-    protected void doStart() throws Exception {
-        StringHelper.notEmpty(name, "name", this);
-
-        if (serverListStrategy == null) {
-            serverListStrategy = new RibbonServiceCallStaticServerListStrategy();
-        }
-
-        if (!(serverListStrategy instanceof ServerList)) {
-            throw new IllegalArgumentException("ServerListStrategy must be instanceof com.netflix.loadbalancer.ServerList but is of type: " + serverListStrategy.getClass().getName());
-        }
-
-        if (rule == null) {
-            // use round robin rule by default
-            rule = new RoundRobinRule();
-        }
-        if (ping == null) {
-            // use dummy ping by default
-            ping = new DummyPing();
-        }
-
-        // setup client config
-        IClientConfig config = IClientConfig.Builder.newBuilder(name).build();
-        if (ribbonClientConfig != null) {
-            for (Map.Entry<String, String> entry : ribbonClientConfig.entrySet()) {
-                IClientConfigKey key = IClientConfigKey.Keys.valueOf(entry.getKey());
-                String value = entry.getValue();
-                LOG.debug("RibbonClientConfig: {}={}", key.key(), value);
-                config.set(key, entry.getValue());
-            }
-        }
-
-        ServerListUpdater updater = new PollingServerListUpdater(config);
-        ribbonLoadBalancer = new ZoneAwareLoadBalancer<>(config, rule, ping, (ServerList<RibbonServer>) serverListStrategy, null, updater);
-
-        LOG.info("RibbonServiceCall with service name: {} is using load balancer: {} and server list: {}", name, ribbonLoadBalancer, serverListStrategy);
-
-        processor = new SendDynamicProcessor(uri, serviceCallExpression);
-        processor.setCamelContext(getCamelContext());
-        if (exchangePattern != null) {
-            processor.setPattern(exchangePattern);
-        }
-        ServiceHelper.startServices(serverListStrategy, processor);
-    }
-
-    @Override
-    protected void doStop() throws Exception {
-        ServiceHelper.stopServices(processor, serverListStrategy);
-    }
-
-}
-

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/components/camel-ribbon/src/main/java/org/apache/camel/component/ribbon/processor/RibbonServiceCallStaticServerListStrategy.java
----------------------------------------------------------------------
diff --git a/components/camel-ribbon/src/main/java/org/apache/camel/component/ribbon/processor/RibbonServiceCallStaticServerListStrategy.java b/components/camel-ribbon/src/main/java/org/apache/camel/component/ribbon/processor/RibbonServiceCallStaticServerListStrategy.java
deleted file mode 100644
index 6188e6d..0000000
--- a/components/camel-ribbon/src/main/java/org/apache/camel/component/ribbon/processor/RibbonServiceCallStaticServerListStrategy.java
+++ /dev/null
@@ -1,108 +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.ribbon.processor;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import com.netflix.client.config.IClientConfig;
-import com.netflix.loadbalancer.AbstractServerList;
-import com.netflix.loadbalancer.ServerList;
-import org.apache.camel.spi.ServiceCallServerListStrategy;
-import org.apache.camel.util.ObjectHelper;
-
-/**
- * A static list of known servers to be used by the Ribbon load balancer with the Camel Service Call EIP.
- * <p/>
- * You can implement custom implementations by existing this class and override the {@link #getUpdatedListOfServers()} that is called by Ribbon to refresh the known list
- * of servers. For example to periodically query a remote server registry for a list of active servers.
- */
-public class RibbonServiceCallStaticServerListStrategy extends AbstractServerList<RibbonServer> implements ServerList<RibbonServer>, ServiceCallServerListStrategy<RibbonServer> {
-
-    private IClientConfig clientConfig;
-    private final List<RibbonServer> servers = new ArrayList<>();
-
-    public RibbonServiceCallStaticServerListStrategy() {
-    }
-
-    public RibbonServiceCallStaticServerListStrategy(List<RibbonServer> servers) {
-        this.servers.addAll(servers);
-    }
-
-    /**
-     * Build a {@link RibbonServiceCallStaticServerListStrategy} with the initial list of servers
-     *
-     * @param servers servers separated by comma in the format: host:port,host2:port,host3:port and so on.
-     */
-    public static RibbonServiceCallStaticServerListStrategy build(String servers) {
-        RibbonServiceCallStaticServerListStrategy answer = new RibbonServiceCallStaticServerListStrategy();
-        String[] parts = servers.split(",");
-        for (String part : parts) {
-            String host = ObjectHelper.before(part, ":");
-            String port = ObjectHelper.after(part, ":");
-            int num = Integer.valueOf(port);
-            answer.addServer(host, num);
-        }
-        return answer;
-    }
-
-    /**
-     * Add a server to the known list of servers.
-     */
-    public void addServer(RibbonServer server) {
-        servers.add(server);
-    }
-
-    /**
-     * Add a server to the known list of servers.
-     */
-    public void addServer(String host, int port) {
-        servers.add(new RibbonServer(host, port));
-    }
-
-    /**
-     * Remove an existing server from the list of known servers.
-     */
-    public void removeServer(String host, int port) {
-        servers.remove(new RibbonServer(host, port));
-    }
-
-    @Override
-    public void initWithNiwsConfig(IClientConfig clientConfig) {
-        this.clientConfig = clientConfig;
-    }
-
-    @Override
-    public List<RibbonServer> getInitialListOfServers() {
-        return servers;
-    }
-
-    @Override
-    public List<RibbonServer> getUpdatedListOfServers() {
-        return servers;
-    }
-
-    @Override
-    public List<RibbonServer> getInitialListOfServers(String name) {
-        return getInitialListOfServers();
-    }
-
-    @Override
-    public List<RibbonServer> getUpdatedListOfServers(String name) {
-        return getUpdatedListOfServers();
-    }
-}

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/components/camel-ribbon/src/main/resources/META-INF/services/org/apache/camel/cloud/ribbon-load-balancer
----------------------------------------------------------------------
diff --git a/components/camel-ribbon/src/main/resources/META-INF/services/org/apache/camel/cloud/ribbon-load-balancer b/components/camel-ribbon/src/main/resources/META-INF/services/org/apache/camel/cloud/ribbon-load-balancer
new file mode 100644
index 0000000..161ac23
--- /dev/null
+++ b/components/camel-ribbon/src/main/resources/META-INF/services/org/apache/camel/cloud/ribbon-load-balancer
@@ -0,0 +1,17 @@
+#
+# 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.ribbon.cloud.RibbonLoadBalancerFactory

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/components/camel-ribbon/src/main/resources/META-INF/services/org/apache/camel/model/ServiceCallDefinition
----------------------------------------------------------------------
diff --git a/components/camel-ribbon/src/main/resources/META-INF/services/org/apache/camel/model/ServiceCallDefinition b/components/camel-ribbon/src/main/resources/META-INF/services/org/apache/camel/model/ServiceCallDefinition
deleted file mode 100644
index 5642951..0000000
--- a/components/camel-ribbon/src/main/resources/META-INF/services/org/apache/camel/model/ServiceCallDefinition
+++ /dev/null
@@ -1,18 +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.
-#
-
-class=org.apache.camel.component.ribbon.processor.RibbonProcessorFactory

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/components/camel-ribbon/src/test/java/org/apache/camel/component/ribbon/cloud/RibbonServerListTest.java
----------------------------------------------------------------------
diff --git a/components/camel-ribbon/src/test/java/org/apache/camel/component/ribbon/cloud/RibbonServerListTest.java b/components/camel-ribbon/src/test/java/org/apache/camel/component/ribbon/cloud/RibbonServerListTest.java
new file mode 100644
index 0000000..fcc4f6b
--- /dev/null
+++ b/components/camel-ribbon/src/test/java/org/apache/camel/component/ribbon/cloud/RibbonServerListTest.java
@@ -0,0 +1,56 @@
+/**
+ * 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.ribbon.cloud;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import com.netflix.loadbalancer.LoadBalancerBuilder;
+import com.netflix.loadbalancer.RoundRobinRule;
+import com.netflix.loadbalancer.Server;
+import com.netflix.loadbalancer.ZoneAwareLoadBalancer;
+import org.apache.camel.cloud.ServiceDefinition;
+import org.apache.camel.cloud.ServiceDiscovery;
+import org.apache.camel.impl.cloud.StaticServiceDiscovery;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+
+public class RibbonServerListTest {
+    @Test
+    public void testFixedServerList() throws Exception {
+        List<ServiceDefinition> servers = new ArrayList<>();
+        servers.add(new RibbonServiceDefinition("unknown", "localhost", 9090));
+        servers.add(new RibbonServiceDefinition("unknown", "localhost", 9091));
+
+        ServiceDiscovery list = new StaticServiceDiscovery(servers);
+
+        ZoneAwareLoadBalancer<RibbonServiceDefinition> lb = LoadBalancerBuilder.<RibbonServiceDefinition>newBuilder()
+            .withDynamicServerList(new RibbonLoadBalancer.RibbonServerList("unknown", list))
+            .withRule(new RoundRobinRule())
+            .buildDynamicServerListLoadBalancer();
+
+        Server server = lb.chooseServer();
+        assertEquals("localhost", server.getHost());
+        assertEquals(9091, server.getPort());
+
+        server = lb.chooseServer();
+        assertEquals("localhost", server.getHost());
+        assertEquals(9090, server.getPort());
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/components/camel-ribbon/src/test/java/org/apache/camel/component/ribbon/cloud/RibbonServiceCallRegistryRouteTest.java
----------------------------------------------------------------------
diff --git a/components/camel-ribbon/src/test/java/org/apache/camel/component/ribbon/cloud/RibbonServiceCallRegistryRouteTest.java b/components/camel-ribbon/src/test/java/org/apache/camel/component/ribbon/cloud/RibbonServiceCallRegistryRouteTest.java
new file mode 100644
index 0000000..7f95639
--- /dev/null
+++ b/components/camel-ribbon/src/test/java/org/apache/camel/component/ribbon/cloud/RibbonServiceCallRegistryRouteTest.java
@@ -0,0 +1,61 @@
+/**
+ * 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.ribbon.cloud;
+
+import org.apache.camel.RoutesBuilder;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.ribbon.RibbonConfiguration;
+import org.apache.camel.impl.cloud.StaticServiceDiscovery;
+import org.apache.camel.model.cloud.ServiceCallConfigurationDefinition;
+
+public class RibbonServiceCallRegistryRouteTest extends RibbonServiceCallRouteTest {
+    @Override
+    protected RoutesBuilder createRouteBuilder() throws Exception {
+        return new RouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                // setup a static ribbon server list with these 2 servers to start with
+                StaticServiceDiscovery servers = new StaticServiceDiscovery();
+                servers.addServer("localhost", 9090);
+                servers.addServer("localhost", 9091);
+
+                RibbonConfiguration configuration = new RibbonConfiguration();
+                RibbonLoadBalancer loadBalancer = new RibbonLoadBalancer(configuration);
+
+                // configure camel service call
+                ServiceCallConfigurationDefinition config = new ServiceCallConfigurationDefinition();
+                config.setLoadBalancer(loadBalancer);
+                config.setServiceDiscovery(servers);
+
+                // register configuration
+                context.setServiceCallConfiguration(config);
+
+                from("direct:start")
+                    .serviceCall("myService")
+                    .to("mock:result");
+                from("jetty:http://localhost:9090")
+                    .to("mock:9090")
+                    .transform().constant("9090");
+                from("jetty:http://localhost:9091")
+                    .to("mock:9091")
+                    .transform().constant("9091");
+            }
+        };
+    }
+}
+

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/components/camel-ribbon/src/test/java/org/apache/camel/component/ribbon/cloud/RibbonServiceCallRouteTest.java
----------------------------------------------------------------------
diff --git a/components/camel-ribbon/src/test/java/org/apache/camel/component/ribbon/cloud/RibbonServiceCallRouteTest.java b/components/camel-ribbon/src/test/java/org/apache/camel/component/ribbon/cloud/RibbonServiceCallRouteTest.java
new file mode 100644
index 0000000..6bda099
--- /dev/null
+++ b/components/camel-ribbon/src/test/java/org/apache/camel/component/ribbon/cloud/RibbonServiceCallRouteTest.java
@@ -0,0 +1,72 @@
+/**
+ * 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.ribbon.cloud;
+
+import org.apache.camel.RoutesBuilder;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.ribbon.RibbonConfiguration;
+import org.apache.camel.impl.cloud.StaticServiceDiscovery;
+import org.apache.camel.test.junit4.CamelTestSupport;
+import org.junit.Test;
+
+public class RibbonServiceCallRouteTest extends CamelTestSupport {
+    @Test
+    public void testServiceCall() throws Exception {
+        getMockEndpoint("mock:9090").expectedMessageCount(1);
+        getMockEndpoint("mock:9091").expectedMessageCount(1);
+        getMockEndpoint("mock:result").expectedMessageCount(2);
+
+        String out = template.requestBody("direct:start", null, String.class);
+        String out2 = template.requestBody("direct:start", null, String.class);
+        assertEquals("9091", out);
+        assertEquals("9090", out2);
+
+        assertMockEndpointsSatisfied();
+    }
+
+    @Override
+    protected RoutesBuilder createRouteBuilder() throws Exception {
+        return new RouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                // setup a static ribbon server list with these 2 servers to start with
+                StaticServiceDiscovery servers = new StaticServiceDiscovery();
+                servers.addServer("localhost", 9090);
+                servers.addServer("localhost", 9091);
+
+                RibbonConfiguration configuration = new RibbonConfiguration();
+                RibbonLoadBalancer loadBalancer = new RibbonLoadBalancer(configuration);
+
+                from("direct:start")
+                    .serviceCall()
+                        .name("myService")
+                        .loadBalancer(loadBalancer)
+                        .serviceDiscovery(servers)
+                        .end()
+                    .to("mock:result");
+                from("jetty:http://localhost:9090")
+                    .to("mock:9090")
+                    .transform().constant("9090");
+                from("jetty:http://localhost:9091")
+                    .to("mock:9091")
+                    .transform().constant("9091");
+            }
+        };
+    }
+}
+

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/components/camel-ribbon/src/test/java/org/apache/camel/component/ribbon/cloud/RibbonServiceCallUpdateRouteTest.java
----------------------------------------------------------------------
diff --git a/components/camel-ribbon/src/test/java/org/apache/camel/component/ribbon/cloud/RibbonServiceCallUpdateRouteTest.java b/components/camel-ribbon/src/test/java/org/apache/camel/component/ribbon/cloud/RibbonServiceCallUpdateRouteTest.java
new file mode 100644
index 0000000..c00f1c7
--- /dev/null
+++ b/components/camel-ribbon/src/test/java/org/apache/camel/component/ribbon/cloud/RibbonServiceCallUpdateRouteTest.java
@@ -0,0 +1,99 @@
+/**
+ * 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.ribbon.cloud;
+
+import java.util.Collections;
+
+import org.apache.camel.RoutesBuilder;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.ribbon.RibbonConfiguration;
+import org.apache.camel.impl.cloud.StaticServiceDiscovery;
+import org.apache.camel.test.junit4.CamelTestSupport;
+import org.junit.Test;
+
+public class RibbonServiceCallUpdateRouteTest extends CamelTestSupport {
+    private final StaticServiceDiscovery servers = new StaticServiceDiscovery();
+
+    @Override
+    public void setUp() throws Exception {
+        // setup a static ribbon server list with these 2 servers to start with
+        servers.addServer("localhost", 9090);
+        servers.addServer("localhost", 9091);
+
+        super.setUp();
+    }
+
+    @Test
+    public void testServiceCall() throws Exception {
+        getMockEndpoint("mock:9090").expectedMessageCount(1);
+        getMockEndpoint("mock:9091").expectedMessageCount(1);
+        getMockEndpoint("mock:result").expectedMessageCount(2);
+
+        String out = template.requestBody("direct:start", null, String.class);
+        String out2 = template.requestBody("direct:start", null, String.class);
+        assertEquals("9091", out);
+        assertEquals("9090", out2);
+
+        assertMockEndpointsSatisfied();
+
+        // stop the first server and remove it from the known list of servers
+        context.stopRoute("9090");
+        servers.removeServer("localhost", 9090);
+
+        // call the other active server
+        String out3 = template.requestBody("direct:start", null, String.class);
+        assertEquals("9091", out3);
+
+        // sleep a bit to make the server updated run and detect that a server is no longer in the list
+        log.debug("Sleeping to all the server list updated to run");
+        Thread.sleep(1000);
+        log.debug("Calling the service now");
+
+        // call again and it should call 9091 as its the only active server
+        String out4 = template.requestBody("direct:start", null, String.class);
+        assertEquals("9091", out4);
+    }
+
+    @Override
+    protected RoutesBuilder createRouteBuilder() throws Exception {
+        return new RouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                RibbonConfiguration configuration = new RibbonConfiguration();
+                // lets update quick so we do not have to sleep so much in the tests
+                configuration.setClientConfig(Collections.singletonMap("ServerListRefreshInterval", "250"));
+                RibbonLoadBalancer loadBalancer = new RibbonLoadBalancer(configuration);
+
+                from("direct:start")
+                    .serviceCall()
+                        .name("myService")
+                        .loadBalancer(loadBalancer)
+                        .serviceDiscovery(servers)
+                        .end()
+                    .to("mock:result");
+                from("jetty:http://localhost:9090").routeId("9090")
+                    .to("mock:9090")
+                    .transform().constant("9090");
+                from("jetty:http://localhost:9091").routeId("9091")
+                    .to("mock:9091")
+                    .transform().constant("9091");
+            }
+        };
+    }
+}
+

http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/components/camel-ribbon/src/test/java/org/apache/camel/component/ribbon/cloud/SpringBeanServiceCallRouteTest.java
----------------------------------------------------------------------
diff --git a/components/camel-ribbon/src/test/java/org/apache/camel/component/ribbon/cloud/SpringBeanServiceCallRouteTest.java b/components/camel-ribbon/src/test/java/org/apache/camel/component/ribbon/cloud/SpringBeanServiceCallRouteTest.java
new file mode 100644
index 0000000..9c99aec
--- /dev/null
+++ b/components/camel-ribbon/src/test/java/org/apache/camel/component/ribbon/cloud/SpringBeanServiceCallRouteTest.java
@@ -0,0 +1,31 @@
+/**
+ * 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.ribbon.cloud;
+
+import org.springframework.context.support.AbstractApplicationContext;
+import org.springframework.context.support.ClassPathXmlApplicationContext;
+import org.springframework.test.annotation.DirtiesContext;
+
+@DirtiesContext
+public class SpringBeanServiceCallRouteTest extends SpringRibbonServiceCallRouteTest {
+    @Override
+    protected AbstractApplicationContext createApplicationContext() {
+        return new ClassPathXmlApplicationContext("org/apache/camel/component/ribbon/cloud/SpringBeanRibbonServiceCallRouteTest.xml");
+    }
+}
+