http://git-wip-us.apache.org/repos/asf/camel/blob/00d1d70b/components/camel-consul/src/main/java/org/apache/camel/component/consul/ConsulClientConfiguration.java
----------------------------------------------------------------------
diff --git 
a/components/camel-consul/src/main/java/org/apache/camel/component/consul/ConsulClientConfiguration.java
 
b/components/camel-consul/src/main/java/org/apache/camel/component/consul/ConsulClientConfiguration.java
new file mode 100644
index 0000000..fc92fc6
--- /dev/null
+++ 
b/components/camel-consul/src/main/java/org/apache/camel/component/consul/ConsulClientConfiguration.java
@@ -0,0 +1,342 @@
+/**
+ * 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;
+
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import com.orbitz.consul.Consul;
+import com.orbitz.consul.option.ConsistencyMode;
+import org.apache.camel.CamelContext;
+import org.apache.camel.RuntimeCamelException;
+import org.apache.camel.spi.UriParam;
+import org.apache.camel.spi.UriParams;
+import org.apache.camel.util.ObjectHelper;
+import org.apache.camel.util.jsse.SSLContextParameters;
+
+@UriParams
+public class ConsulClientConfiguration implements Cloneable {
+    @UriParam
+    private String url;
+    @UriParam(label = "advanced")
+    private String datacenter;
+    @UriParam(label = "advanced")
+    private String nearNode;
+    @UriParam(label = "advanced")
+    private List<String> nodeMeta;
+    @UriParam(label = "advanced", defaultValue = "DEFAULT", enums = 
"DEFAULT,STALE,CONSISTENT")
+    private ConsistencyMode consistencyMode = ConsistencyMode.DEFAULT;
+    @UriParam(javaType = "java.lang.String")
+    private Set<String> tags;
+
+    @UriParam(label = "security")
+    private SSLContextParameters sslContextParameters;
+    @UriParam(label = "security", secret = true)
+    private String aclToken;
+    @UriParam(label = "security", secret = true)
+    private String userName;
+    @UriParam(label = "security", secret = true)
+    private String password;
+
+    @UriParam
+    private Long connectTimeoutMillis;
+    @UriParam
+    private Long readTimeoutMillis;
+    @UriParam
+    private Long writeTimeoutMillis;
+    @UriParam(defaultValue = "true")
+    private boolean pingInstance = true;
+
+    @UriParam(label = "consumer,watch", defaultValue = "10")
+    private Integer blockSeconds = 10;
+    @UriParam(label = "consumer,watch", defaultValue = "0")
+    private long firstIndex;
+    @UriParam(label = "consumer,watch", defaultValue = "false")
+    private boolean recursive;
+
+    public ConsulClientConfiguration() {
+    }
+
+    public String getUrl() {
+        return url;
+    }
+
+    /**
+     * The Consul agent URL
+     */
+    public void setUrl(String url) {
+        this.url = url;
+    }
+
+    /**
+     * @deprecated replaced by {@link #getDatacenter()} ()}
+     */
+    @Deprecated
+    public String getDc() {
+        return datacenter;
+    }
+
+    /**
+     * The data center
+     *
+     * @deprecated replaced by {@link #setDatacenter(String)} ()}
+     */
+    @Deprecated
+    public void setDc(String dc) {
+        this.datacenter = dc;
+    }
+
+    public String getDatacenter() {
+        return datacenter;
+    }
+
+    /**
+     * The data center
+     */
+    public void setDatacenter(String datacenter) {
+        this.datacenter = datacenter;
+    }
+
+    public String getNearNode() {
+        return nearNode;
+    }
+
+    /**
+     * The near node to use for queries.
+     */
+    public void setNearNode(String nearNode) {
+        this.nearNode = nearNode;
+    }
+
+    public List<String> getNodeMeta() {
+        return nodeMeta;
+    }
+
+    /**
+     * The note meta-data to use for queries.
+     */
+    public void setNodeMeta(List<String> nodeMeta) {
+        this.nodeMeta = nodeMeta;
+    }
+
+    public ConsistencyMode getConsistencyMode() {
+        return consistencyMode;
+    }
+
+    /**
+     * The consistencyMode used for queries, default ConsistencyMode.DEFAULT
+     */
+    public void setConsistencyMode(ConsistencyMode consistencyMode) {
+        this.consistencyMode = consistencyMode;
+    }
+
+    public Set<String> getTags() {
+        return tags;
+    }
+
+    /**
+     * Set tags. You can separate multiple tags by comma.
+     */
+    public void setTags(Set<String> tags) {
+        this.tags = tags;
+    }
+
+    /**
+     * Set tags. You can separate multiple tags by comma.
+     */
+    public void setTags(String tagsAsString) {
+        this.tags = new HashSet<>();
+        Collections.addAll(tags, tagsAsString.split(","));
+    }
+
+    public SSLContextParameters getSslContextParameters() {
+        return sslContextParameters;
+    }
+
+    /**
+     * SSL configuration using an 
org.apache.camel.util.jsse.SSLContextParameters
+     * instance.
+     */
+    public void setSslContextParameters(SSLContextParameters 
sslContextParameters) {
+        this.sslContextParameters = sslContextParameters;
+    }
+
+    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 boolean requiresBasicAuthentication() {
+        return ObjectHelper.isNotEmpty(userName) && 
ObjectHelper.isNotEmpty(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 boolean isPingInstance() {
+        return pingInstance;
+    }
+
+    /**
+     * Configure if the AgentClient should attempt a ping before returning the 
Consul instance
+     */
+    public void setPingInstance(boolean pingInstance) {
+        this.pingInstance = pingInstance;
+    }
+
+    public Integer getBlockSeconds() {
+        return blockSeconds;
+    }
+
+    /**
+     * The second to wait for a watch event, default 10 seconds
+     */
+    public void setBlockSeconds(Integer blockSeconds) {
+        this.blockSeconds = blockSeconds;
+    }
+
+    public long getFirstIndex() {
+        return firstIndex;
+    }
+
+    /**
+     * The first index for watch for, default 0
+     */
+    public void setFirstIndex(long firstIndex) {
+        this.firstIndex = firstIndex;
+    }
+
+    public boolean isRecursive() {
+        return recursive;
+    }
+
+    /**
+     * Recursively watch, default false
+     */
+    public void setRecursive(boolean recursive) {
+        this.recursive = recursive;
+    }
+
+    // ****************************************
+    // Create a client
+    // ****************************************
+
+    public Consul createConsulClient() throws Exception {
+        return createConsulClient(null);
+    }
+
+    public Consul createConsulClient(CamelContext camelContext) throws 
Exception {
+        Consul.Builder builder = Consul.builder();
+        builder.withPing(pingInstance);
+
+        if (ObjectHelper.isNotEmpty(url)) {
+            builder.withUrl(url);
+        }
+        if (ObjectHelper.isNotEmpty(camelContext) && 
ObjectHelper.isNotEmpty(sslContextParameters)) {
+            
builder.withSslContext(sslContextParameters.createSSLContext(camelContext));
+        }
+        if (ObjectHelper.isNotEmpty(aclToken)) {
+            builder.withAclToken(aclToken);
+        }
+        if (requiresBasicAuthentication()) {
+            builder.withBasicAuth(userName, password);
+        }
+        if (ObjectHelper.isNotEmpty(connectTimeoutMillis)) {
+            builder.withConnectTimeoutMillis(connectTimeoutMillis);
+        }
+        if (ObjectHelper.isNotEmpty(readTimeoutMillis)) {
+            builder.withReadTimeoutMillis(readTimeoutMillis);
+        }
+        if (ObjectHelper.isNotEmpty(writeTimeoutMillis)) {
+            builder.withWriteTimeoutMillis(writeTimeoutMillis);
+        }
+
+        return builder.build();
+    }
+
+    // ****************************************
+    // Copy
+    // ****************************************
+
+    public ConsulClientConfiguration copy() {
+        try {
+            return (ConsulClientConfiguration)super.clone();
+        } catch (CloneNotSupportedException e) {
+            throw new RuntimeCamelException(e);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/00d1d70b/components/camel-consul/src/main/java/org/apache/camel/component/consul/ConsulComponent.java
----------------------------------------------------------------------
diff --git 
a/components/camel-consul/src/main/java/org/apache/camel/component/consul/ConsulComponent.java
 
b/components/camel-consul/src/main/java/org/apache/camel/component/consul/ConsulComponent.java
index f248527..11566f6 100644
--- 
a/components/camel-consul/src/main/java/org/apache/camel/component/consul/ConsulComponent.java
+++ 
b/components/camel-consul/src/main/java/org/apache/camel/component/consul/ConsulComponent.java
@@ -160,7 +160,6 @@ public class ConsulComponent extends DefaultComponent 
implements SSLContextParam
     @Override
     protected Endpoint createEndpoint(String uri, String remaining, 
Map<String, Object> parameters) throws Exception {
         ConsulConfiguration configuration = 
Optional.ofNullable(this.configuration).orElseGet(ConsulConfiguration::new).copy();
-        configuration.setCamelContext(getCamelContext());
 
         // using global ssl context parameters if set
         if (configuration.getSslContextParameters() == null) {

http://git-wip-us.apache.org/repos/asf/camel/blob/00d1d70b/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 ceb1f20..80e665b 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
@@ -16,55 +16,12 @@
  */
 package org.apache.camel.component.consul;
 
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-
-import com.orbitz.consul.Consul;
-import com.orbitz.consul.option.ConsistencyMode;
-
-import org.apache.camel.CamelContext;
-import org.apache.camel.CamelContextAware;
 import org.apache.camel.RuntimeCamelException;
 import org.apache.camel.spi.UriParam;
 import org.apache.camel.spi.UriParams;
-import org.apache.camel.util.ObjectHelper;
-import org.apache.camel.util.jsse.SSLContextParameters;
 
 @UriParams
-public class ConsulConfiguration implements CamelContextAware, Cloneable {
-    @UriParam
-    private String url;
-    @UriParam(label = "advanced")
-    private String datacenter;
-    @UriParam(label = "advanced")
-    private String nearNode;
-    @UriParam(label = "advanced")
-    private List<String> nodeMeta;
-    @UriParam(label = "advanced", defaultValue = "DEFAULT", enums = 
"DEFAULT,STALE,CONSISTENT")
-    private ConsistencyMode consistencyMode = ConsistencyMode.DEFAULT;
-    @UriParam(javaType = "java.lang.String")
-    private Set<String> tags;
-
-    @UriParam(label = "security")
-    private SSLContextParameters sslContextParameters;
-    @UriParam(label = "security", secret = true)
-    private String aclToken;
-    @UriParam(label = "security", secret = true)
-    private String userName;
-    @UriParam(label = "security", secret = true)
-    private String password;
-
-    @UriParam
-    private Long connectTimeoutMillis;
-    @UriParam
-    private Long readTimeoutMillis;
-    @UriParam
-    private Long writeTimeoutMillis;
-    @UriParam(defaultValue = "true")
-    private boolean pingInstance = true;
-
+public class ConsulConfiguration extends ConsulClientConfiguration {
     @UriParam
     private String key;
     @UriParam(label = "producer")
@@ -72,222 +29,13 @@ public class ConsulConfiguration implements 
CamelContextAware, Cloneable {
     @UriParam(label = "producer", defaultValue = "false")
     private boolean valueAsString;
 
-    @UriParam(label = "consumer,watch", defaultValue = "10")
-    private Integer blockSeconds = 10;
-    @UriParam(label = "consumer,watch", defaultValue = "0")
-    private long firstIndex;
-    @UriParam(label = "consumer,watch", defaultValue = "false")
-    private boolean recursive;
-
-    private CamelContext context;
-
     public ConsulConfiguration() {
-        this.context = null;
-    }
-
-    public ConsulConfiguration(CamelContext context) {
-        this.context = context;
-    }
-
-    @Override
-    public void setCamelContext(CamelContext context) {
-        this.context = context;
-    }
-
-    @Override
-    public CamelContext getCamelContext() {
-        return context;
-    }
-
-    public String getUrl() {
-        return url;
-    }
-
-    /**
-     * The Consul agent URL
-     */
-    public void setUrl(String url) {
-        this.url = url;
-    }
-
-    /**
-     * @deprecated replaced by {@link #getDatacenter()} ()}
-     */
-    @Deprecated
-    public String getDc() {
-        return datacenter;
-    }
-
-    /**
-     * The data center
-     *
-     * @deprecated replaced by {@link #setDatacenter(String)} ()}
-     */
-    @Deprecated
-    public void setDc(String dc) {
-        this.datacenter = dc;
-    }
-
-    public String getDatacenter() {
-        return datacenter;
-    }
-
-    /**
-     * The data center
-     */
-    public void setDatacenter(String datacenter) {
-        this.datacenter = datacenter;
-    }
-
-    public String getNearNode() {
-        return nearNode;
-    }
-
-    /**
-     * The near node to use for queries.
-     */
-    public void setNearNode(String nearNode) {
-        this.nearNode = nearNode;
-    }
-
-    public List<String> getNodeMeta() {
-        return nodeMeta;
-    }
-
-    /**
-     * The note meta-data to use for queries.
-     */
-    public void setNodeMeta(List<String> nodeMeta) {
-        this.nodeMeta = nodeMeta;
-    }
-
-    public ConsistencyMode getConsistencyMode() {
-        return consistencyMode;
-    }
-
-    /**
-     * The consistencyMode used for queries, default ConsistencyMode.DEFAULT
-     */
-    public void setConsistencyMode(ConsistencyMode consistencyMode) {
-        this.consistencyMode = consistencyMode;
-    }
-
-    public Set<String> getTags() {
-        return tags;
-    }
-
-    /**
-     * Set tags. You can separate multiple tags by comma.
-     */
-    public void setTags(Set<String> tags) {
-        this.tags = tags;
-    }
-
-    /**
-     * Set tags. You can separate multiple tags by comma.
-     */
-    public void setTags(String tagsAsString) {
-        this.tags = new HashSet<>();
-        Collections.addAll(tags, tagsAsString.split(","));
-    }
-
-    public SSLContextParameters getSslContextParameters() {
-        return sslContextParameters;
-    }
-
-    /**
-     * SSL configuration using an 
org.apache.camel.util.jsse.SSLContextParameters
-     * instance.
-     */
-    public void setSslContextParameters(SSLContextParameters 
sslContextParameters) {
-        this.sslContextParameters = sslContextParameters;
-    }
-
-    public String getAclToken() {
-        return aclToken;
-    }
-
-    /**
-     * Sets the ACL token to be used with Consul
-     */
-    public void setAclToken(String aclToken) {
-        this.aclToken = aclToken;
     }
 
     public String getAction() {
         return action;
     }
 
-    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 boolean requiresBasicAuthentication() {
-        return ObjectHelper.isNotEmpty(userName) && 
ObjectHelper.isNotEmpty(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 boolean isPingInstance() {
-        return pingInstance;
-    }
-
-    /**
-     * Configure if the AgentClient should attempt a ping before returning the 
Consul instance
-     */
-    public void setPingInstance(boolean pingInstance) {
-        this.pingInstance = pingInstance;
-    }
-
     /**
      * The default action. Can be overridden by CamelConsulAction
      */
@@ -318,68 +66,11 @@ public class ConsulConfiguration implements 
CamelContextAware, Cloneable {
         this.key = key;
     }
 
-    public Integer getBlockSeconds() {
-        return blockSeconds;
-    }
-
-    /**
-     * The second to wait for a watch event, default 10 seconds
-     */
-    public void setBlockSeconds(Integer blockSeconds) {
-        this.blockSeconds = blockSeconds;
-    }
-
-    public long getFirstIndex() {
-        return firstIndex;
-    }
-
-    /**
-     * The first index for watch for, default 0
-     */
-    public void setFirstIndex(long firstIndex) {
-        this.firstIndex = firstIndex;
-    }
-
-    public boolean isRecursive() {
-        return recursive;
-    }
-
-    /**
-     * Recursively watch, default false
-     */
-    public void setRecursive(boolean recursive) {
-        this.recursive = recursive;
-    }
-
-    public Consul createConsulClient() throws Exception {
-        Consul.Builder builder = Consul.builder();
-        builder.withPing(pingInstance);
-
-        if (ObjectHelper.isNotEmpty(url)) {
-            builder.withUrl(url);
-        }
-        if (ObjectHelper.isNotEmpty(context) && 
ObjectHelper.isNotEmpty(sslContextParameters)) {
-            
builder.withSslContext(sslContextParameters.createSSLContext(context));
-        }
-        if (ObjectHelper.isNotEmpty(aclToken)) {
-            builder.withAclToken(aclToken);
-        }
-        if (requiresBasicAuthentication()) {
-            builder.withBasicAuth(userName, password);
-        }
-        if (ObjectHelper.isNotEmpty(connectTimeoutMillis)) {
-            builder.withConnectTimeoutMillis(connectTimeoutMillis);
-        }
-        if (ObjectHelper.isNotEmpty(readTimeoutMillis)) {
-            builder.withReadTimeoutMillis(readTimeoutMillis);
-        }
-        if (ObjectHelper.isNotEmpty(writeTimeoutMillis)) {
-            builder.withWriteTimeoutMillis(writeTimeoutMillis);
-        }
-
-        return builder.build();
-    }
+    // ****************************************
+    // Copy
+    // ****************************************
 
+    @Override
     public ConsulConfiguration copy() {
         try {
             return (ConsulConfiguration)super.clone();

http://git-wip-us.apache.org/repos/asf/camel/blob/00d1d70b/components/camel-consul/src/main/java/org/apache/camel/component/consul/ConsulEndpoint.java
----------------------------------------------------------------------
diff --git 
a/components/camel-consul/src/main/java/org/apache/camel/component/consul/ConsulEndpoint.java
 
b/components/camel-consul/src/main/java/org/apache/camel/component/consul/ConsulEndpoint.java
index c9eaccf..c8d1c24 100644
--- 
a/components/camel-consul/src/main/java/org/apache/camel/component/consul/ConsulEndpoint.java
+++ 
b/components/camel-consul/src/main/java/org/apache/camel/component/consul/ConsulEndpoint.java
@@ -100,7 +100,7 @@ public class ConsulEndpoint extends DefaultEndpoint {
 
     public synchronized Consul getConsul() throws Exception {
         if (consul == null) {
-            consul = configuration.createConsulClient();
+            consul = configuration.createConsulClient(getCamelContext());
         }
 
         return consul;

http://git-wip-us.apache.org/repos/asf/camel/blob/00d1d70b/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
index 8cfa854..e7cfd5f 100644
--- 
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
@@ -27,7 +27,6 @@ import com.orbitz.consul.model.catalog.CatalogService;
 import com.orbitz.consul.model.health.ServiceHealth;
 import com.orbitz.consul.option.ImmutableQueryOptions;
 import com.orbitz.consul.option.QueryOptions;
-import org.apache.camel.RuntimeCamelException;
 import org.apache.camel.cloud.ServiceDefinition;
 import org.apache.camel.component.consul.ConsulConfiguration;
 import org.apache.camel.impl.cloud.DefaultServiceDefinition;
@@ -41,7 +40,10 @@ public final class ConsulServiceDiscovery extends 
DefaultServiceDiscovery {
     private final QueryOptions queryOptions;
 
     public ConsulServiceDiscovery(ConsulConfiguration configuration) throws 
Exception {
-        this.client = Suppliers.memorize(configuration::createConsulClient, 
this::rethrowAsRuntimeCamelException);
+        this.client = Suppliers.memorize(
+            () -> configuration.createConsulClient(getCamelContext()),
+            e -> ObjectHelper.wrapRuntimeCamelException(e)
+        );
 
         ImmutableQueryOptions.Builder builder = 
ImmutableQueryOptions.builder();
         ObjectHelper.ifNotEmpty(configuration.getDatacenter(), 
builder::datacenter);
@@ -68,10 +70,6 @@ public final class ConsulServiceDiscovery extends 
DefaultServiceDiscovery {
     // Helpers
     // *************************
 
-    private void rethrowAsRuntimeCamelException(Exception e) {
-        throw new RuntimeCamelException(e);
-    }
-
     private boolean isHealthy(ServiceHealth serviceHealth) {
         return serviceHealth.getChecks().stream().allMatch(
             check -> ObjectHelper.equal(check.getStatus(), "passing", true)

http://git-wip-us.apache.org/repos/asf/camel/blob/00d1d70b/components/camel-consul/src/main/java/org/apache/camel/component/consul/ha/ConsulClusterConfiguration.java
----------------------------------------------------------------------
diff --git 
a/components/camel-consul/src/main/java/org/apache/camel/component/consul/ha/ConsulClusterConfiguration.java
 
b/components/camel-consul/src/main/java/org/apache/camel/component/consul/ha/ConsulClusterConfiguration.java
index f992487..535eec6 100644
--- 
a/components/camel-consul/src/main/java/org/apache/camel/component/consul/ha/ConsulClusterConfiguration.java
+++ 
b/components/camel-consul/src/main/java/org/apache/camel/component/consul/ha/ConsulClusterConfiguration.java
@@ -17,9 +17,9 @@
 package org.apache.camel.component.consul.ha;
 
 import org.apache.camel.RuntimeCamelException;
-import org.apache.camel.component.consul.ConsulConfiguration;
+import org.apache.camel.component.consul.ConsulClientConfiguration;
 
-public class ConsulClusterConfiguration extends ConsulConfiguration {
+public class ConsulClusterConfiguration extends ConsulClientConfiguration {
     private int sessionTtl = 60;
     private int sessionLockDelay = 5;
     private int sessionRefreshInterval = 5;

http://git-wip-us.apache.org/repos/asf/camel/blob/00d1d70b/components/camel-consul/src/main/java/org/apache/camel/component/consul/ha/ConsulClusterView.java
----------------------------------------------------------------------
diff --git 
a/components/camel-consul/src/main/java/org/apache/camel/component/consul/ha/ConsulClusterView.java
 
b/components/camel-consul/src/main/java/org/apache/camel/component/consul/ha/ConsulClusterView.java
index 1956d9e..4ec8be2 100644
--- 
a/components/camel-consul/src/main/java/org/apache/camel/component/consul/ha/ConsulClusterView.java
+++ 
b/components/camel-consul/src/main/java/org/apache/camel/component/consul/ha/ConsulClusterView.java
@@ -33,7 +33,6 @@ import com.orbitz.consul.model.kv.Value;
 import com.orbitz.consul.model.session.ImmutableSession;
 import com.orbitz.consul.model.session.SessionInfo;
 import com.orbitz.consul.option.QueryOptions;
-import org.apache.camel.CamelContext;
 import org.apache.camel.ha.CamelClusterMember;
 import org.apache.camel.impl.ha.AbstractCamelClusterView;
 import org.slf4j.Logger;
@@ -64,13 +63,6 @@ final class ConsulClusterView extends 
AbstractCamelClusterView {
     }
 
     @Override
-    public void setCamelContext(CamelContext camelContext) {
-        super.setCamelContext(camelContext);
-
-        this.configuration.setCamelContext(camelContext);
-    }
-
-    @Override
     public Optional<CamelClusterMember> getMaster() {
         if (keyValueClient == null) {
             return Optional.empty();
@@ -103,7 +95,7 @@ final class ConsulClusterView extends 
AbstractCamelClusterView {
     @Override
     protected void doStart() throws Exception {
         if (sessionId == null) {
-            client = configuration.createConsulClient();
+            client = configuration.createConsulClient(getCamelContext());
             sessionClient = client.sessionClient();
             keyValueClient = client.keyValueClient();
 

http://git-wip-us.apache.org/repos/asf/camel/blob/00d1d70b/components/camel-consul/src/main/java/org/apache/camel/component/consul/health/ConsulHealthCheckRepository.java
----------------------------------------------------------------------
diff --git 
a/components/camel-consul/src/main/java/org/apache/camel/component/consul/health/ConsulHealthCheckRepository.java
 
b/components/camel-consul/src/main/java/org/apache/camel/component/consul/health/ConsulHealthCheckRepository.java
new file mode 100644
index 0000000..e7ca18a
--- /dev/null
+++ 
b/components/camel-consul/src/main/java/org/apache/camel/component/consul/health/ConsulHealthCheckRepository.java
@@ -0,0 +1,230 @@
+/**
+ * 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.health;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import java.util.function.Supplier;
+import java.util.stream.Stream;
+
+import com.orbitz.consul.Consul;
+import org.apache.camel.CamelContext;
+import org.apache.camel.CamelContextAware;
+import org.apache.camel.health.HealthCheck;
+import org.apache.camel.health.HealthCheckConfiguration;
+import org.apache.camel.health.HealthCheckRepository;
+import org.apache.camel.health.HealthCheckResultBuilder;
+import org.apache.camel.impl.health.AbstractHealthCheck;
+import org.apache.camel.util.ObjectHelper;
+import org.apache.camel.util.function.Suppliers;
+
+public class ConsulHealthCheckRepository implements HealthCheckRepository, 
CamelContextAware {
+    private final Supplier<Consul> client;
+    private final ConcurrentMap<String, HealthCheck> checks;
+    private ConsulHealthCheckRepositoryConfiguration configuration;
+    private CamelContext camelContext;
+
+    public ConsulHealthCheckRepository() {
+        this(null);
+    }
+
+    private 
ConsulHealthCheckRepository(ConsulHealthCheckRepositoryConfiguration 
configuration) {
+        this.checks = new ConcurrentHashMap<>();
+        this.configuration = configuration;
+        this.client = Suppliers.memorize(this::createConsul, 
ObjectHelper::wrapRuntimeCamelException);
+    }
+
+    // *************************************
+    //
+    // *************************************
+
+    public ConsulHealthCheckRepositoryConfiguration getConfiguration() {
+        return configuration;
+    }
+
+    public void setConfiguration(ConsulHealthCheckRepositoryConfiguration 
configuration) {
+        this.configuration = configuration;
+    }
+
+    @Override
+    public void setCamelContext(CamelContext camelContext) {
+        this.camelContext = camelContext;
+    }
+
+    @Override
+    public CamelContext getCamelContext() {
+        return camelContext;
+    }
+
+    @Override
+    public Stream<HealthCheck> stream() {
+        final Set<String> ids = configuration.getChecks();
+
+        if (ObjectHelper.isNotEmpty(ids)) {
+            return ids.stream()
+                .map(checkId -> checks.computeIfAbsent(checkId, 
ConsulHealthCheck::new))
+                .filter(check -> check.getConfiguration().isEnabled());
+        }
+
+        return Stream.empty();
+    }
+
+    // *************************************
+    //
+    // *************************************
+
+    private Consul createConsul() throws Exception {
+        ConsulHealthCheckRepositoryConfiguration conf = configuration;
+
+        if (conf == null) {
+            conf = new ConsulHealthCheckRepositoryConfiguration();
+        }
+
+        return conf.createConsulClient(camelContext);
+    }
+
+    private class ConsulHealthCheck extends AbstractHealthCheck {
+        private final String checkId;
+
+        ConsulHealthCheck(String checkId) {
+            super("consul-" + checkId.replaceAll(":", "-"));
+
+            this.checkId = checkId;
+
+            HealthCheckConfiguration conf = 
configuration.getConfigurations().get(getId());
+            if (conf == null) {
+                conf = HealthCheckConfiguration.builder()
+                    .complete(configuration.getDefaultConfiguration())
+                    .build();
+            }
+
+            setConfiguration(conf);
+        }
+
+        @Override
+        protected void doCall(HealthCheckResultBuilder builder, Map<String, 
Object> options) {
+            builder.unknown();
+
+            com.orbitz.consul.model.health.HealthCheck check = 
client.get().agentClient().getChecks().get(checkId);
+            if (check != null) {
+
+                // From Consul sources:
+                // 
https://github.com/hashicorp/consul/blob/master/api/health.go#L8-L16
+                //
+                // States are:
+                //
+                // const (
+                //     HealthAny is special, and is used as a wild card,
+                //     not as a specific state.
+                //     HealthAny      = "any"
+                //     HealthPassing  = "passing"
+                //     HealthWarning  = "warning"
+                //     HealthCritical = "critical"
+                //     HealthMaint    = "maintenance"
+                // )
+                if (ObjectHelper.equalIgnoreCase(check.getStatus(), 
"passing")) {
+                    builder.up();
+                }
+                if (ObjectHelper.equalIgnoreCase(check.getStatus(), 
"warning")) {
+                    builder.down();
+                }
+                if (ObjectHelper.equalIgnoreCase(check.getStatus(), 
"critical")) {
+                    builder.down();
+                }
+
+                builder.detail("consul.service.name", 
check.getServiceName().orNull());
+                builder.detail("consul.service.id", 
check.getServiceId().orNull());
+                builder.detail("consul.check.status", check.getStatus());
+                builder.detail("consul.check.id", check.getCheckId());
+            }
+        }
+    }
+
+
+
+    // ****************************************
+    // Builder
+    // ****************************************
+
+    public static final class Builder implements 
org.apache.camel.Builder<ConsulHealthCheckRepository> {
+        private HealthCheckConfiguration defaultConfiguration;
+        private Set<String> checks;
+        private Map<String, HealthCheckConfiguration> configurations;
+
+        public Builder configuration(HealthCheckConfiguration 
defaultConfiguration) {
+            this.defaultConfiguration = defaultConfiguration;
+            return this;
+        }
+
+        public Builder configuration(String id, HealthCheckConfiguration 
configuration) {
+            if (this.configurations == null) {
+                this.configurations = new HashMap<>();
+            }
+
+            this.configurations.put(id, configuration);
+
+            return this;
+        }
+
+        public Builder configurations(Map<String, HealthCheckConfiguration> 
configurations) {
+            if (ObjectHelper.isNotEmpty(configurations)) {
+                configurations.forEach(this::configuration);
+            }
+
+            return this;
+        }
+
+        public Builder check(String id) {
+            if (ObjectHelper.isNotEmpty(id)) {
+                if (this.checks == null) {
+                    this.checks = new HashSet<>();
+                }
+                this.checks.add(id);
+            }
+
+            return this;
+        }
+
+        public Builder checks(Collection<String> ids) {
+            if (ObjectHelper.isNotEmpty(ids)) {
+                ids.forEach(this::check);
+            }
+
+            return this;
+        }
+
+        @Override
+        public ConsulHealthCheckRepository build() {
+            ConsulHealthCheckRepositoryConfiguration configuration = new 
ConsulHealthCheckRepositoryConfiguration();
+            configuration.setDefaultConfiguration(defaultConfiguration);
+
+            if (checks != null) {
+                checks.forEach(configuration::addCheck);
+            }
+            if (configurations != null) {
+                configurations.forEach(configuration::addConfiguration);
+            }
+
+            return new ConsulHealthCheckRepository(configuration);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/00d1d70b/components/camel-consul/src/main/java/org/apache/camel/component/consul/health/ConsulHealthCheckRepositoryConfiguration.java
----------------------------------------------------------------------
diff --git 
a/components/camel-consul/src/main/java/org/apache/camel/component/consul/health/ConsulHealthCheckRepositoryConfiguration.java
 
b/components/camel-consul/src/main/java/org/apache/camel/component/consul/health/ConsulHealthCheckRepositoryConfiguration.java
new file mode 100644
index 0000000..1f3cde2
--- /dev/null
+++ 
b/components/camel-consul/src/main/java/org/apache/camel/component/consul/health/ConsulHealthCheckRepositoryConfiguration.java
@@ -0,0 +1,93 @@
+/**
+ * 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.health;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.camel.RuntimeCamelException;
+import org.apache.camel.component.consul.ConsulClientConfiguration;
+import org.apache.camel.health.HealthCheckConfiguration;
+
+public class ConsulHealthCheckRepositoryConfiguration extends 
ConsulClientConfiguration {
+    /**
+     * Default configuration.
+     */
+    private HealthCheckConfiguration defaultConfiguration;
+
+    /**
+     * Define the checks to include.
+     */
+    private Set<String> checks;
+
+    /**
+     * Service configuration.
+     */
+    private Map<String, HealthCheckConfiguration> configurations;
+
+    public ConsulHealthCheckRepositoryConfiguration() {
+        this.checks = new HashSet<>();
+        this.configurations = new HashMap<>();
+    }
+
+    // ****************************************
+    // Properties
+    // ****************************************
+
+    public HealthCheckConfiguration getDefaultConfiguration() {
+        return defaultConfiguration;
+    }
+
+    public void setDefaultConfiguration(HealthCheckConfiguration 
defaultConfiguration) {
+        this.defaultConfiguration = defaultConfiguration;
+    }
+
+    public Set<String> getChecks() {
+        return checks;
+    }
+
+    public void addCheck(String id) {
+        checks.add(id);
+    }
+
+    public Map<String, HealthCheckConfiguration> getConfigurations() {
+        return configurations;
+    }
+
+    public void addConfiguration(String id, HealthCheckConfiguration 
configuration) {
+        if (this.configurations == null) {
+            this.configurations = new HashMap<>();
+        }
+
+        this.configurations.put(id, configuration);
+    }
+
+    // ****************************************
+    // Copy
+    // ****************************************
+
+    @Override
+    public ConsulHealthCheckRepositoryConfiguration copy() {
+        try {
+            return (ConsulHealthCheckRepositoryConfiguration)super.clone();
+        } catch (CloneNotSupportedException e) {
+            throw new RuntimeCamelException(e);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/00d1d70b/components/camel-consul/src/main/java/org/apache/camel/component/consul/policy/ConsulRoutePolicy.java
----------------------------------------------------------------------
diff --git 
a/components/camel-consul/src/main/java/org/apache/camel/component/consul/policy/ConsulRoutePolicy.java
 
b/components/camel-consul/src/main/java/org/apache/camel/component/consul/policy/ConsulRoutePolicy.java
index a40fd20..c5ce6c1 100644
--- 
a/components/camel-consul/src/main/java/org/apache/camel/component/consul/policy/ConsulRoutePolicy.java
+++ 
b/components/camel-consul/src/main/java/org/apache/camel/component/consul/policy/ConsulRoutePolicy.java
@@ -83,7 +83,7 @@ public final class ConsulRoutePolicy extends 
RoutePolicySupport implements Camel
 
     public ConsulRoutePolicy(ConsulConfiguration configuration) throws 
Exception {
         this.consulUrl = configuration.getUrl();
-        this.consul = configuration.createConsulClient();
+        this.consul = configuration.createConsulClient(camelContext);
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/camel/blob/00d1d70b/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
index e63a39f..2523ad7 100644
--- 
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
@@ -71,7 +71,7 @@ public class ConsulServiceDiscoveryTest {
 
     @Test
     public void testServiceDiscovery() throws Exception {
-        ConsulConfiguration configuration = new ConsulConfiguration(null);
+        ConsulConfiguration configuration = new ConsulConfiguration();
         ServiceDiscovery discovery = new ConsulServiceDiscovery(configuration);
 
         List<ServiceDefinition> services = discovery.getServices("my-service");

http://git-wip-us.apache.org/repos/asf/camel/blob/00d1d70b/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 7f134f3..8d0cb46 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
@@ -46,6 +46,9 @@ import 
org.apache.camel.component.properties.PropertiesLocation;
 import org.apache.camel.component.properties.PropertiesParser;
 import org.apache.camel.component.properties.PropertiesResolver;
 import org.apache.camel.ha.CamelClusterService;
+import org.apache.camel.health.HealthCheckRegistry;
+import org.apache.camel.health.HealthCheckRepository;
+import org.apache.camel.health.HealthCheckService;
 import org.apache.camel.management.DefaultManagementAgent;
 import org.apache.camel.management.DefaultManagementLifecycleStrategy;
 import org.apache.camel.management.DefaultManagementStrategy;
@@ -160,6 +163,7 @@ public abstract class AbstractCamelContextFactoryBean<T 
extends ModelCamelContex
         return contextClassLoaderOnStart;
     }
 
+    //CHECKSTYLE:OFF
     public void afterPropertiesSet() throws Exception {
         if (ObjectHelper.isEmpty(getId())) {
             throw new IllegalArgumentException("Id must be set");
@@ -339,7 +343,29 @@ public abstract class AbstractCamelContextFactoryBean<T 
extends ModelCamelContex
                 getContext().addRoutePolicyFactory(factory);
             }
         }
-
+        // Health check registry
+        HealthCheckRegistry healthCheckRegistry = 
getBeanForType(HealthCheckRegistry.class);
+        if (healthCheckRegistry != null) {
+            healthCheckRegistry.setCamelContext(getContext());
+            LOG.info("Using HealthCheckRegistry: {}", healthCheckRegistry);
+            getContext().setHealthCheckRegistry(healthCheckRegistry);
+        } else {
+            healthCheckRegistry = getContext().getHealthCheckRegistry();
+            healthCheckRegistry.setCamelContext(getContext());
+        }
+        // Health check repository
+        Set<HealthCheckRepository> repositories = 
getContext().getRegistry().findByType(HealthCheckRepository.class);
+        if (ObjectHelper.isNotEmpty(repositories)) {
+            for (HealthCheckRepository repository: repositories) {
+                healthCheckRegistry.addRepository(repository);
+            }
+        }
+        // Health check service
+        HealthCheckService healthCheckService = 
getBeanForType(HealthCheckService.class);
+        if (healthCheckService != null) {
+            LOG.info("Using HealthCheckService: {}", healthCheckService);
+            getContext().addService(healthCheckService);
+        }
         // Route controller
         RouteController routeController = 
getBeanForType(RouteController.class);
         if (clusterService != null) {
@@ -359,6 +385,7 @@ public abstract class AbstractCamelContextFactoryBean<T 
extends ModelCamelContex
         // init stream caching strategy
         initStreamCachingStrategy();
     }
+    //CHECKSTYLE:ON
 
     /**
      * Setup all the routes which must be done prior starting {@link 
CamelContext}.

http://git-wip-us.apache.org/repos/asf/camel/blob/00d1d70b/components/camel-servicenow/camel-servicenow-component/pom.xml
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/camel-servicenow-component/pom.xml 
b/components/camel-servicenow/camel-servicenow-component/pom.xml
index 4b9a720..6aa16a9 100644
--- a/components/camel-servicenow/camel-servicenow-component/pom.xml
+++ b/components/camel-servicenow/camel-servicenow-component/pom.xml
@@ -29,7 +29,7 @@
 
   <artifactId>camel-servicenow</artifactId>
   <packaging>jar</packaging>
-  <name>Camel :: ServiceNow</name>
+  <name>Camel :: ServiceNow :: Component</name>
   <description>Camel ServiceNow support</description>
 
   <properties>

http://git-wip-us.apache.org/repos/asf/camel/blob/00d1d70b/components/camel-servicenow/camel-servicenow-component/src/main/docs/servicenow-component.adoc
----------------------------------------------------------------------
diff --git 
a/components/camel-servicenow/camel-servicenow-component/src/main/docs/servicenow-component.adoc
 
b/components/camel-servicenow/camel-servicenow-component/src/main/docs/servicenow-component.adoc
index f0a177a..cf613d0 100644
--- 
a/components/camel-servicenow/camel-servicenow-component/src/main/docs/servicenow-component.adoc
+++ 
b/components/camel-servicenow/camel-servicenow-component/src/main/docs/servicenow-component.adoc
@@ -30,7 +30,7 @@ for this component:
 
 
 // component options: START
-The ServiceNow component supports 10 options which are listed below.
+The ServiceNow component supports 14 options which are listed below.
 
 
 
@@ -45,6 +45,10 @@ The ServiceNow component supports 10 options which are 
listed below.
 | *oauthClientId* (security) | OAuth2 ClientID |  | String
 | *oauthClientSecret* (security) | OAuth2 ClientSecret |  | String
 | *oauthTokenUrl* (security) | OAuth token Url |  | String
+| *proxyHost* (advanced) | The proxy host name |  | String
+| *proxyPort* (advanced) | The proxy port number |  | Integer
+| *proxyUserName* (security) | Username for proxy authentication |  | String
+| *proxyPassword* (security) | Password for proxy authentication |  | String
 | *useGlobalSslContext Parameters* (security) | Enable usage of global SSL 
context parameters. | false | boolean
 | *resolveProperty Placeholders* (advanced) | Whether the component should 
resolve property placeholders on itself when starting. Only properties which 
are of String type can use property placeholders. | true | boolean
 |===

http://git-wip-us.apache.org/repos/asf/camel/blob/00d1d70b/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/ServiceNowClient.java
----------------------------------------------------------------------
diff --git 
a/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/ServiceNowClient.java
 
b/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/ServiceNowClient.java
index 9fd7886..4e5668f 100644
--- 
a/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/ServiceNowClient.java
+++ 
b/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/ServiceNowClient.java
@@ -16,6 +16,8 @@
  */
 package org.apache.camel.component.servicenow;
 
+import java.io.IOException;
+import java.security.GeneralSecurityException;
 import java.util.Arrays;
 import java.util.Map;
 import java.util.function.Function;
@@ -45,7 +47,7 @@ public final class ServiceNowClient {
     private final ServiceNowConfiguration configuration;
     private final WebClient client;
 
-    ServiceNowClient(CamelContext camelContext, ServiceNowConfiguration 
configuration) throws Exception {
+    public ServiceNowClient(CamelContext camelContext, ServiceNowConfiguration 
configuration) {
         this.camelContext = camelContext;
         this.configuration = configuration;
         this.client = WebClient.create(
@@ -206,7 +208,7 @@ public final class ServiceNowClient {
     }
 
     private static void configureRequestContext(
-            CamelContext context, ServiceNowConfiguration configuration, 
WebClient client) throws Exception {
+            CamelContext context, ServiceNowConfiguration configuration, 
WebClient client) {
 
         WebClient.getConfig(client)
             .getRequestContext()
@@ -214,7 +216,7 @@ public final class ServiceNowClient {
     }
 
     private static void configureTls(
-        CamelContext camelContext, ServiceNowConfiguration configuration, 
WebClient client) throws Exception {
+        CamelContext camelContext, ServiceNowConfiguration configuration, 
WebClient client) {
 
         SSLContextParameters sslContextParams = 
configuration.getSslContextParameters();
         if (sslContextParams != null) {
@@ -224,15 +226,19 @@ public final class ServiceNowClient {
                 tlsClientParams = new TLSClientParameters();
             }
 
-            SSLContext sslContext = 
sslContextParams.createSSLContext(camelContext);
-            tlsClientParams.setSSLSocketFactory(sslContext.getSocketFactory());
+            try {
+                SSLContext sslContext = 
sslContextParams.createSSLContext(camelContext);
+                
tlsClientParams.setSSLSocketFactory(sslContext.getSocketFactory());
 
-            conduit.setTlsClientParameters(tlsClientParams);
+                conduit.setTlsClientParameters(tlsClientParams);
+            } catch (IOException | GeneralSecurityException e) {
+                throw ObjectHelper.wrapRuntimeCamelException(e);
+            }
         }
     }
 
     private static void configureHttpClientPolicy(
-            CamelContext context, ServiceNowConfiguration configuration, 
WebClient client) throws Exception {
+            CamelContext context, ServiceNowConfiguration configuration, 
WebClient client) {
 
         HTTPClientPolicy httpPolicy = configuration.getHttpClientPolicy();
         if (httpPolicy == null) {
@@ -252,7 +258,7 @@ public final class ServiceNowClient {
     }
 
     private static void configureProxyAuthorizationPolicy(
-            CamelContext context, ServiceNowConfiguration configuration, 
WebClient client) throws Exception {
+            CamelContext context, ServiceNowConfiguration configuration, 
WebClient client) {
 
         ProxyAuthorizationPolicy proxyPolicy = 
configuration.getProxyAuthorizationPolicy();
         if (proxyPolicy == null) {

http://git-wip-us.apache.org/repos/asf/camel/blob/00d1d70b/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/ServiceNowComponent.java
----------------------------------------------------------------------
diff --git 
a/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/ServiceNowComponent.java
 
b/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/ServiceNowComponent.java
index c9cbb89..e2cf354 100644
--- 
a/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/ServiceNowComponent.java
+++ 
b/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/ServiceNowComponent.java
@@ -16,8 +16,6 @@
  */
 package org.apache.camel.component.servicenow;
 
-import java.util.Arrays;
-import java.util.Collection;
 import java.util.Map;
 
 import org.apache.camel.CamelContext;
@@ -25,9 +23,7 @@ import org.apache.camel.ComponentVerifier;
 import org.apache.camel.Endpoint;
 import org.apache.camel.SSLContextParametersAware;
 import org.apache.camel.VerifiableComponent;
-import org.apache.camel.component.extension.ComponentExtension;
 import org.apache.camel.component.extension.ComponentVerifierExtension;
-import org.apache.camel.component.extension.MetaDataExtension;
 import org.apache.camel.impl.DefaultComponent;
 import org.apache.camel.spi.Metadata;
 import org.apache.camel.util.EndpointHelper;
@@ -39,8 +35,6 @@ import org.apache.camel.util.ObjectHelper;
  */
 @Metadata(label = "verifiers", enums = "parameters,connectivity")
 public class ServiceNowComponent extends DefaultComponent implements 
VerifiableComponent, SSLContextParametersAware {
-    private static final Collection<Class<? extends ComponentExtension>> 
EXTENSIONS = Arrays.asList(ComponentVerifierExtension.class, 
MetaDataExtension.class);
-
     @Metadata(label = "advanced")
     private String instanceName;
     @Metadata(label = "advanced")
@@ -48,9 +42,6 @@ public class ServiceNowComponent extends DefaultComponent 
implements VerifiableC
     @Metadata(label = "security", defaultValue = "false")
     private boolean useGlobalSslContextParameters;
 
-    private ServiceNowComponentVerifierExtension verifierExtension;
-    private ServiceNowMetaDataExtension metaDataExtension;
-
     public ServiceNowComponent() {
         this(null);
     }
@@ -64,54 +55,9 @@ public class ServiceNowComponent extends DefaultComponent 
implements VerifiableC
         registerExtension(ServiceNowMetaDataExtension::new);
     }
 
-    @Override
-    protected Endpoint createEndpoint(String uri, String remaining, 
Map<String, Object> parameters) throws Exception {
-        final CamelContext context = getCamelContext();
-        final ServiceNowConfiguration configuration = 
this.configuration.copy();
-
-        Map<String, Object> models = 
IntrospectionSupport.extractProperties(parameters, "model.");
-        for (Map.Entry<String, Object> entry : models.entrySet()) {
-            configuration.addModel(
-                entry.getKey(),
-                EndpointHelper.resolveParameter(context, 
(String)entry.getValue(), Class.class));
-        }
-
-        Map<String, Object> requestModels = 
IntrospectionSupport.extractProperties(parameters, "requestModel.");
-        for (Map.Entry<String, Object> entry : requestModels.entrySet()) {
-            configuration.addRequestModel(
-                entry.getKey(),
-                EndpointHelper.resolveParameter(context, 
(String)entry.getValue(), Class.class));
-        }
-
-        Map<String, Object> responseModels = 
IntrospectionSupport.extractProperties(parameters, "responseModel.");
-        for (Map.Entry<String, Object> entry : responseModels.entrySet()) {
-            configuration.addResponseModel(
-                entry.getKey(),
-                EndpointHelper.resolveParameter(context, 
(String)entry.getValue(), Class.class));
-        }
-
-        setProperties(configuration, parameters);
-
-        if (ObjectHelper.isEmpty(remaining)) {
-            // If an instance is not set on the endpoint uri, use the one set 
on
-            // component.
-            remaining = instanceName;
-        }
-
-        String instanceName = 
getCamelContext().resolvePropertyPlaceholders(remaining);
-        if (!configuration.hasApiUrl()) {
-            
configuration.setApiUrl(String.format("https://%s.service-now.com/api";, 
instanceName));
-        }
-        if (!configuration.hasOauthTokenUrl()) {
-            
configuration.setOauthTokenUrl(String.format("https://%s.service-now.com/oauth_token.do";,
 instanceName));
-        }
-
-        if (configuration.getSslContextParameters() == null) {
-            
configuration.setSslContextParameters(retrieveGlobalSslContextParameters());
-        }
-
-        return new ServiceNowEndpoint(uri, this, configuration, instanceName);
-    }
+    // ****************************************
+    // Properties
+    // ****************************************
 
     public String getInstanceName() {
         return instanceName;
@@ -206,6 +152,58 @@ public class ServiceNowComponent extends DefaultComponent 
implements VerifiableC
         configuration.setOauthTokenUrl(oauthTokenUrl);
     }
 
+    public String getProxyHost() {
+        return configuration.getProxyHost();
+    }
+
+    /**
+     * The proxy host name
+     * @param proxyHost
+     */
+    @Metadata(label = "advanced")
+    public void setProxyHost(String proxyHost) {
+        configuration.setProxyHost(proxyHost);
+    }
+
+    public Integer getProxyPort() {
+        return configuration.getProxyPort();
+    }
+
+    /**
+     * The proxy port number
+     * @param proxyPort
+     */
+    @Metadata(label = "advanced")
+    public void setProxyPort(Integer proxyPort) {
+        configuration.setProxyPort(proxyPort);
+    }
+
+    public String getProxyUserName() {
+        return configuration.getProxyUserName();
+    }
+
+    /**
+     * Username for proxy authentication
+     * @param proxyUserName
+     */
+    @Metadata(label = "advanced,security", secret = true)
+    public void setProxyUserName(String proxyUserName) {
+        configuration.setProxyUserName(proxyUserName);
+    }
+
+    public String getProxyPassword() {
+        return configuration.getProxyPassword();
+    }
+
+    /**
+     * Password for proxy authentication
+     * @param proxyPassword
+     */
+    @Metadata(label = "advanced,security", secret = true)
+    public void setProxyPassword(String proxyPassword) {
+        configuration.setProxyPassword(proxyPassword);
+    }
+
     @Override
     public boolean isUseGlobalSslContextParameters() {
         return this.useGlobalSslContextParameters;
@@ -223,4 +221,57 @@ public class ServiceNowComponent extends DefaultComponent 
implements VerifiableC
     public ComponentVerifier getVerifier() {
         return (scope, parameters) -> 
getExtension(ComponentVerifierExtension.class).orElseThrow(UnsupportedOperationException::new).verify(scope,
 parameters);
     }
+
+    // ****************************************
+    // Component impl
+    // ****************************************
+
+    @Override
+    protected Endpoint createEndpoint(String uri, String remaining, 
Map<String, Object> parameters) throws Exception {
+        final CamelContext context = getCamelContext();
+        final ServiceNowConfiguration configuration = 
this.configuration.copy();
+
+        Map<String, Object> models = 
IntrospectionSupport.extractProperties(parameters, "model.");
+        for (Map.Entry<String, Object> entry : models.entrySet()) {
+            configuration.addModel(
+                entry.getKey(),
+                EndpointHelper.resolveParameter(context, 
(String)entry.getValue(), Class.class));
+        }
+
+        Map<String, Object> requestModels = 
IntrospectionSupport.extractProperties(parameters, "requestModel.");
+        for (Map.Entry<String, Object> entry : requestModels.entrySet()) {
+            configuration.addRequestModel(
+                entry.getKey(),
+                EndpointHelper.resolveParameter(context, 
(String)entry.getValue(), Class.class));
+        }
+
+        Map<String, Object> responseModels = 
IntrospectionSupport.extractProperties(parameters, "responseModel.");
+        for (Map.Entry<String, Object> entry : responseModels.entrySet()) {
+            configuration.addResponseModel(
+                entry.getKey(),
+                EndpointHelper.resolveParameter(context, 
(String)entry.getValue(), Class.class));
+        }
+
+        setProperties(configuration, parameters);
+
+        if (ObjectHelper.isEmpty(remaining)) {
+            // If an instance is not set on the endpoint uri, use the one set 
on
+            // component.
+            remaining = instanceName;
+        }
+
+        String instanceName = 
getCamelContext().resolvePropertyPlaceholders(remaining);
+        if (!configuration.hasApiUrl()) {
+            
configuration.setApiUrl(String.format("https://%s.service-now.com/api";, 
instanceName));
+        }
+        if (!configuration.hasOauthTokenUrl()) {
+            
configuration.setOauthTokenUrl(String.format("https://%s.service-now.com/oauth_token.do";,
 instanceName));
+        }
+
+        if (configuration.getSslContextParameters() == null) {
+            
configuration.setSslContextParameters(retrieveGlobalSslContextParameters());
+        }
+
+        return new ServiceNowEndpoint(uri, this, configuration, instanceName);
+    }
 }

http://git-wip-us.apache.org/repos/asf/camel/blob/00d1d70b/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/ServiceNowComponentVerifierExtension.java
----------------------------------------------------------------------
diff --git 
a/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/ServiceNowComponentVerifierExtension.java
 
b/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/ServiceNowComponentVerifierExtension.java
index 0422238..8a0222a 100644
--- 
a/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/ServiceNowComponentVerifierExtension.java
+++ 
b/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/ServiceNowComponentVerifierExtension.java
@@ -24,6 +24,7 @@ import 
org.apache.camel.component.extension.verifier.DefaultComponentVerifierExt
 import org.apache.camel.component.extension.verifier.NoSuchOptionException;
 import org.apache.camel.component.extension.verifier.ResultBuilder;
 import org.apache.camel.component.extension.verifier.ResultErrorBuilder;
+import org.apache.camel.util.ObjectHelper;
 
 final class ServiceNowComponentVerifierExtension extends 
DefaultComponentVerifierExtension {
 
@@ -55,28 +56,18 @@ final class ServiceNowComponentVerifierExtension extends 
DefaultComponentVerifie
         ResultBuilder builder = 
ResultBuilder.withStatusAndScope(Result.Status.OK, Scope.CONNECTIVITY);
 
         try {
-            // Load ServiceNow Configuration
-            ServiceNowConfiguration configuration = new 
ServiceNowConfiguration();
-            setProperties(configuration, parameters);
-
-            String instanceName = getMandatoryOption(parameters, 
"instanceName", String.class);
-            String tableName = configuration.getTable() != null ? 
configuration.getTable() : "incident";
-
-            // Configure Api and OAuthToken ULRs using instanceName
-            if (!configuration.hasApiUrl()) {
-                
configuration.setApiUrl(String.format("https://%s.service-now.com/api";, 
instanceName));
-            }
-            if (!configuration.hasOauthTokenUrl()) {
-                
configuration.setOauthTokenUrl(String.format("https://%s.service-now.com/oauth_token.do";,
 instanceName));
-            }
+            final ServiceNowConfiguration configuration = 
getServiceNowConfiguration(parameters);
+            final ServiceNowClient client = getServiceNowClient(configuration, 
parameters);
+            final String tableName = 
ObjectHelper.supplyIfEmpty(configuration.getTable(), () -> "incident");
 
-            new ServiceNowClient(getCamelContext(), configuration)
+            client.reset()
                 .types(MediaType.APPLICATION_JSON_TYPE)
                 .path("now")
                 .path(configuration.getApiVersion())
                 .path("table")
                 .path(tableName)
                 .query(ServiceNowParams.SYSPARM_LIMIT.getId(), 1L)
+                .query(ServiceNowParams.SYSPARM_FIELDS.getId(), "sys_id")
                 .invoke(HttpMethod.GET);
         } catch (NoSuchOptionException e) {
             builder.error(
@@ -106,4 +97,78 @@ final class ServiceNowComponentVerifierExtension extends 
DefaultComponentVerifie
 
         return builder.build();
     }
+
+    // *********************************
+    // Helpers
+    // *********************************
+
+    private String getInstanceName(Map<String, Object> parameters) throws 
Exception {
+        String instanceName = (String)parameters.get("instanceName");
+        if (ObjectHelper.isEmpty(instanceName) && 
ObjectHelper.isNotEmpty(getComponent())) {
+            instanceName = 
getComponent(ServiceNowComponent.class).getInstanceName();
+        }
+
+        if (ObjectHelper.isEmpty(instanceName)) {
+            throw new NoSuchOptionException("instanceName");
+        }
+
+        return instanceName;
+    }
+
+    private ServiceNowClient getServiceNowClient(ServiceNowConfiguration 
configuration, Map<String, Object> parameters) throws Exception {
+        ServiceNowClient client = null;
+
+        // check if a client has been supplied to the parameters map
+        for (Object value : parameters.values()) {
+            if (value instanceof ServiceNowClient) {
+                client = ServiceNowClient.class.cast(value);
+                break;
+            }
+        }
+
+        // if no client is provided
+        if (ObjectHelper.isEmpty(client)) {
+            final String instanceName = getInstanceName(parameters);
+
+            // Configure Api and OAuthToken ULRs using instanceName
+            if (!configuration.hasApiUrl()) {
+                
configuration.setApiUrl(String.format("https://%s.service-now.com/api";, 
instanceName));
+            }
+            if (!configuration.hasOauthTokenUrl()) {
+                
configuration.setOauthTokenUrl(String.format("https://%s.service-now.com/oauth_token.do";,
 instanceName));
+            }
+
+            client = new ServiceNowClient(getCamelContext(), configuration);
+        }
+
+        return client;
+    }
+
+    private ServiceNowConfiguration getServiceNowConfiguration(Map<String, 
Object> parameters) throws Exception {
+        ServiceNowConfiguration configuration = null;
+
+        // check if a configuration has been supplied to the parameters map
+        for (Object value : parameters.values()) {
+            if (value instanceof ServiceNowConfiguration) {
+                configuration = ServiceNowConfiguration.class.cast(value);
+                break;
+            }
+        }
+
+        // if no configuration is provided
+        if (ObjectHelper.isEmpty(configuration)) {
+            if (ObjectHelper.isNotEmpty(getComponent())) {
+                configuration = 
getComponent(ServiceNowComponent.class).getConfiguration().copy();
+            } else {
+                configuration = new ServiceNowConfiguration();
+            }
+
+            // bind parameters to ServiceNow Configuration only if 
configuration
+            // does not come from the parameters map as in that case we expect
+            // it to be pre-configured.
+            setProperties(configuration, parameters);
+        }
+
+        return configuration;
+    }
 }

http://git-wip-us.apache.org/repos/asf/camel/blob/00d1d70b/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/ServiceNowConstants.java
----------------------------------------------------------------------
diff --git 
a/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/ServiceNowConstants.java
 
b/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/ServiceNowConstants.java
index 955f389..fece6d6 100644
--- 
a/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/ServiceNowConstants.java
+++ 
b/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/ServiceNowConstants.java
@@ -17,6 +17,8 @@
 package org.apache.camel.component.servicenow;
 
 public final class ServiceNowConstants {
+    public static final String COMPONENT_SCHEME = "servicenow";
+
     public static final String CAMEL_HEADER_PREFIX = "CamelServiceNow";
 
     public static final String RESOURCE = "CamelServiceNowResource";

http://git-wip-us.apache.org/repos/asf/camel/blob/00d1d70b/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/auth/AuthenticationRequestFilter.java
----------------------------------------------------------------------
diff --git 
a/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/auth/AuthenticationRequestFilter.java
 
b/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/auth/AuthenticationRequestFilter.java
index 4689455..7f563f7 100644
--- 
a/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/auth/AuthenticationRequestFilter.java
+++ 
b/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/auth/AuthenticationRequestFilter.java
@@ -35,7 +35,7 @@ public final class AuthenticationRequestFilter implements 
ClientRequestFilter {
     private final OAuthToken authToken;
     private final String authString;
 
-    public AuthenticationRequestFilter(ServiceNowConfiguration conf) throws 
IOException {
+    public AuthenticationRequestFilter(ServiceNowConfiguration conf) {
         this.authToken = conf.hasOAuthAuthentication() ? new OAuthToken(conf) 
: null;
         this.authString = conf.hasBasicAuthentication() ? 
getBasicAuthenticationString(conf) : null;
     }

http://git-wip-us.apache.org/repos/asf/camel/blob/00d1d70b/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/CamelAutoConfiguration.java
----------------------------------------------------------------------
diff --git 
a/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/CamelAutoConfiguration.java
 
b/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/CamelAutoConfiguration.java
index 2f99fca..fc6cde6 100644
--- 
a/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/CamelAutoConfiguration.java
+++ 
b/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/CamelAutoConfiguration.java
@@ -31,6 +31,9 @@ import org.apache.camel.TypeConverters;
 import org.apache.camel.component.properties.PropertiesComponent;
 import org.apache.camel.component.properties.PropertiesParser;
 import org.apache.camel.ha.CamelClusterService;
+import org.apache.camel.health.HealthCheckRegistry;
+import org.apache.camel.health.HealthCheckRepository;
+import org.apache.camel.health.HealthCheckService;
 import org.apache.camel.impl.FileWatcherReloadStrategy;
 import org.apache.camel.processor.interceptor.BacklogTracer;
 import org.apache.camel.processor.interceptor.DefaultTraceFormatter;
@@ -475,7 +478,29 @@ public class CamelAutoConfiguration {
         if (sslContextParametersSupplier != null) {
             
camelContext.setSSLContextParameters(sslContextParametersSupplier.get());
         }
-
+        // Health check registry
+        HealthCheckRegistry healthCheckRegistry = 
getSingleBeanOfType(applicationContext, HealthCheckRegistry.class);
+        if (healthCheckRegistry != null) {
+            healthCheckRegistry.setCamelContext(camelContext);
+            LOG.info("Using HealthCheckRegistry: {}", healthCheckRegistry);
+            camelContext.setHealthCheckRegistry(healthCheckRegistry);
+        } else {
+            healthCheckRegistry = camelContext.getHealthCheckRegistry();
+            healthCheckRegistry.setCamelContext(camelContext);
+        }
+        // Health check repository
+        Map<String, HealthCheckRepository> repositories = 
applicationContext.getBeansOfType(HealthCheckRepository.class);
+        if (ObjectHelper.isNotEmpty(repositories)) {
+            for (HealthCheckRepository repository: repositories.values()) {
+                healthCheckRegistry.addRepository(repository);
+            }
+        }
+        // Health check service
+        HealthCheckService healthCheckService = 
getSingleBeanOfType(applicationContext, HealthCheckService.class);
+        if (healthCheckService != null) {
+            LOG.info("Using HealthCheckService: {}", healthCheckService);
+            camelContext.addService(healthCheckService);
+        }
         // Route controller
         RouteController routeController = 
getSingleBeanOfType(applicationContext, RouteController.class);
         if (routeController != null) {

http://git-wip-us.apache.org/repos/asf/camel/blob/00d1d70b/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/actuate/endpoint/AbstractCamelEndpoint.java
----------------------------------------------------------------------
diff --git 
a/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/actuate/endpoint/AbstractCamelEndpoint.java
 
b/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/actuate/endpoint/AbstractCamelEndpoint.java
new file mode 100644
index 0000000..532d0d6
--- /dev/null
+++ 
b/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/actuate/endpoint/AbstractCamelEndpoint.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.spring.boot.actuate.endpoint;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.spi.HasCamelContext;
+import org.springframework.boot.actuate.endpoint.AbstractEndpoint;
+import org.springframework.boot.actuate.endpoint.Endpoint;
+
+/**
+ * Abstract camel {@link Endpoint}.
+ */
+abstract class AbstractCamelEndpoint<T> extends AbstractEndpoint<T> implements 
HasCamelContext {
+    private final CamelContext camelContext;
+
+    protected AbstractCamelEndpoint(String id, CamelContext camelContext) {
+        super(id);
+        this.camelContext = camelContext;
+
+        // is enabled by default
+        this.setEnabled(true);
+    }
+
+    @Override
+    public CamelContext getCamelContext() {
+        return this.camelContext;
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/00d1d70b/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/actuate/endpoint/AbstractCamelMvcEndpoint.java
----------------------------------------------------------------------
diff --git 
a/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/actuate/endpoint/AbstractCamelMvcEndpoint.java
 
b/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/actuate/endpoint/AbstractCamelMvcEndpoint.java
new file mode 100644
index 0000000..991c508
--- /dev/null
+++ 
b/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/actuate/endpoint/AbstractCamelMvcEndpoint.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.spring.boot.actuate.endpoint;
+
+import java.util.function.Function;
+import java.util.function.Supplier;
+
+import org.springframework.boot.actuate.endpoint.Endpoint;
+import org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter;
+import org.springframework.boot.actuate.endpoint.mvc.MvcEndpoint;
+import org.springframework.http.HttpStatus;
+import org.springframework.web.bind.annotation.ResponseStatus;
+
+/**
+ * Adapter to expose {@link T} as an {@link MvcEndpoint}.
+ */
+abstract class AbstractCamelMvcEndpoint<T extends Endpoint> extends 
EndpointMvcAdapter {
+    private final T delegate;
+
+    protected AbstractCamelMvcEndpoint(String path, T delegate) {
+        super(delegate);
+        this.delegate = delegate;
+
+        setPath(path);
+    }
+
+    // ********************************************
+    // Helpers
+    // ********************************************
+
+    protected T delegate() {
+        return this.delegate;
+    }
+
+    protected Object doIfEnabled(Supplier<Object> supplier) {
+        if (!delegate.isEnabled()) {
+            return getDisabledResponse();
+        }
+
+        return supplier.get();
+    }
+
+    protected Object doIfEnabled(Function<T, Object> supplier) {
+        if (!delegate.isEnabled()) {
+            return getDisabledResponse();
+        }
+
+        return supplier.apply(delegate);
+    }
+
+    @SuppressWarnings("serial")
+    @ResponseStatus(value = HttpStatus.INTERNAL_SERVER_ERROR)
+    public static class GenericException extends RuntimeException {
+        public GenericException(String message, Throwable cause) {
+            super(message, cause);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/00d1d70b/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/actuate/endpoint/CamelHealthCheckEndpoint.java
----------------------------------------------------------------------
diff --git 
a/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/actuate/endpoint/CamelHealthCheckEndpoint.java
 
b/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/actuate/endpoint/CamelHealthCheckEndpoint.java
new file mode 100644
index 0000000..a55aca2
--- /dev/null
+++ 
b/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/actuate/endpoint/CamelHealthCheckEndpoint.java
@@ -0,0 +1,180 @@
+/**
+ * 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.boot.actuate.endpoint;
+
+import java.time.Duration;
+import java.util.Collection;
+import java.util.Map;
+import java.util.Optional;
+
+import static java.util.stream.Collectors.toList;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonPropertyOrder;
+import org.apache.camel.CamelContext;
+import org.apache.camel.health.HealthCheck;
+import org.apache.camel.health.HealthCheckConfiguration;
+import org.apache.camel.health.HealthCheckHelper;
+import org.apache.camel.util.ObjectHelper;
+import org.springframework.boot.actuate.endpoint.Endpoint;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+
+/**
+ * {@link Endpoint} to expose {@link org.apache.camel.health.HealthCheck} 
information.
+ */
+@ConfigurationProperties(prefix = "endpoints." + 
CamelHealthCheckEndpoint.ENDPOINT_ID)
+public class CamelHealthCheckEndpoint extends 
AbstractCamelEndpoint<Collection<CamelHealthCheckEndpoint.HealthCheckResult>> {
+    public static final String ENDPOINT_ID = "camelhealthcheck";
+
+    public CamelHealthCheckEndpoint(CamelContext camelContext) {
+        super(ENDPOINT_ID, camelContext);
+    }
+
+    @Override
+    public Collection<HealthCheckResult> invoke() {
+        return HealthCheckHelper.invoke(getCamelContext()).stream()
+            .map(result -> new HealthCheckResult(result, new Check(result)))
+            .collect(toList());
+    }
+
+    // ****************************************
+    // Used by CamelHealthCheckMvcEndpoint
+    // ****************************************
+
+    Optional<HealthCheckResult> query(String id, Map<String, Object> options) {
+        return HealthCheckHelper.query(getCamelContext(), id, options)
+            .map(result -> new DetailedHealthCheckResult(result, new 
DetailedCheck(result)));
+    }
+
+    Optional<HealthCheckResult> invoke(String id, Map<String, Object> options) 
{
+        return HealthCheckHelper.invoke(getCamelContext(), id, options)
+            .map(result -> new DetailedHealthCheckResult(result, new 
DetailedCheck(result)));
+    }
+
+    // ****************************************
+    // Wrappers
+    // ****************************************
+
+    @JsonInclude(JsonInclude.Include.NON_EMPTY)
+    @JsonPropertyOrder({"enabled", "interval", "failureThreshold"})
+    public static class CheckConfiguration {
+        protected final HealthCheckConfiguration configuration;
+
+        public CheckConfiguration(HealthCheckConfiguration configuration) {
+            this.configuration = ObjectHelper.supplyIfEmpty(configuration, 
HealthCheckConfiguration::new);
+        }
+
+        @JsonProperty("enabled")
+        public Boolean isEnabled() {
+            return configuration.isEnabled();
+        }
+
+        @JsonProperty("interval")
+        public String getDuration() {
+            Duration interval = configuration.getInterval();
+            return interval != null ? interval.toString() : null;
+        }
+
+        @JsonProperty("failureThreshold")
+        public Integer getFailureThreshold() {
+            return configuration.getFailureThreshold();
+        }
+    }
+
+    @JsonInclude(JsonInclude.Include.NON_EMPTY)
+    @JsonPropertyOrder({"id", "group"})
+    public static class Check {
+        protected final HealthCheck.Result result;
+
+        public Check(HealthCheck.Result result) {
+            this.result = result;
+        }
+
+        @JsonProperty("id")
+        public String getId() {
+            return result.getCheck().getId();
+        }
+
+        @JsonProperty("group")
+        public String getGroup() {
+            return result.getCheck().getGroup();
+        }
+    }
+
+    @JsonInclude(JsonInclude.Include.NON_EMPTY)
+    @JsonPropertyOrder({"status", "message", "check"})
+    public static class HealthCheckResult {
+        protected final HealthCheck.Result result;
+        protected final Check check;
+
+        public HealthCheckResult(HealthCheck.Result result, Check check) {
+            this.result = result;
+            this.check = check;
+        }
+
+        @JsonProperty("status")
+        public String getStatus() {
+            return result.getState().name();
+        }
+
+        @JsonProperty("message")
+        public String getMessage() {
+            return result.getMessage().orElse(null);
+        }
+
+        @JsonProperty("check")
+        public Check getCheck() {
+            return this.check;
+        }
+    }
+
+    @JsonInclude(JsonInclude.Include.NON_EMPTY)
+    @JsonPropertyOrder({"id", "group", "metaData"})
+    public static class DetailedCheck extends Check {
+        private CheckConfiguration configuration;
+
+        public DetailedCheck(HealthCheck.Result result) {
+            super(result);
+
+            this.configuration = new 
CheckConfiguration(result.getCheck().getConfiguration());
+        }
+
+        @JsonProperty("configuration")
+        public CheckConfiguration getConfiguration() {
+            return this.configuration;
+        }
+
+        @JsonProperty("metaData")
+        public Map<String, Object> getMeta() {
+            return result.getCheck().getMetaData();
+        }
+    }
+
+    @JsonInclude(JsonInclude.Include.NON_EMPTY)
+    @JsonPropertyOrder({"status", "message", "details", "check"})
+    public static class DetailedHealthCheckResult extends HealthCheckResult {
+        public DetailedHealthCheckResult(HealthCheck.Result result, Check 
check) {
+            super(result, check);
+        }
+
+        @JsonProperty("details")
+        public Map<String, Object> getDetails() {
+            return result.getDetails();
+        }
+    }
+}

Reply via email to