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:19 UTC

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

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;