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/08/04 16:09:52 UTC

[01/19] camel git commit: CAMEL-11554: ServiceNow : add meta data extension to retrieve table's structure

Repository: camel
Updated Branches:
  refs/heads/master f3472922a -> 109da7c9a


CAMEL-11554: ServiceNow : add meta data extension to retrieve table's structure


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

Branch: refs/heads/master
Commit: 79172c339e856df992ebbe5bf417d06a10721439
Parents: 4252939
Author: lburgazzoli <lb...@gmail.com>
Authored: Thu Jul 20 18:17:52 2017 +0200
Committer: lburgazzoli <lb...@gmail.com>
Committed: Fri Aug 4 18:09:04 2017 +0200

----------------------------------------------------------------------
 .../src/main/docs/servicenow-component.adoc     |   3 +-
 .../servicenow/AbstractServiceNowProcessor.java |  39 +-
 .../component/servicenow/ServiceNowClient.java  |  46 +-
 .../servicenow/ServiceNowComponent.java         |  51 ++-
 .../ServiceNowComponentVerifierExtension.java   |   9 +-
 .../servicenow/ServiceNowEndpoint.java          |   2 +-
 .../component/servicenow/ServiceNowHelper.java  |  95 ++++
 .../servicenow/ServiceNowMetaDataExtension.java | 457 +++++++++++++++++++
 .../servicenow/model/DictionaryEntry.java       |  56 +++
 .../component/servicenow/model/Reference.java   |  56 +++
 .../ServiceNowComponentVerifierTest.java        |   7 +-
 .../ServiceNowMetaDataExtensionTest.java        |  87 ++++
 .../src/test/resources/log4j2.properties        |  15 +-
 .../ServiceNowComponentConfiguration.java       |  12 +
 14 files changed, 850 insertions(+), 85 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/camel/blob/79172c33/components/camel-servicenow/src/main/docs/servicenow-component.adoc
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/src/main/docs/servicenow-component.adoc b/components/camel-servicenow/src/main/docs/servicenow-component.adoc
index b946415..af9bc01 100644
--- a/components/camel-servicenow/src/main/docs/servicenow-component.adoc
+++ b/components/camel-servicenow/src/main/docs/servicenow-component.adoc
@@ -30,13 +30,14 @@ for this component:
 
 
 // component options: START
-The ServiceNow component supports 9 options which are listed below.
+The ServiceNow component supports 10 options which are listed below.
 
 
 
 [width="100%",cols="2,5,^1,2",options="header"]
 |=======================================================================
 | Name | Description | Default | Type
+| **instanceName** (advanced) | The ServiceNow instance name |  | String
 | **configuration** (advanced) | The ServiceNow default configuration |  | ServiceNowConfiguration
 | **apiUrl** (producer) | The ServiceNow REST API url |  | String
 | **userName** (security) | ServiceNow user account name |  | String

http://git-wip-us.apache.org/repos/asf/camel/blob/79172c33/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/AbstractServiceNowProcessor.java
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/AbstractServiceNowProcessor.java b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/AbstractServiceNowProcessor.java
index 6dc66a3..ab2d824 100644
--- a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/AbstractServiceNowProcessor.java
+++ b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/AbstractServiceNowProcessor.java
@@ -32,8 +32,6 @@ import org.apache.camel.Exchange;
 import org.apache.camel.Message;
 import org.apache.camel.Processor;
 import org.apache.camel.util.ObjectHelper;
-import org.apache.camel.util.StringHelper;
-import org.apache.camel.util.URISupport;
 
 public abstract class AbstractServiceNowProcessor implements Processor {
 
@@ -79,43 +77,8 @@ public abstract class AbstractServiceNowProcessor implements Processor {
     // Header
     // *********************************
 
-
     protected AbstractServiceNowProcessor setHeaders(Message message, Class<?> responseModel, Response response) throws Exception {
-        List<String> links = response.getStringHeaders().get(HttpHeaders.LINK);
-        if (links != null) {
-            for (String link : links) {
-                String[] parts = link.split(";");
-                if (parts.length != 2) {
-                    continue;
-                }
-
-                // Sanitize parts
-                String uri = StringHelper.between(parts[0], "<", ">");
-                String rel = StringHelper.removeQuotes(StringHelper.after(parts[1], "="));
-
-                Map<String, Object> query = URISupport.parseQuery(uri);
-                Object offset = query.get(ServiceNowParams.SYSPARM_OFFSET.getId());
-
-                if (offset != null) {
-                    switch (rel) {
-                    case ServiceNowConstants.LINK_FIRST:
-                        message.setHeader(ServiceNowConstants.OFFSET_FIRST, offset);
-                        break;
-                    case ServiceNowConstants.LINK_LAST:
-                        message.setHeader(ServiceNowConstants.OFFSET_LAST, offset);
-                        break;
-                    case ServiceNowConstants.LINK_NEXT:
-                        message.setHeader(ServiceNowConstants.OFFSET_NEXT, offset);
-                        break;
-                    case ServiceNowConstants.LINK_PREV:
-                        message.setHeader(ServiceNowConstants.OFFSET_PREV, offset);
-                        break;
-                    default:
-                        break;
-                    }
-                }
-            }
-        }
+        ServiceNowHelper.findOffsets(response, (k, v) -> message.setHeader(k, v));
 
         String attachmentMeta = response.getHeaderString(ServiceNowConstants.ATTACHMENT_META_HEADER);
         if (ObjectHelper.isNotEmpty(attachmentMeta)) {

http://git-wip-us.apache.org/repos/asf/camel/blob/79172c33/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowClient.java
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowClient.java b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowClient.java
index 465a692..6157ecf 100644
--- a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowClient.java
+++ b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowClient.java
@@ -18,6 +18,7 @@ package org.apache.camel.component.servicenow;
 
 import java.util.Arrays;
 import java.util.Map;
+import java.util.function.Function;
 import javax.net.ssl.SSLContext;
 import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Response;
@@ -34,10 +35,12 @@ import org.apache.cxf.transport.http.HTTPConduit;
 import org.apache.cxf.transports.http.configuration.HTTPClientPolicy;
 
 public final class ServiceNowClient {
+    private final CamelContext camelContext;
     private final ServiceNowConfiguration configuration;
     private final WebClient client;
 
     ServiceNowClient(CamelContext camelContext, ServiceNowConfiguration configuration) throws Exception {
+        this.camelContext = camelContext;
         this.configuration = configuration;
         this.client = WebClient.create(
             configuration.getApiUrl(),
@@ -97,6 +100,11 @@ public final class ServiceNowClient {
         return this;
     }
 
+    public ServiceNowClient queryF(String name, String format, Object... values) {
+        client.query(name, String.format(format, values));
+        return this;
+    }
+
     public ServiceNowClient query(ServiceNowParam param, Message message) {
         Object value = param.getHeaderValue(message, configuration);
         if (value != null) {
@@ -107,10 +115,34 @@ public final class ServiceNowClient {
     }
 
     public Response invoke(String httpMethod) throws Exception {
-        return invoke(httpMethod, null);
+        return invoke(client, httpMethod, null);
     }
 
     public Response invoke(String httpMethod, Object body) throws Exception {
+        return invoke(client, httpMethod, body);
+    }
+
+    public <T> T trasform(String httpMethod, Function<Response, T> function) throws Exception {
+        return function.apply(invoke(client, httpMethod, null));
+    }
+
+    public <T> T trasform(String httpMethod, Object body, Function<Response, T> function) throws Exception {
+        return function.apply(invoke(client, httpMethod, body));
+    }
+
+    public ServiceNowClient reset() {
+        client.back(true);
+        client.reset();
+        client.resetQuery();
+
+        return this;
+    }
+
+    // *******************************
+    // Helpers
+    // *******************************
+
+    private Response invoke(WebClient client, String httpMethod, Object body) throws Exception {
         Response response = client.invoke(httpMethod, body);
         int code = response.getStatus();
 
@@ -146,18 +178,6 @@ public final class ServiceNowClient {
         return response;
     }
 
-    public ServiceNowClient reset() {
-        client.back(true);
-        client.reset();
-        client.resetQuery();
-
-        return this;
-    }
-
-    // *******************************
-    // Helpers
-    // *******************************
-
     private static void configureRequestContext(
             CamelContext context, ServiceNowConfiguration configuration, WebClient client) throws Exception {
 

http://git-wip-us.apache.org/repos/asf/camel/blob/79172c33/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowComponent.java
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowComponent.java b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowComponent.java
index ff414c8..c9cbb89 100644
--- a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowComponent.java
+++ b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowComponent.java
@@ -16,10 +16,9 @@
  */
 package org.apache.camel.component.servicenow;
 
+import java.util.Arrays;
 import java.util.Collection;
-import java.util.Collections;
 import java.util.Map;
-import java.util.Optional;
 
 import org.apache.camel.CamelContext;
 import org.apache.camel.ComponentVerifier;
@@ -28,30 +27,41 @@ 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;
 import org.apache.camel.util.IntrospectionSupport;
+import org.apache.camel.util.ObjectHelper;
 
 /**
  * Represents the component that manages {@link ServiceNowEndpoint}.
  */
 @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")
     private ServiceNowConfiguration configuration;
     @Metadata(label = "security", defaultValue = "false")
     private boolean useGlobalSslContextParameters;
 
+    private ServiceNowComponentVerifierExtension verifierExtension;
+    private ServiceNowMetaDataExtension metaDataExtension;
+
     public ServiceNowComponent() {
-        this.configuration = new ServiceNowConfiguration();
+        this(null);
     }
 
     public ServiceNowComponent(CamelContext camelContext) {
         super(camelContext);
 
         this.configuration = new ServiceNowConfiguration();
+
+        registerExtension(ServiceNowComponentVerifierExtension::new);
+        registerExtension(ServiceNowMetaDataExtension::new);
     }
 
     @Override
@@ -82,6 +92,12 @@ public class ServiceNowComponent extends DefaultComponent implements VerifiableC
 
         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));
@@ -97,6 +113,17 @@ public class ServiceNowComponent extends DefaultComponent implements VerifiableC
         return new ServiceNowEndpoint(uri, this, configuration, instanceName);
     }
 
+    public String getInstanceName() {
+        return instanceName;
+    }
+
+    /**
+     * The ServiceNow instance name
+     */
+    public void setInstanceName(String instanceName) {
+        this.instanceName = instanceName;
+    }
+
     public ServiceNowConfiguration getConfiguration() {
         return configuration;
     }
@@ -194,22 +221,6 @@ public class ServiceNowComponent extends DefaultComponent implements VerifiableC
 
     @Override
     public ComponentVerifier getVerifier() {
-        return new ServiceNowComponentVerifierExtension(this);
-    }
-
-    @Override
-    public Collection<Class<? extends ComponentExtension>> getExtensionTypes() {
-        return Collections.singletonList(ComponentVerifierExtension.class);
-    }
-
-    @Override
-    public <T extends ComponentExtension> Optional<T> getExtension(Class<T> extensionType) {
-        if (ComponentVerifierExtension.class.isAssignableFrom(extensionType)) {
-            return Optional.of(
-                extensionType.cast(new ServiceNowComponentVerifierExtension(this))
-            );
-        }
-
-        return Optional.empty();
+        return (scope, parameters) -> getExtension(ComponentVerifierExtension.class).orElseThrow(UnsupportedOperationException::new).verify(scope, parameters);
     }
 }

http://git-wip-us.apache.org/repos/asf/camel/blob/79172c33/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowComponentVerifierExtension.java
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowComponentVerifierExtension.java b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowComponentVerifierExtension.java
index 96313d2..0422238 100644
--- a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowComponentVerifierExtension.java
+++ b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowComponentVerifierExtension.java
@@ -25,13 +25,10 @@ import org.apache.camel.component.extension.verifier.NoSuchOptionException;
 import org.apache.camel.component.extension.verifier.ResultBuilder;
 import org.apache.camel.component.extension.verifier.ResultErrorBuilder;
 
-public class ServiceNowComponentVerifierExtension extends DefaultComponentVerifierExtension {
-    private final ServiceNowComponent component;
+final class ServiceNowComponentVerifierExtension extends DefaultComponentVerifierExtension {
 
-    ServiceNowComponentVerifierExtension(ServiceNowComponent component) {
-        super("servicenow", component.getCamelContext());
-
-        this.component = component;
+    ServiceNowComponentVerifierExtension() {
+        super("servicenow");
     }
 
     // *********************************

http://git-wip-us.apache.org/repos/asf/camel/blob/79172c33/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowEndpoint.java
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowEndpoint.java b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowEndpoint.java
index 23e6334..dcf3563 100644
--- a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowEndpoint.java
+++ b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowEndpoint.java
@@ -34,7 +34,7 @@ import org.slf4j.LoggerFactory;
 public class ServiceNowEndpoint extends DefaultEndpoint {
     private static final Logger LOGGER = LoggerFactory.getLogger(ServiceNowEndpoint.class);
 
-    @UriPath(description = "The ServiceNow instance name ")
+    @UriPath(description = "The ServiceNow instance name")
     @Metadata(required = "true")
     private final String instanceName;
 

http://git-wip-us.apache.org/repos/asf/camel/blob/79172c33/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowHelper.java
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowHelper.java b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowHelper.java
new file mode 100644
index 0000000..2d9b70e
--- /dev/null
+++ b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowHelper.java
@@ -0,0 +1,95 @@
+/**
+ * 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.servicenow;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.function.BiConsumer;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.Response;
+
+import org.apache.camel.util.StringHelper;
+import org.apache.camel.util.URISupport;
+
+public final class ServiceNowHelper {
+    private ServiceNowHelper() {
+    }
+
+    public static void findOffsets(Response response, BiConsumer<String, Object> consumer) throws Exception {
+        List<String> links = response.getStringHeaders().get(HttpHeaders.LINK);
+        if (links != null) {
+            for (String link : links) {
+                String[] parts = link.split(";");
+                if (parts.length != 2) {
+                    continue;
+                }
+
+                // Sanitize parts
+                String uri = StringHelper.between(parts[0], "<", ">");
+                String rel = StringHelper.removeQuotes(StringHelper.after(parts[1], "="));
+
+                Map<String, Object> query = URISupport.parseQuery(uri);
+                Object offset = query.get(ServiceNowParams.SYSPARM_OFFSET.getId());
+
+                if (offset != null) {
+                    switch (rel) {
+                    case ServiceNowConstants.LINK_FIRST:
+                        consumer.accept(ServiceNowConstants.OFFSET_FIRST, offset);
+                        break;
+                    case ServiceNowConstants.LINK_LAST:
+                        consumer.accept(ServiceNowConstants.OFFSET_LAST, offset);
+                        break;
+                    case ServiceNowConstants.LINK_NEXT:
+                        consumer.accept(ServiceNowConstants.OFFSET_NEXT, offset);
+                        break;
+                    case ServiceNowConstants.LINK_PREV:
+                        consumer.accept(ServiceNowConstants.OFFSET_PREV, offset);
+                        break;
+                    default:
+                        break;
+                    }
+                }
+            }
+        }
+    }
+
+    public static Optional<String> findOffset(Response response, String type) throws Exception {
+        List<String> links = response.getStringHeaders().get(HttpHeaders.LINK);
+        if (links != null) {
+            for (String link : links) {
+                String[] parts = link.split(";");
+                if (parts.length != 2) {
+                    continue;
+                }
+
+                // Sanitize parts
+                String uri = StringHelper.between(parts[0], "<", ">");
+                String rel = StringHelper.removeQuotes(StringHelper.after(parts[1], "="));
+
+                Map<String, Object> query = URISupport.parseQuery(uri);
+                Object offset = query.get(ServiceNowParams.SYSPARM_OFFSET.getId());
+
+                if (offset != null && type.equals(rel)) {
+                    return Optional.of(offset.toString());
+                }
+            }
+        }
+
+        return Optional.empty();
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/79172c33/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowMetaDataExtension.java
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowMetaDataExtension.java b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowMetaDataExtension.java
new file mode 100644
index 0000000..f7e2df8
--- /dev/null
+++ b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowMetaDataExtension.java
@@ -0,0 +1,457 @@
+/**
+ * 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.servicenow;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.Stack;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import java.util.function.Consumer;
+import java.util.regex.Pattern;
+import java.util.stream.Stream;
+import javax.ws.rs.HttpMethod;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import org.apache.camel.RuntimeCamelException;
+import org.apache.camel.component.extension.MetaDataExtension;
+import org.apache.camel.component.extension.metadata.AbstractMetaDataExtension;
+import org.apache.camel.component.extension.metadata.MetaDataBuilder;
+import org.apache.camel.component.servicenow.model.DictionaryEntry;
+import org.apache.camel.util.IntrospectionSupport;
+import org.apache.camel.util.ObjectHelper;
+import org.apache.camel.util.StringHelper;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+final class ServiceNowMetaDataExtension extends AbstractMetaDataExtension {
+    private static final Logger LOGGER = LoggerFactory.getLogger(ServiceNowMetaDataExtension.class);
+    private final ConcurrentMap<String, String> properties;
+
+    ServiceNowMetaDataExtension() {
+        this.properties = new ConcurrentHashMap<>();
+    }
+
+    @Override
+    public Optional<MetaDataExtension.MetaData> meta(Map<String, Object> parameters) {
+        try {
+            final MetaContext context = new MetaContext(parameters);
+
+            if (!ObjectHelper.equalIgnoreCase(context.getObjectType(), "table")) {
+                throw new UnsupportedOperationException("Unsupported object type <" + context.getObjectType() + ">");
+            }
+
+            return tableMeta(context);
+
+        } catch (UnsupportedOperationException e) {
+            throw e;
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    private Optional<MetaDataExtension.MetaData> tableMeta(MetaContext context) {
+        try {
+            final List<String> names = getObjectHierarchy(context);
+            final ObjectNode root = context.getConfiguration().getMapper().createObjectNode();
+
+            if (names.isEmpty()) {
+                return Optional.empty();
+            }
+
+            loadProperties(context);
+            registerDefinitions(context, root);
+
+            root.putObject("properties");
+            root.put("$schema", "http://json-schema.org/schema#");
+            root.put("id", "http://camel.apache.org/schemas/servicenow/" + context.getObjectName() + ".json");
+            root.put("type", "object");
+            root.put("additionalProperties", false);
+            root.putArray("required");
+
+            for (String name : names) {
+                context.getStack().push(name);
+
+                LOGGER.debug("Load dictionary <{}>", context.getStack());
+                loadDictionary(context, name, root);
+                context.getStack().pop();
+            }
+
+            return Optional.of(
+                MetaDataBuilder.on(getCamelContext())
+                    .withAttribute(MetaData.CONTENT_TYPE, "application/schema+json")
+                    .withAttribute(MetaData.JAVA_TYPE, JsonNode.class)
+                    .withPayload(root)
+                    .build()
+            );
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    // ********************************
+    // Properties
+    // ********************************
+
+    private synchronized void loadProperties(MetaContext context) {
+        if (!properties.isEmpty()) {
+            return;
+        }
+
+        try {
+            String offset = "0";
+
+            while (true) {
+                Response response = context.getClient().reset()
+                    .types(MediaType.APPLICATION_JSON_TYPE)
+                    .path("now")
+                    .path(context.getConfiguration().getApiVersion())
+                    .path("table")
+                    .path("sys_properties")
+                    .query("sysparm_exclude_reference_link", "true")
+                    .query("sysparm_fields", "name%2Cvalue")
+                    .query("sysparm_offset", offset)
+                    .query("sysparm_query", "name=glide.sys.date_format^ORname=glide.sys.time_format")
+                    .invoke(HttpMethod.GET);
+
+                findResultNode(response).ifPresent(node -> processResult(node, n -> {
+                    if (n.hasNonNull("name") && n.hasNonNull("value")) {
+                        properties.put(
+                            n.findValue("name").asText(),
+                            n.findValue("value").asText()
+                        );
+                    }
+                }));
+
+                Optional<String> next = ServiceNowHelper.findOffset(response, ServiceNowConstants.LINK_NEXT);
+                if (next.isPresent()) {
+                    offset = next.get();
+                } else {
+                    break;
+                }
+            }
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    // ********************************
+    // Definitions
+    // ********************************
+
+    private void registerDefinitions(MetaContext context, ObjectNode root) {
+        final ObjectNode definitions = root.putObject("definitions");
+
+        // Global Unique ID
+        definitions.putObject("guid")
+            .put("type", "string")
+            .put("pattern", "^[a-fA-F0-9]{32}");
+
+        // Date/Time
+        String dateFormat = properties.getOrDefault("glide.sys.date_format", "yyyy-MM-dd");
+        String timeFormat = properties.getOrDefault("glide.sys.time_format", "HH:mm:ss");
+
+        definitions.putObject("date")
+            .put("type", "string")
+            .put("format", dateFormat);
+        definitions.putObject("time")
+            .put("type", "string")
+            .put("format", timeFormat);
+        definitions.putObject("date-time")
+            .put("type", "string")
+            .put("format", dateFormat + " " + timeFormat);
+    }
+
+    // ********************************
+    // Dictionary
+    // ********************************
+
+    private void loadDictionary(MetaContext context, String name, ObjectNode root) throws Exception {
+        String offset = "0";
+
+        while (true) {
+            Response response = context.getClient().reset()
+                .types(MediaType.APPLICATION_JSON_TYPE)
+                .path("now")
+                .path(context.getConfiguration().getApiVersion())
+                .path("table")
+                .path("sys_dictionary")
+                .query("sysparm_display_value", "false")
+                .queryF("sysparm_query", "name=%s", name)
+                .query("sysparm_offset", offset)
+                .invoke(HttpMethod.GET);
+
+            findResultNode(response).ifPresent(node -> processResult(node, n -> {
+                processDictionaryNode(context, root, n);
+            }));
+
+            Optional<String> next = ServiceNowHelper.findOffset(response, ServiceNowConstants.LINK_NEXT);
+            if (next.isPresent()) {
+                offset = next.get();
+            } else {
+                break;
+            }
+        }
+    }
+
+    private void processDictionaryNode(MetaContext context, ObjectNode root, JsonNode node) {
+        if (node.hasNonNull("element")) {
+            final String id = node.get("element").asText();
+
+            if (ObjectHelper.isNotEmpty(id)) {
+                String parent = context.getStack().peek();
+                String includeKey = "object." + parent + ".fields";
+                String fields = (String)context.getParameters().get(includeKey);
+
+                boolean included = false;
+
+                if (ObjectHelper.isNotEmpty(fields)) {
+                    if (Stream.of(fields.split(",")).map(StringHelper::trimToNull).filter(Objects::nonNull).map(Pattern::compile).anyMatch(p -> p.matcher(id).matches())) {
+                        included = true;
+                    }
+                    if (Stream.of(fields.split(",")).map(StringHelper::trimToNull).filter(Objects::nonNull).anyMatch(id::equalsIgnoreCase)) {
+                        included = true;
+                    }
+                } else {
+                    included = !context.getParameters().containsKey(includeKey);
+                }
+
+                if (!included) {
+                    return;
+                }
+
+                context.getStack().push(id);
+                LOGGER.debug("Load dictionary element <{}>", context.getStack());
+
+                try {
+                    final DictionaryEntry entry = context.getConfiguration().getMapper().treeToValue(node, DictionaryEntry.class);
+                    final ObjectNode property = ((ObjectNode)root.get("properties")).putObject(id);
+
+                    // Add custom fields for code generation, json schema
+                    // validators are not supposed to use this extensions.
+                    final ObjectNode servicenow = property.putObject("servicenow");
+
+                    // the internal type
+                    servicenow.put("internal_type", entry.getInternalType().getValue());
+
+                    switch (entry.getInternalType().getValue()) {
+                    case "integer":
+                        property.put("type", "number");
+                        break;
+                    case "boolean":
+                        property.put("type", "boolean");
+                        break;
+                    case "guid":
+                    case "GUID":
+                        property.put("$ref", "#/definitions/guid");
+                        break;
+                    case "glide_date":
+                        property.put("$ref", "#/definitions/date");
+                        break;
+                    case "due_date":
+                    case "glide_date_time":
+                    case "glide_time":
+                    case "glide_duration":
+                        property.put("$ref", "#/definitions/date-time");
+                        break;
+                    case "reference":
+                        property.put("$ref", "#/definitions/guid");
+
+                        if (entry.getReference().getValue() != null) {
+                            // the referenced object type
+                            servicenow.put("sys_db_object", entry.getReference().getValue());
+                        }
+
+                        break;
+                    default:
+                        property.put("type", "string");
+
+                        if (entry.getMaxLength() != null) {
+                            property.put("maxLength", entry.getMaxLength());
+                        }
+                        break;
+                    }
+
+                    if (entry.isMandatory()) {
+                        ArrayNode required = (ArrayNode)root.get("required");
+                        if (required == null) {
+                            required = root.putArray("required");
+                        }
+
+                        required.add(id);
+                    }
+
+                } catch (JsonProcessingException e) {
+                    throw new RuntimeCamelException(e);
+                } finally {
+
+                    context.getStack().pop();
+                }
+            }
+        }
+    }
+
+    // *************************************
+    // Helpers
+    // *************************************
+
+    private List<String> getObjectHierarchy(MetaContext context) throws Exception {
+        List<String> hierarchy = new ArrayList<>();
+        String query = String.format("name=%s", context.getObjectName());
+
+        while (true) {
+            Optional<JsonNode> response = context.getClient().reset()
+                .types(MediaType.APPLICATION_JSON_TYPE)
+                .path("now")
+                .path(context.getConfiguration().getApiVersion())
+                .path("table")
+                .path("sys_db_object")
+                .query("sysparm_exclude_reference_link", "true")
+                .query("sysparm_fields", "name%2Csuper_class")
+                .query("sysparm_query", query)
+                .trasform(HttpMethod.GET, this::findResultNode);
+
+            if (response.isPresent()) {
+                JsonNode node = response.get();
+                JsonNode nameNode = node.findValue("name");
+                JsonNode classNode = node.findValue("super_class");
+
+                if (nameNode != null && classNode != null) {
+                    query = String.format("sys_id=%s", classNode.textValue());
+                    hierarchy.add(0, nameNode.textValue());
+                } else {
+                    break;
+                }
+            } else {
+                break;
+            }
+        }
+
+        return hierarchy;
+    }
+
+    private void processResult(JsonNode node, Consumer<JsonNode> consumer) {
+        if (node.isArray()) {
+            Iterator<JsonNode> it = node.elements();
+            while (it.hasNext()) {
+                consumer.accept(it.next());
+            }
+        } else {
+            consumer.accept(node);
+        }
+    }
+
+    private Optional<JsonNode> findResultNode(Response response) {
+        if (ObjectHelper.isNotEmpty(response.getHeaderString(HttpHeaders.CONTENT_TYPE))) {
+            JsonNode root = response.readEntity(JsonNode.class);
+            if (root != null) {
+                Iterator<Map.Entry<String, JsonNode>> fields = root.fields();
+                while (fields.hasNext()) {
+                    final Map.Entry<String, JsonNode> entry = fields.next();
+                    final String key = entry.getKey();
+                    final JsonNode node = entry.getValue();
+
+                    if (ObjectHelper.equal("result", key, true)) {
+                        return Optional.of(node);
+                    }
+                }
+            }
+        }
+
+        return Optional.empty();
+    }
+
+    // *********************************
+    // Context class
+    // *********************************
+
+    private final class MetaContext {
+        private final Map<String, Object> parameters;
+        private final ServiceNowConfiguration configuration;
+        private final ServiceNowClient client;
+        private final String instanceName;
+        private final String objectName;
+        private final String objectType;
+        private final Stack<String> stack;
+
+        MetaContext(Map<String, Object> parameters) throws Exception {
+            this.parameters = parameters;
+            this.configuration = getComponent(ServiceNowComponent.class).getConfiguration().copy();
+            this.stack = new Stack<>();
+
+            IntrospectionSupport.setProperties(configuration, new HashMap<>(parameters));
+
+            this.instanceName = (String)parameters.getOrDefault("instanceName", getComponent(ServiceNowComponent.class).getInstanceName());
+            this.objectType = (String)parameters.getOrDefault("objectType", "table");
+            this.objectName = (String)parameters.getOrDefault("objectName", configuration.getTable());
+
+            ObjectHelper.notNull(instanceName, "instanceName");
+            ObjectHelper.notNull(objectName, "objectName");
+            ObjectHelper.notNull(objectType, "objectType");
+
+            // 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));
+            }
+
+            this.client = new ServiceNowClient(getCamelContext(), configuration);
+        }
+
+        public Map<String, Object> getParameters() {
+            return parameters;
+        }
+
+        public ServiceNowConfiguration getConfiguration() {
+            return configuration;
+        }
+
+        public ServiceNowClient getClient() {
+            return client;
+        }
+
+        public String getInstanceName() {
+            return instanceName;
+        }
+
+        public String getObjectType() {
+            return objectType;
+        }
+
+        public String getObjectName() {
+            return objectName;
+        }
+
+        public Stack<String> getStack() {
+            return stack;
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/79172c33/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/model/DictionaryEntry.java
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/model/DictionaryEntry.java b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/model/DictionaryEntry.java
new file mode 100644
index 0000000..af7aa5b
--- /dev/null
+++ b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/model/DictionaryEntry.java
@@ -0,0 +1,56 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.servicenow.model;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+public class DictionaryEntry {
+    private final Reference internalType;
+    private final Reference reference;
+    private final Integer maxLength;
+    private final boolean mandatory;
+
+    @JsonCreator
+    public DictionaryEntry(
+        @JsonProperty(value = "internal_type") Reference internalType,
+        @JsonProperty(value = "reference") Reference reference,
+        @JsonProperty(value = "max_length") Integer maxLength,
+        @JsonProperty(value = "mandatory", defaultValue = "false") boolean mandatory) {
+
+        this.internalType = internalType;
+        this.reference = reference;
+        this.maxLength = maxLength;
+        this.mandatory = mandatory;
+    }
+
+    public Reference getInternalType() {
+        return internalType;
+    }
+
+    public Reference getReference() {
+        return reference;
+    }
+
+    public Integer getMaxLength() {
+        return maxLength;
+    }
+
+    public boolean isMandatory() {
+        return mandatory;
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/79172c33/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/model/Reference.java
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/model/Reference.java b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/model/Reference.java
new file mode 100644
index 0000000..1bcb2a7
--- /dev/null
+++ b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/model/Reference.java
@@ -0,0 +1,56 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.servicenow.model;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+public class Reference {
+    private final String link;
+    private final String value;
+    private final String displayValue;
+
+    @JsonCreator
+    public Reference(String value) {
+        this.link = null;
+        this.value = value;
+        this.displayValue = null;
+    }
+
+    @JsonCreator
+    public Reference(
+        @JsonProperty(value = "link", required = false) String link,
+        @JsonProperty(value = "value", required = true) String value,
+        @JsonProperty(value = "display_value", required = false) String displayValue) {
+
+        this.link = link;
+        this.value = value;
+        this.displayValue = displayValue;
+    }
+
+    public String getLink() {
+        return link;
+    }
+
+    public String getValue() {
+        return value;
+    }
+
+    public String getDisplayValue() {
+        return displayValue;
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/79172c33/components/camel-servicenow/src/test/java/org/apache/camel/component/servicenow/ServiceNowComponentVerifierTest.java
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/src/test/java/org/apache/camel/component/servicenow/ServiceNowComponentVerifierTest.java b/components/camel-servicenow/src/test/java/org/apache/camel/component/servicenow/ServiceNowComponentVerifierTest.java
index ddb3109..120346a 100644
--- a/components/camel-servicenow/src/test/java/org/apache/camel/component/servicenow/ServiceNowComponentVerifierTest.java
+++ b/components/camel-servicenow/src/test/java/org/apache/camel/component/servicenow/ServiceNowComponentVerifierTest.java
@@ -33,11 +33,8 @@ public class ServiceNowComponentVerifierTest extends ServiceNowTestSupport {
         return false;
     }
 
-    protected ServiceNowComponentVerifierExtension getVerifier() {
-        ServiceNowComponent component = context().getComponent("servicenow", ServiceNowComponent.class);
-        ServiceNowComponentVerifierExtension verifier = (ServiceNowComponentVerifierExtension)component.getVerifier();
-
-        return verifier;
+    protected ComponentVerifier getVerifier() {
+        return context().getComponent("servicenow", ServiceNowComponent.class).getVerifier();
     }
 
     // *********************************

http://git-wip-us.apache.org/repos/asf/camel/blob/79172c33/components/camel-servicenow/src/test/java/org/apache/camel/component/servicenow/ServiceNowMetaDataExtensionTest.java
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/src/test/java/org/apache/camel/component/servicenow/ServiceNowMetaDataExtensionTest.java b/components/camel-servicenow/src/test/java/org/apache/camel/component/servicenow/ServiceNowMetaDataExtensionTest.java
new file mode 100644
index 0000000..e99cb56
--- /dev/null
+++ b/components/camel-servicenow/src/test/java/org/apache/camel/component/servicenow/ServiceNowMetaDataExtensionTest.java
@@ -0,0 +1,87 @@
+/**
+ * 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.servicenow;
+
+import java.util.Map;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import org.apache.camel.component.extension.MetaDataExtension;
+import org.junit.Assert;
+import org.junit.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class ServiceNowMetaDataExtensionTest extends ServiceNowTestSupport {
+    private static final Logger LOGGER = LoggerFactory.getLogger(ServiceNowMetaDataExtensionTest.class);
+
+    public ServiceNowMetaDataExtensionTest() {
+        super(false);
+    }
+
+    @Override
+    public boolean isUseRouteBuilder() {
+        return false;
+    }
+
+    protected ServiceNowComponent getComponent() {
+        return context().getComponent("servicenow", ServiceNowComponent.class);
+    }
+
+    protected MetaDataExtension getExtension() {
+        return getComponent().getExtension(MetaDataExtension.class).orElseThrow(IllegalStateException::new);
+    }
+
+    // *********************************
+    //
+    // *********************************
+
+    @Test
+    public void testMetaData() throws Exception {
+        Map<String, Object> parameters = getParameters();
+        parameters.put("objectType", "table");
+        parameters.put("objectName", "incident");
+        //parameters.put("object.sys_user.fields", "first_name,last_name");
+        //parameters.put("object.incident.fields", "caller_id,severity,resolved_at,sys_id");
+        //parameters.put("object.incident.fields", "^sys_.*$");
+        //parameters.put("object.task.fields", "");
+
+        MetaDataExtension.MetaData result = getExtension().meta(parameters).orElseThrow(IllegalStateException::new);
+
+        Assert.assertEquals("application/schema+json", result.getAttribute(MetaDataExtension.MetaData.CONTENT_TYPE));
+        Assert.assertEquals(JsonNode.class, result.getAttribute(MetaDataExtension.MetaData.JAVA_TYPE));
+        Assert.assertTrue(result.getPayload(JsonNode.class).hasNonNull("definitions"));
+        Assert.assertTrue(result.getPayload(JsonNode.class).get("definitions").hasNonNull("guid"));
+        Assert.assertTrue(result.getPayload(JsonNode.class).get("definitions").hasNonNull("date"));
+        Assert.assertTrue(result.getPayload(JsonNode.class).get("definitions").hasNonNull("time"));
+        Assert.assertTrue(result.getPayload(JsonNode.class).get("definitions").hasNonNull("date-time"));
+        Assert.assertTrue(result.getPayload(JsonNode.class).hasNonNull("properties"));
+
+        //LOGGER.info(
+        //    new ObjectMapper().writerWithDefaultPrettyPrinter().writeValueAsString(result.getPayload())
+        //);
+    }
+
+
+    @Test(expected = UnsupportedOperationException.class)
+    public void testMInvalidObjectType() throws Exception {
+        Map<String, Object> parameters = getParameters();
+        parameters.put("objectType", "test");
+        parameters.put("objectName", "incident");
+
+        getExtension().meta(parameters);
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/79172c33/components/camel-servicenow/src/test/resources/log4j2.properties
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/src/test/resources/log4j2.properties b/components/camel-servicenow/src/test/resources/log4j2.properties
index 4061901..edd6b44 100644
--- a/components/camel-servicenow/src/test/resources/log4j2.properties
+++ b/components/camel-servicenow/src/test/resources/log4j2.properties
@@ -20,11 +20,24 @@ appender.file.name = file
 appender.file.fileName = target/camel-servicenow-test.log
 appender.file.layout.type = PatternLayout
 appender.file.layout.pattern = %d %-5p %c{1} - %m %n
+
 appender.out.type = Console
 appender.out.name = out
 appender.out.layout.type = PatternLayout
 appender.out.layout.pattern = %d{HH:mm:ss.SSS} [%-15.15t] %-30.30c{1} %-5p %m%n
+
 logger.servicenow.name = org.apache.camel.component.servicenow
 logger.servicenow.level = DEBUG
+
+#logger.metadata.name = org.apache.camel.component.servicenow.ServiceNowMetaDataExtensionTest
+#logger.metadata.level = DEBUG
+#logger.metadata.additivity = true
+#logger.metadata.appenderRef.metadata.ref = out
+
+#logger.metadata-ext.name = org.apache.camel.component.servicenow.ServiceNowMetaDataExtension
+#logger.metadata-ext.level = DEBUG
+#logger.metadata-ext.additivity = true
+#logger.metadata-ext.appenderRef.metadata-ext.ref = out
+
 rootLogger.level = INFO
-rootLogger.appenderRef.file.ref = file
+rootLogger.appenderRef.root.ref = file

http://git-wip-us.apache.org/repos/asf/camel/blob/79172c33/platforms/spring-boot/components-starter/camel-servicenow-starter/src/main/java/org/apache/camel/component/servicenow/springboot/ServiceNowComponentConfiguration.java
----------------------------------------------------------------------
diff --git a/platforms/spring-boot/components-starter/camel-servicenow-starter/src/main/java/org/apache/camel/component/servicenow/springboot/ServiceNowComponentConfiguration.java b/platforms/spring-boot/components-starter/camel-servicenow-starter/src/main/java/org/apache/camel/component/servicenow/springboot/ServiceNowComponentConfiguration.java
index 3aa6b72..56e1a4e 100644
--- a/platforms/spring-boot/components-starter/camel-servicenow-starter/src/main/java/org/apache/camel/component/servicenow/springboot/ServiceNowComponentConfiguration.java
+++ b/platforms/spring-boot/components-starter/camel-servicenow-starter/src/main/java/org/apache/camel/component/servicenow/springboot/ServiceNowComponentConfiguration.java
@@ -41,6 +41,10 @@ public class ServiceNowComponentConfiguration
             ComponentConfigurationPropertiesCommon {
 
     /**
+     * The ServiceNow instance name
+     */
+    private String instanceName;
+    /**
      * The ServiceNow default configuration
      */
     private ServiceNowConfigurationNestedConfiguration configuration;
@@ -79,6 +83,14 @@ public class ServiceNowComponentConfiguration
      */
     private Boolean resolvePropertyPlaceholders = true;
 
+    public String getInstanceName() {
+        return instanceName;
+    }
+
+    public void setInstanceName(String instanceName) {
+        this.instanceName = instanceName;
+    }
+
     public ServiceNowConfigurationNestedConfiguration getConfiguration() {
         return configuration;
     }


[04/19] camel git commit: CAMEL-11550: Component extensions

Posted by lb...@apache.org.
http://git-wip-us.apache.org/repos/asf/camel/blob/42529399/components/camel-http/src/test/java/org/apache/camel/component/http/HttpComponentVerifierExtensionTest.java
----------------------------------------------------------------------
diff --git a/components/camel-http/src/test/java/org/apache/camel/component/http/HttpComponentVerifierExtensionTest.java b/components/camel-http/src/test/java/org/apache/camel/component/http/HttpComponentVerifierExtensionTest.java
new file mode 100644
index 0000000..0ac9560
--- /dev/null
+++ b/components/camel-http/src/test/java/org/apache/camel/component/http/HttpComponentVerifierExtensionTest.java
@@ -0,0 +1,151 @@
+/**
+ * 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.http;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.camel.Component;
+import org.apache.camel.component.extension.ComponentVerifierExtension;
+import org.apache.camel.component.http.handler.BasicValidationHandler;
+import org.apache.camel.test.AvailablePortFinder;
+import org.eclipse.jetty.server.Server;
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+public class HttpComponentVerifierExtensionTest extends BaseHttpTest {
+    private static final String AUTH_USERNAME = "camel";
+    private static final String AUTH_PASSWORD = "password";
+    private static final int PORT = AvailablePortFinder.getNextAvailable();
+
+    private Server localServer;
+
+    @Before
+    @Override
+    public void setUp() throws Exception {
+        localServer = new Server(PORT);
+        localServer.setHandler(handlers(
+            contextHandler("/basic", new BasicValidationHandler("GET", null, null, getExpectedContent()))
+        ));
+
+        localServer.start();
+
+        super.setUp();
+    }
+
+    @After
+    @Override
+    public void tearDown() throws Exception {
+        super.tearDown();
+
+        if (localServer != null) {
+            localServer.stop();
+        }
+    }
+
+    @Override
+    public boolean isUseRouteBuilder() {
+        return false;
+    }
+
+    // *************************************************
+    // Helpers
+    // *************************************************
+
+    protected String getLocalServerUri(String contextPath) throws Exception {
+        return new StringBuilder()
+            .append("http://")
+            .append("localhost")
+            .append(":")
+            .append(PORT)
+            .append(contextPath != null ? contextPath : "")
+            .toString();
+    }
+
+    // *************************************************
+    // Tests (parameters)
+    // *************************************************
+
+    @Test
+    public void testParameters() throws Exception {
+        Component component = context().getComponent("http");
+        ComponentVerifierExtension verifier = component.getExtension(ComponentVerifierExtension.class).orElseThrow(IllegalStateException::new);
+
+        Map<String, Object> parameters = new HashMap<>();
+        parameters.put("httpUri", getLocalServerUri("/basic"));
+
+        ComponentVerifierExtension.Result result = verifier.verify(ComponentVerifierExtension.Scope.PARAMETERS, parameters);
+
+        Assert.assertEquals(ComponentVerifierExtension.Result.Status.OK, result.getStatus());
+    }
+
+    @Test
+    public void testMissingMandatoryParameters() throws Exception {
+        Component component = context().getComponent("http");
+        ComponentVerifierExtension verifier = component.getExtension(ComponentVerifierExtension.class).orElseThrow(IllegalStateException::new);
+
+        Map<String, Object> parameters = new HashMap<>();
+
+        ComponentVerifierExtension.Result result = verifier.verify(ComponentVerifierExtension.Scope.PARAMETERS, parameters);
+
+        Assert.assertEquals(ComponentVerifierExtension.Result.Status.ERROR, result.getStatus());
+        Assert.assertEquals(1, result.getErrors().size());
+
+        ComponentVerifierExtension.VerificationError error = result.getErrors().get(0);
+
+        Assert.assertEquals(ComponentVerifierExtension.VerificationError.StandardCode.MISSING_PARAMETER, error.getCode());
+        Assert.assertTrue(error.getParameterKeys().contains("httpUri"));
+    }
+
+    // *************************************************
+    // Tests (connectivity)
+    // *************************************************
+
+    @Test
+    public void testConnectivity() throws Exception {
+        Component component = context().getComponent("http");
+        ComponentVerifierExtension verifier = component.getExtension(ComponentVerifierExtension.class).orElseThrow(IllegalStateException::new);
+
+        Map<String, Object> parameters = new HashMap<>();
+        parameters.put("httpUri", getLocalServerUri("/basic"));
+
+        ComponentVerifierExtension.Result result = verifier.verify(ComponentVerifierExtension.Scope.CONNECTIVITY, parameters);
+
+        Assert.assertEquals(ComponentVerifierExtension.Result.Status.OK, result.getStatus());
+    }
+
+    @Test
+    public void testConnectivityWithWrongUri() throws Exception {
+        Component component = context().getComponent("http");
+        ComponentVerifierExtension verifier = component.getExtension(ComponentVerifierExtension.class).orElseThrow(IllegalStateException::new);
+
+        Map<String, Object> parameters = new HashMap<>();
+        parameters.put("httpUri", "http://www.not-existing-uri.unknown");
+
+        ComponentVerifierExtension.Result result = verifier.verify(ComponentVerifierExtension.Scope.CONNECTIVITY, parameters);
+
+        Assert.assertEquals(ComponentVerifierExtension.Result.Status.ERROR, result.getStatus());
+        Assert.assertEquals(1, result.getErrors().size());
+
+        ComponentVerifierExtension.VerificationError error = result.getErrors().get(0);
+
+        Assert.assertEquals(ComponentVerifierExtension.VerificationError.StandardCode.EXCEPTION, error.getCode());
+        Assert.assertTrue(error.getParameterKeys().contains("httpUri"));
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/42529399/components/camel-http/src/test/java/org/apache/camel/component/http/HttpComponentVerifierTest.java
----------------------------------------------------------------------
diff --git a/components/camel-http/src/test/java/org/apache/camel/component/http/HttpComponentVerifierTest.java b/components/camel-http/src/test/java/org/apache/camel/component/http/HttpComponentVerifierTest.java
new file mode 100644
index 0000000..764baf7
--- /dev/null
+++ b/components/camel-http/src/test/java/org/apache/camel/component/http/HttpComponentVerifierTest.java
@@ -0,0 +1,150 @@
+/**
+ * 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.http;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.camel.ComponentVerifier;
+import org.apache.camel.component.http.handler.BasicValidationHandler;
+import org.apache.camel.test.AvailablePortFinder;
+import org.eclipse.jetty.server.Server;
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+public class HttpComponentVerifierTest extends BaseHttpTest {
+    private static final String AUTH_USERNAME = "camel";
+    private static final String AUTH_PASSWORD = "password";
+    private static final int PORT = AvailablePortFinder.getNextAvailable();
+
+    private Server localServer;
+
+    @Before
+    @Override
+    public void setUp() throws Exception {
+        localServer = new Server(PORT);
+        localServer.setHandler(handlers(
+            contextHandler("/basic", new BasicValidationHandler("GET", null, null, getExpectedContent()))
+        ));
+
+        localServer.start();
+
+        super.setUp();
+    }
+
+    @After
+    @Override
+    public void tearDown() throws Exception {
+        super.tearDown();
+
+        if (localServer != null) {
+            localServer.stop();
+        }
+    }
+
+    @Override
+    public boolean isUseRouteBuilder() {
+        return false;
+    }
+
+    // *************************************************
+    // Helpers
+    // *************************************************
+
+    protected String getLocalServerUri(String contextPath) throws Exception {
+        return new StringBuilder()
+            .append("http://")
+            .append("localhost")
+            .append(":")
+            .append(PORT)
+            .append(contextPath != null ? contextPath : "")
+            .toString();
+    }
+
+    // *************************************************
+    // Tests (parameters)
+    // *************************************************
+
+    @Test
+    public void testParameters() throws Exception {
+        HttpComponent component = context().getComponent("http", HttpComponent.class);
+        ComponentVerifier verifier = component.getVerifier();
+
+        Map<String, Object> parameters = new HashMap<>();
+        parameters.put("httpUri", getLocalServerUri("/basic"));
+
+        ComponentVerifier.Result result = verifier.verify(ComponentVerifier.Scope.PARAMETERS, parameters);
+
+        Assert.assertEquals(ComponentVerifier.Result.Status.OK, result.getStatus());
+    }
+
+    @Test
+    public void testMissingMandatoryParameters() throws Exception {
+        HttpComponent component = context().getComponent("http", HttpComponent.class);
+        ComponentVerifier verifier = component.getVerifier();
+
+        Map<String, Object> parameters = new HashMap<>();
+
+        ComponentVerifier.Result result = verifier.verify(ComponentVerifier.Scope.PARAMETERS, parameters);
+
+        Assert.assertEquals(ComponentVerifier.Result.Status.ERROR, result.getStatus());
+        Assert.assertEquals(1, result.getErrors().size());
+
+        ComponentVerifier.VerificationError error = result.getErrors().get(0);
+
+        Assert.assertEquals(ComponentVerifier.VerificationError.StandardCode.MISSING_PARAMETER, error.getCode());
+        Assert.assertTrue(error.getParameterKeys().contains("httpUri"));
+    }
+
+    // *************************************************
+    // Tests (connectivity)
+    // *************************************************
+
+    @Test
+    public void testConnectivity() throws Exception {
+        HttpComponent component = context().getComponent("http", HttpComponent.class);
+        ComponentVerifier verifier = component.getVerifier();
+
+        Map<String, Object> parameters = new HashMap<>();
+        parameters.put("httpUri", getLocalServerUri("/basic"));
+
+        ComponentVerifier.Result result = verifier.verify(ComponentVerifier.Scope.CONNECTIVITY, parameters);
+
+        Assert.assertEquals(ComponentVerifier.Result.Status.OK, result.getStatus());
+    }
+
+    @Test
+    public void testConnectivityWithWrongUri() throws Exception {
+        HttpComponent component = context().getComponent("http", HttpComponent.class);
+        ComponentVerifier verifier = component.getVerifier();
+
+        Map<String, Object> parameters = new HashMap<>();
+        parameters.put("httpUri", "http://www.not-existing-uri.unknown");
+
+        ComponentVerifier.Result result = verifier.verify(ComponentVerifier.Scope.CONNECTIVITY, parameters);
+
+        Assert.assertEquals(ComponentVerifier.Result.Status.ERROR, result.getStatus());
+        Assert.assertEquals(1, result.getErrors().size());
+
+        ComponentVerifier.VerificationError error = result.getErrors().get(0);
+
+        Assert.assertEquals(ComponentVerifier.VerificationError.StandardCode.EXCEPTION, error.getCode());
+        Assert.assertTrue(error.getParameterKeys().contains("httpUri"));
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/camel/blob/42529399/components/camel-http4/src/main/java/org/apache/camel/component/http4/HttpComponent.java
----------------------------------------------------------------------
diff --git a/components/camel-http4/src/main/java/org/apache/camel/component/http4/HttpComponent.java b/components/camel-http4/src/main/java/org/apache/camel/component/http4/HttpComponent.java
index fc891cf..6a99af3 100644
--- a/components/camel-http4/src/main/java/org/apache/camel/component/http4/HttpComponent.java
+++ b/components/camel-http4/src/main/java/org/apache/camel/component/http4/HttpComponent.java
@@ -32,6 +32,7 @@ import org.apache.camel.Producer;
 import org.apache.camel.ResolveEndpointFailedException;
 import org.apache.camel.SSLContextParametersAware;
 import org.apache.camel.VerifiableComponent;
+import org.apache.camel.component.extension.ComponentVerifierExtension;
 import org.apache.camel.http.common.HttpBinding;
 import org.apache.camel.http.common.HttpCommonComponent;
 import org.apache.camel.http.common.HttpHelper;
@@ -105,11 +106,13 @@ public class HttpComponent extends HttpCommonComponent implements RestProducerFa
     private boolean useGlobalSslContextParameters;
 
     public HttpComponent() {
-        super(HttpEndpoint.class);
+        this(HttpEndpoint.class);
     }
 
     public HttpComponent(Class<? extends HttpEndpoint> endpointClass) {
         super(endpointClass);
+
+        registerExtension(HttpComponentVerifierExtension::new);
     }
 
     /**
@@ -549,10 +552,8 @@ public class HttpComponent extends HttpCommonComponent implements RestProducerFa
         super.doStop();
     }
 
-    /**
-     * TODO: document
-     */
+    @Override
     public ComponentVerifier getVerifier() {
-        return new HttpComponentVerifier(this);
+        return (scope, parameters) -> getExtension(ComponentVerifierExtension.class).orElseThrow(UnsupportedOperationException::new).verify(scope, parameters);
     }
 }

http://git-wip-us.apache.org/repos/asf/camel/blob/42529399/components/camel-http4/src/main/java/org/apache/camel/component/http4/HttpComponentVerifier.java
----------------------------------------------------------------------
diff --git a/components/camel-http4/src/main/java/org/apache/camel/component/http4/HttpComponentVerifier.java b/components/camel-http4/src/main/java/org/apache/camel/component/http4/HttpComponentVerifier.java
deleted file mode 100644
index 46e3bc4..0000000
--- a/components/camel-http4/src/main/java/org/apache/camel/component/http4/HttpComponentVerifier.java
+++ /dev/null
@@ -1,250 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.camel.component.http4;
-
-import java.net.UnknownHostException;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Optional;
-
-import org.apache.camel.http.common.HttpHelper;
-import org.apache.camel.impl.verifier.DefaultComponentVerifier;
-import org.apache.camel.impl.verifier.ResultBuilder;
-import org.apache.camel.impl.verifier.ResultErrorBuilder;
-import org.apache.camel.util.FileUtil;
-import org.apache.camel.util.ObjectHelper;
-import org.apache.http.client.config.RequestConfig;
-import org.apache.http.client.methods.CloseableHttpResponse;
-import org.apache.http.client.methods.HttpGet;
-import org.apache.http.client.methods.HttpUriRequest;
-import org.apache.http.impl.client.CloseableHttpClient;
-import org.apache.http.impl.client.HttpClientBuilder;
-
-final class HttpComponentVerifier extends DefaultComponentVerifier {
-    private final HttpComponent component;
-
-    HttpComponentVerifier(HttpComponent component) {
-        super("http4", component.getCamelContext());
-
-        this.component = component;
-    }
-
-    // *********************************
-    // Parameters validation
-    // *********************************
-
-    @Override
-    protected Result verifyParameters(Map<String, Object> parameters) {
-        // Default is success
-        final ResultBuilder builder = ResultBuilder.withStatusAndScope(Result.Status.OK, Scope.PARAMETERS);
-        // Make a copy to avoid clashing with parent validation
-        final HashMap<String, Object> verifyParams = new HashMap<>(parameters);
-        // Check if validation is rest-related
-        final boolean isRest = verifyParams.entrySet().stream().anyMatch(e -> e.getKey().startsWith("rest."));
-
-        if (isRest) {
-            // Build the httpUri from rest configuration
-            verifyParams.put("httpUri", buildHttpUriFromRestParameters(parameters));
-
-            // Cleanup parameters map from rest related stuffs
-            verifyParams.entrySet().removeIf(e -> e.getKey().startsWith("rest."));
-        }
-
-        // Validate using the catalog
-        super.verifyParametersAgainstCatalog(builder, verifyParams);
-
-        return builder.build();
-    }
-
-    // *********************************
-    // Connectivity validation
-    // *********************************
-
-    @Override
-    protected Result verifyConnectivity(Map<String, Object> parameters) {
-        // Default is success
-        final ResultBuilder builder = ResultBuilder.withStatusAndScope(Result.Status.OK, Scope.CONNECTIVITY);
-        // Make a copy to avoid clashing with parent validation
-        final HashMap<String, Object> verifyParams = new HashMap<>(parameters);
-        // Check if validation is rest-related
-        final boolean isRest = verifyParams.entrySet().stream().anyMatch(e -> e.getKey().startsWith("rest."));
-
-        if (isRest) {
-            // Build the httpUri from rest configuration
-            verifyParams.put("httpUri", buildHttpUriFromRestParameters(parameters));
-
-            // Cleanup parameters from rest related stuffs
-            verifyParams.entrySet().removeIf(e -> e.getKey().startsWith("rest."));
-        }
-
-        String httpUri = getOption(verifyParams, "httpUri", String.class).orElse(null);
-        if (ObjectHelper.isEmpty(httpUri)) {
-            builder.error(
-                ResultErrorBuilder.withMissingOption("httpUri")
-                    .detail("rest", isRest)
-                    .build()
-            );
-        }
-
-        try {
-            CloseableHttpClient httpclient = createHttpClient(verifyParams);
-            HttpUriRequest request = new HttpGet(httpUri);
-
-            try (CloseableHttpResponse response = httpclient.execute(request)) {
-                int code = response.getStatusLine().getStatusCode();
-                String okCodes = getOption(verifyParams, "okStatusCodeRange", String.class).orElse("200-299");
-
-                if (!HttpHelper.isStatusCodeOk(code, okCodes)) {
-                    if (code == 401) {
-                        // Unauthorized, add authUsername and authPassword to the list
-                        // of parameters in error
-                        builder.error(
-                            ResultErrorBuilder.withHttpCode(code)
-                                .description(response.getStatusLine().getReasonPhrase())
-                                .parameterKey("authUsername")
-                                .parameterKey("authPassword")
-                                .build()
-                        );
-                    } else if (code >= 300 && code < 400) {
-                        // redirect
-                        builder.error(
-                            ResultErrorBuilder.withHttpCode(code)
-                                .description(response.getStatusLine().getReasonPhrase())
-                                .parameterKey("httpUri")
-                                .detail(VerificationError.HttpAttribute.HTTP_REDIRECT, () -> HttpUtil.responseHeaderValue(response, "location"))
-                                .build()
-                        );
-                    } else if (code >= 400) {
-                        // generic http error
-                        builder.error(
-                            ResultErrorBuilder.withHttpCode(code)
-                                .description(response.getStatusLine().getReasonPhrase())
-                                .build()
-                        );
-                    }
-                }
-            } catch (UnknownHostException e) {
-                builder.error(
-                    ResultErrorBuilder.withException(e)
-                        .parameterKey("httpUri")
-                        .build()
-                );
-            }
-        } catch (Exception e) {
-            builder.error(ResultErrorBuilder.withException(e).build());
-        }
-
-        return builder.build();
-    }
-
-    // *********************************
-    // Helpers
-    // *********************************
-
-    private String buildHttpUriFromRestParameters(Map<String, Object> parameters) {
-        // We are doing rest endpoint validation but as today the endpoint
-        // can't do any param substitution so the validation is performed
-        // against the http uri
-        String httpUri = getOption(parameters, "rest.host", String.class).orElse(null);
-        String path = getOption(parameters, "rest.path", String.class).map(FileUtil::stripLeadingSeparator).orElse(null);
-
-        if (ObjectHelper.isNotEmpty(httpUri) && ObjectHelper.isNotEmpty(path)) {
-            httpUri = httpUri + "/" + path;
-        }
-
-        return httpUri;
-    }
-
-    private Optional<HttpClientConfigurer> configureAuthentication(Map<String, Object> parameters) {
-        Optional<String> authUsername = getOption(parameters, "authUsername", String.class);
-        Optional<String> authPassword = getOption(parameters, "authPassword", String.class);
-
-        if (authUsername.isPresent() && authPassword.isPresent()) {
-            Optional<String> authDomain = getOption(parameters, "authDomain", String.class);
-            Optional<String> authHost = getOption(parameters, "authHost", String.class);
-
-            return Optional.of(
-                new BasicAuthenticationHttpClientConfigurer(
-                    authUsername.get(),
-                    authPassword.get(),
-                    authDomain.orElse(null),
-                    authHost.orElse(null)
-                )
-            );
-        }
-
-        return Optional.empty();
-    }
-
-    private Optional<HttpClientConfigurer> configureProxy(Map<String, Object> parameters) {
-        Optional<String> uri = getOption(parameters, "httpUri", String.class);
-        Optional<String> proxyAuthHost = getOption(parameters, "proxyAuthHost", String.class);
-        Optional<Integer> proxyAuthPort = getOption(parameters, "proxyAuthPort", Integer.class);
-
-        if (proxyAuthHost.isPresent() && proxyAuthPort.isPresent()) {
-            Optional<String> proxyAuthScheme = getOption(parameters, "proxyAuthScheme", String.class);
-            Optional<String> proxyAuthUsername = getOption(parameters, "proxyAuthUsername", String.class);
-            Optional<String> proxyAuthPassword = getOption(parameters, "proxyAuthPassword", String.class);
-            Optional<String> proxyAuthDomain = getOption(parameters, "proxyAuthDomain", String.class);
-            Optional<String> proxyAuthNtHost = getOption(parameters, "proxyAuthNtHost", String.class);
-
-            if (!proxyAuthScheme.isPresent()) {
-                proxyAuthScheme = Optional.of(HttpHelper.isSecureConnection(uri.get()) ? "https" : "http");
-            }
-
-            if (proxyAuthUsername != null && proxyAuthPassword != null) {
-                return Optional.of(
-                    new ProxyHttpClientConfigurer(
-                        proxyAuthHost.get(),
-                        proxyAuthPort.get(),
-                        proxyAuthScheme.get(),
-                        proxyAuthUsername.orElse(null),
-                        proxyAuthPassword.orElse(null),
-                        proxyAuthDomain.orElse(null),
-                        proxyAuthNtHost.orElse(null))
-                );
-            } else {
-                return Optional.of(
-                    new ProxyHttpClientConfigurer(
-                        proxyAuthHost.get(),
-                        proxyAuthPort.get(),
-                        proxyAuthScheme.get())
-                );
-            }
-        }
-
-        return Optional.empty();
-    }
-
-    private CloseableHttpClient createHttpClient(Map<String, Object> parameters) throws Exception {
-        CompositeHttpConfigurer configurer = new CompositeHttpConfigurer();
-        configureAuthentication(parameters).ifPresent(configurer::addConfigurer);
-        configureProxy(parameters).ifPresent(configurer::addConfigurer);
-
-        HttpClientBuilder builder = HttpClientBuilder.create();
-        configurer.configureHttpClient(builder);
-
-        RequestConfig.Builder requestConfigBuilder = RequestConfig.custom();
-
-        // Apply custom http client properties like httpClient.redirectsEnabled
-        setProperties(builder, "httpClient.", parameters);
-        setProperties(requestConfigBuilder, "httpClient.", parameters);
-
-        return builder.setDefaultRequestConfig(requestConfigBuilder.build())
-            .build();
-    }
-}

http://git-wip-us.apache.org/repos/asf/camel/blob/42529399/components/camel-http4/src/main/java/org/apache/camel/component/http4/HttpComponentVerifierExtension.java
----------------------------------------------------------------------
diff --git a/components/camel-http4/src/main/java/org/apache/camel/component/http4/HttpComponentVerifierExtension.java b/components/camel-http4/src/main/java/org/apache/camel/component/http4/HttpComponentVerifierExtension.java
new file mode 100644
index 0000000..3aee9eb
--- /dev/null
+++ b/components/camel-http4/src/main/java/org/apache/camel/component/http4/HttpComponentVerifierExtension.java
@@ -0,0 +1,248 @@
+/**
+ * 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.http4;
+
+import java.net.UnknownHostException;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Optional;
+
+import org.apache.camel.component.extension.ComponentVerifierExtension;
+import org.apache.camel.component.extension.verifier.DefaultComponentVerifierExtension;
+import org.apache.camel.component.extension.verifier.ResultBuilder;
+import org.apache.camel.component.extension.verifier.ResultErrorBuilder;
+import org.apache.camel.http.common.HttpHelper;
+import org.apache.camel.util.FileUtil;
+import org.apache.camel.util.ObjectHelper;
+import org.apache.http.client.config.RequestConfig;
+import org.apache.http.client.methods.CloseableHttpResponse;
+import org.apache.http.client.methods.HttpGet;
+import org.apache.http.client.methods.HttpUriRequest;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.impl.client.HttpClientBuilder;
+
+final class HttpComponentVerifierExtension extends DefaultComponentVerifierExtension {
+
+    HttpComponentVerifierExtension() {
+        super("http4");
+    }
+
+    // *********************************
+    // Parameters validation
+    // *********************************
+
+    @Override
+    protected Result verifyParameters(Map<String, Object> parameters) {
+        // Default is success
+        final ResultBuilder builder = ResultBuilder.withStatusAndScope(Result.Status.OK, ComponentVerifierExtension.Scope.PARAMETERS);
+        // Make a copy to avoid clashing with parent validation
+        final HashMap<String, Object> verifyParams = new HashMap<>(parameters);
+        // Check if validation is rest-related
+        final boolean isRest = verifyParams.entrySet().stream().anyMatch(e -> e.getKey().startsWith("rest."));
+
+        if (isRest) {
+            // Build the httpUri from rest configuration
+            verifyParams.put("httpUri", buildHttpUriFromRestParameters(parameters));
+
+            // Cleanup parameters map from rest related stuffs
+            verifyParams.entrySet().removeIf(e -> e.getKey().startsWith("rest."));
+        }
+
+        // Validate using the catalog
+        super.verifyParametersAgainstCatalog(builder, verifyParams);
+
+        return builder.build();
+    }
+
+    // *********************************
+    // Connectivity validation
+    // *********************************
+
+    @Override
+    protected Result verifyConnectivity(Map<String, Object> parameters) {
+        // Default is success
+        final ResultBuilder builder = ResultBuilder.withStatusAndScope(Result.Status.OK, ComponentVerifierExtension.Scope.CONNECTIVITY);
+        // Make a copy to avoid clashing with parent validation
+        final HashMap<String, Object> verifyParams = new HashMap<>(parameters);
+        // Check if validation is rest-related
+        final boolean isRest = verifyParams.entrySet().stream().anyMatch(e -> e.getKey().startsWith("rest."));
+
+        if (isRest) {
+            // Build the httpUri from rest configuration
+            verifyParams.put("httpUri", buildHttpUriFromRestParameters(parameters));
+
+            // Cleanup parameters from rest related stuffs
+            verifyParams.entrySet().removeIf(e -> e.getKey().startsWith("rest."));
+        }
+
+        String httpUri = getOption(verifyParams, "httpUri", String.class).orElse(null);
+        if (ObjectHelper.isEmpty(httpUri)) {
+            builder.error(
+                ResultErrorBuilder.withMissingOption("httpUri")
+                    .detail("rest", isRest)
+                    .build()
+            );
+        }
+
+        try {
+            CloseableHttpClient httpclient = createHttpClient(verifyParams);
+            HttpUriRequest request = new HttpGet(httpUri);
+
+            try (CloseableHttpResponse response = httpclient.execute(request)) {
+                int code = response.getStatusLine().getStatusCode();
+                String okCodes = getOption(verifyParams, "okStatusCodeRange", String.class).orElse("200-299");
+
+                if (!HttpHelper.isStatusCodeOk(code, okCodes)) {
+                    if (code == 401) {
+                        // Unauthorized, add authUsername and authPassword to the list
+                        // of parameters in error
+                        builder.error(
+                            ResultErrorBuilder.withHttpCode(code)
+                                .description(response.getStatusLine().getReasonPhrase())
+                                .parameterKey("authUsername")
+                                .parameterKey("authPassword")
+                                .build()
+                        );
+                    } else if (code >= 300 && code < 400) {
+                        // redirect
+                        builder.error(
+                            ResultErrorBuilder.withHttpCode(code)
+                                .description(response.getStatusLine().getReasonPhrase())
+                                .parameterKey("httpUri")
+                                .detail(VerificationError.HttpAttribute.HTTP_REDIRECT, () -> HttpUtil.responseHeaderValue(response, "location"))
+                                .build()
+                        );
+                    } else if (code >= 400) {
+                        // generic http error
+                        builder.error(
+                            ResultErrorBuilder.withHttpCode(code)
+                                .description(response.getStatusLine().getReasonPhrase())
+                                .build()
+                        );
+                    }
+                }
+            } catch (UnknownHostException e) {
+                builder.error(
+                    ResultErrorBuilder.withException(e)
+                        .parameterKey("httpUri")
+                        .build()
+                );
+            }
+        } catch (Exception e) {
+            builder.error(ResultErrorBuilder.withException(e).build());
+        }
+
+        return builder.build();
+    }
+
+    // *********************************
+    // Helpers
+    // *********************************
+
+    private String buildHttpUriFromRestParameters(Map<String, Object> parameters) {
+        // We are doing rest endpoint validation but as today the endpoint
+        // can't do any param substitution so the validation is performed
+        // against the http uri
+        String httpUri = getOption(parameters, "rest.host", String.class).orElse(null);
+        String path = getOption(parameters, "rest.path", String.class).map(FileUtil::stripLeadingSeparator).orElse(null);
+
+        if (ObjectHelper.isNotEmpty(httpUri) && ObjectHelper.isNotEmpty(path)) {
+            httpUri = httpUri + "/" + path;
+        }
+
+        return httpUri;
+    }
+
+    private Optional<HttpClientConfigurer> configureAuthentication(Map<String, Object> parameters) {
+        Optional<String> authUsername = getOption(parameters, "authUsername", String.class);
+        Optional<String> authPassword = getOption(parameters, "authPassword", String.class);
+
+        if (authUsername.isPresent() && authPassword.isPresent()) {
+            Optional<String> authDomain = getOption(parameters, "authDomain", String.class);
+            Optional<String> authHost = getOption(parameters, "authHost", String.class);
+
+            return Optional.of(
+                new BasicAuthenticationHttpClientConfigurer(
+                    authUsername.get(),
+                    authPassword.get(),
+                    authDomain.orElse(null),
+                    authHost.orElse(null)
+                )
+            );
+        }
+
+        return Optional.empty();
+    }
+
+    private Optional<HttpClientConfigurer> configureProxy(Map<String, Object> parameters) {
+        Optional<String> uri = getOption(parameters, "httpUri", String.class);
+        Optional<String> proxyAuthHost = getOption(parameters, "proxyAuthHost", String.class);
+        Optional<Integer> proxyAuthPort = getOption(parameters, "proxyAuthPort", Integer.class);
+
+        if (proxyAuthHost.isPresent() && proxyAuthPort.isPresent()) {
+            Optional<String> proxyAuthScheme = getOption(parameters, "proxyAuthScheme", String.class);
+            Optional<String> proxyAuthUsername = getOption(parameters, "proxyAuthUsername", String.class);
+            Optional<String> proxyAuthPassword = getOption(parameters, "proxyAuthPassword", String.class);
+            Optional<String> proxyAuthDomain = getOption(parameters, "proxyAuthDomain", String.class);
+            Optional<String> proxyAuthNtHost = getOption(parameters, "proxyAuthNtHost", String.class);
+
+            if (!proxyAuthScheme.isPresent()) {
+                proxyAuthScheme = Optional.of(HttpHelper.isSecureConnection(uri.get()) ? "https" : "http");
+            }
+
+            if (proxyAuthUsername != null && proxyAuthPassword != null) {
+                return Optional.of(
+                    new ProxyHttpClientConfigurer(
+                        proxyAuthHost.get(),
+                        proxyAuthPort.get(),
+                        proxyAuthScheme.get(),
+                        proxyAuthUsername.orElse(null),
+                        proxyAuthPassword.orElse(null),
+                        proxyAuthDomain.orElse(null),
+                        proxyAuthNtHost.orElse(null))
+                );
+            } else {
+                return Optional.of(
+                    new ProxyHttpClientConfigurer(
+                        proxyAuthHost.get(),
+                        proxyAuthPort.get(),
+                        proxyAuthScheme.get())
+                );
+            }
+        }
+
+        return Optional.empty();
+    }
+
+    private CloseableHttpClient createHttpClient(Map<String, Object> parameters) throws Exception {
+        CompositeHttpConfigurer configurer = new CompositeHttpConfigurer();
+        configureAuthentication(parameters).ifPresent(configurer::addConfigurer);
+        configureProxy(parameters).ifPresent(configurer::addConfigurer);
+
+        HttpClientBuilder builder = HttpClientBuilder.create();
+        configurer.configureHttpClient(builder);
+
+        RequestConfig.Builder requestConfigBuilder = RequestConfig.custom();
+
+        // Apply custom http client properties like httpClient.redirectsEnabled
+        setProperties(builder, "httpClient.", parameters);
+        setProperties(requestConfigBuilder, "httpClient.", parameters);
+
+        return builder.setDefaultRequestConfig(requestConfigBuilder.build())
+            .build();
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/42529399/components/camel-http4/src/test/java/org/apache/camel/component/http4/CamelComponentVerifierExtensionTest.java
----------------------------------------------------------------------
diff --git a/components/camel-http4/src/test/java/org/apache/camel/component/http4/CamelComponentVerifierExtensionTest.java b/components/camel-http4/src/test/java/org/apache/camel/component/http4/CamelComponentVerifierExtensionTest.java
new file mode 100644
index 0000000..a853919
--- /dev/null
+++ b/components/camel-http4/src/test/java/org/apache/camel/component/http4/CamelComponentVerifierExtensionTest.java
@@ -0,0 +1,263 @@
+/**
+ * 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.http4;
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.camel.Component;
+import org.apache.camel.ComponentVerifier;
+import org.apache.camel.component.extension.ComponentVerifierExtension;
+import org.apache.camel.component.http4.handler.AuthenticationValidationHandler;
+import org.apache.camel.component.http4.handler.BasicValidationHandler;
+import org.apache.http.HttpException;
+import org.apache.http.HttpRequest;
+import org.apache.http.HttpResponse;
+import org.apache.http.HttpStatus;
+import org.apache.http.impl.bootstrap.HttpServer;
+import org.apache.http.impl.bootstrap.ServerBootstrap;
+import org.apache.http.localserver.RequestBasicAuth;
+import org.apache.http.localserver.ResponseBasicUnauthorized;
+import org.apache.http.protocol.HttpContext;
+import org.apache.http.protocol.HttpProcessor;
+import org.apache.http.protocol.HttpRequestHandler;
+import org.apache.http.protocol.ImmutableHttpProcessor;
+import org.apache.http.protocol.ResponseContent;
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+public class CamelComponentVerifierExtensionTest extends BaseHttpTest {
+    private static final String AUTH_USERNAME = "camel";
+    private static final String AUTH_PASSWORD = "password";
+
+    private HttpServer localServer;
+
+    @Before
+    @Override
+    public void setUp() throws Exception {
+        localServer = ServerBootstrap.bootstrap()
+            .setHttpProcessor(getHttpProcessor())
+            .registerHandler("/basic", new BasicValidationHandler("GET", null, null, getExpectedContent()))
+            .registerHandler("/auth", new AuthenticationValidationHandler("GET", null, null, getExpectedContent(), AUTH_USERNAME, AUTH_PASSWORD))
+            .registerHandler("/redirect", redirectTo(HttpStatus.SC_MOVED_PERMANENTLY, "/redirected"))
+            .registerHandler("/redirected", new BasicValidationHandler("GET", null, null, getExpectedContent()))
+            .create();
+
+        localServer.start();
+
+        super.setUp();
+    }
+
+    @After
+    @Override
+    public void tearDown() throws Exception {
+        super.tearDown();
+
+        if (localServer != null) {
+            localServer.stop();
+        }
+    }
+
+    @Override
+    public boolean isUseRouteBuilder() {
+        return false;
+    }
+
+    private HttpProcessor getHttpProcessor() {
+        return new ImmutableHttpProcessor(
+            Arrays.asList(
+                new RequestBasicAuth()
+            ),
+            Arrays.asList(
+                new ResponseContent(),
+                new ResponseBasicUnauthorized())
+        );
+    }
+
+    // *************************************************
+    // Helpers
+    // *************************************************
+
+    protected String getLocalServerUri(String contextPath) {
+        return new StringBuilder()
+            .append("http://")
+            .append(localServer.getInetAddress().getHostName())
+            .append(":")
+            .append(localServer.getLocalPort())
+            .append(contextPath != null
+                ? contextPath.startsWith("/") ? contextPath : "/" + contextPath
+                : "")
+            .toString();
+    }
+
+    private HttpRequestHandler redirectTo(int code, String path) {
+        return new HttpRequestHandler() {
+            @Override
+            public void handle(HttpRequest request, HttpResponse response, HttpContext context) throws HttpException, IOException {
+                response.setHeader("location", getLocalServerUri(path));
+                response.setStatusCode(code);
+            }
+        };
+    }
+
+    // *************************************************
+    // Tests (parameters)
+    // *************************************************
+
+    @Test
+    public void testParameters() throws Exception {
+        Component component = context().getComponent("http4");
+        ComponentVerifierExtension verifier = component.getExtension(ComponentVerifierExtension.class).orElseThrow(IllegalStateException::new);
+
+        Map<String, Object> parameters = new HashMap<>();
+        parameters.put("httpUri", getLocalServerUri("/basic"));
+
+        ComponentVerifierExtension.Result result = verifier.verify(ComponentVerifierExtension.Scope.PARAMETERS, parameters);
+
+        Assert.assertEquals(ComponentVerifierExtension.Result.Status.OK, result.getStatus());
+    }
+
+    @Test
+    public void testMissingMandatoryParameters() throws Exception {
+        Component component = context().getComponent("http4");
+        ComponentVerifierExtension verifier = component.getExtension(ComponentVerifierExtension.class).orElseThrow(IllegalStateException::new);
+
+        Map<String, Object> parameters = new HashMap<>();
+
+        ComponentVerifier.Result result = verifier.verify(ComponentVerifierExtension.Scope.PARAMETERS, parameters);
+
+        Assert.assertEquals(ComponentVerifier.Result.Status.ERROR, result.getStatus());
+        Assert.assertEquals(1, result.getErrors().size());
+
+        ComponentVerifierExtension.VerificationError error = result.getErrors().get(0);
+
+        Assert.assertEquals(ComponentVerifierExtension.VerificationError.StandardCode.MISSING_PARAMETER, error.getCode());
+        Assert.assertTrue(error.getParameterKeys().contains("httpUri"));
+    }
+
+    // *************************************************
+    // Tests (connectivity)
+    // *************************************************
+
+    @Test
+    public void testConnectivity() throws Exception {
+        Component component = context().getComponent("http4");
+        ComponentVerifierExtension verifier = component.getExtension(ComponentVerifierExtension.class).orElseThrow(IllegalStateException::new);
+
+        Map<String, Object> parameters = new HashMap<>();
+        parameters.put("httpUri", getLocalServerUri("/basic"));
+
+        ComponentVerifierExtension.Result result = verifier.verify(ComponentVerifierExtension.Scope.CONNECTIVITY, parameters);
+
+        Assert.assertEquals(ComponentVerifierExtension.Result.Status.OK, result.getStatus());
+    }
+
+    @Test
+    public void testConnectivityWithWrongUri() throws Exception {
+        Component component = context().getComponent("http4");
+        ComponentVerifierExtension verifier = component.getExtension(ComponentVerifierExtension.class).orElseThrow(IllegalStateException::new);
+
+        Map<String, Object> parameters = new HashMap<>();
+        parameters.put("httpUri", "http://www.not-existing-uri.unknown");
+
+        ComponentVerifierExtension.Result result = verifier.verify(ComponentVerifierExtension.Scope.CONNECTIVITY, parameters);
+
+        Assert.assertEquals(ComponentVerifierExtension.Result.Status.ERROR, result.getStatus());
+        Assert.assertEquals(1, result.getErrors().size());
+
+        ComponentVerifierExtension.VerificationError error = result.getErrors().get(0);
+
+        Assert.assertEquals(ComponentVerifierExtension.VerificationError.StandardCode.EXCEPTION, error.getCode());
+        Assert.assertTrue(error.getParameterKeys().contains("httpUri"));
+    }
+
+    @Test
+    public void testConnectivityWithAuthentication() throws Exception {
+        Component component = context().getComponent("http4");
+        ComponentVerifierExtension verifier = component.getExtension(ComponentVerifierExtension.class).orElseThrow(IllegalStateException::new);
+
+        Map<String, Object> parameters = new HashMap<>();
+        parameters.put("httpUri", getLocalServerUri("/auth"));
+        parameters.put("authUsername", AUTH_USERNAME);
+        parameters.put("authPassword", AUTH_PASSWORD);
+
+        ComponentVerifierExtension.Result result = verifier.verify(ComponentVerifierExtension.Scope.CONNECTIVITY, parameters);
+
+        Assert.assertEquals(ComponentVerifierExtension.Result.Status.OK, result.getStatus());
+    }
+
+    @Test
+    public void testConnectivityWithWrongAuthenticationData() throws Exception {
+        Component component = context().getComponent("http4");
+        ComponentVerifierExtension verifier = component.getExtension(ComponentVerifierExtension.class).orElseThrow(IllegalStateException::new);
+
+        Map<String, Object> parameters = new HashMap<>();
+        parameters.put("httpUri", getLocalServerUri("/auth"));
+        parameters.put("authUsername", "unknown");
+        parameters.put("authPassword", AUTH_PASSWORD);
+
+        ComponentVerifierExtension.Result result = verifier.verify(ComponentVerifierExtension.Scope.CONNECTIVITY, parameters);
+
+        Assert.assertEquals(ComponentVerifierExtension.Result.Status.ERROR, result.getStatus());
+        Assert.assertEquals(1, result.getErrors().size());
+
+        ComponentVerifierExtension.VerificationError error = result.getErrors().get(0);
+
+        Assert.assertEquals(ComponentVerifierExtension.VerificationError.StandardCode.AUTHENTICATION, error.getCode());
+        Assert.assertEquals(401, error.getDetails().get(ComponentVerifierExtension.VerificationError.HttpAttribute.HTTP_CODE));
+        Assert.assertTrue(error.getParameterKeys().contains("authUsername"));
+        Assert.assertTrue(error.getParameterKeys().contains("authPassword"));
+    }
+
+    @Test
+    public void testConnectivityWithRedirect() throws Exception {
+        Component component = context().getComponent("http4");
+        ComponentVerifierExtension verifier = component.getExtension(ComponentVerifierExtension.class).orElseThrow(IllegalStateException::new);
+
+        Map<String, Object> parameters = new HashMap<>();
+        parameters.put("httpUri", getLocalServerUri("/redirect"));
+
+        ComponentVerifierExtension.Result result = verifier.verify(ComponentVerifierExtension.Scope.CONNECTIVITY, parameters);
+
+        Assert.assertEquals(ComponentVerifierExtension.Result.Status.OK, result.getStatus());
+    }
+
+    @Test
+    public void testConnectivityWithRedirectDisabled() throws Exception {
+        Component component = context().getComponent("http4");
+        ComponentVerifierExtension verifier = component.getExtension(ComponentVerifierExtension.class).orElseThrow(IllegalStateException::new);
+
+        Map<String, Object> parameters = new HashMap<>();
+        parameters.put("httpUri", getLocalServerUri("/redirect"));
+        parameters.put("httpClient.redirectsEnabled", "false");
+
+        ComponentVerifierExtension.Result result = verifier.verify(ComponentVerifierExtension.Scope.CONNECTIVITY, parameters);
+
+        Assert.assertEquals(ComponentVerifierExtension.Result.Status.ERROR, result.getStatus());
+        Assert.assertEquals(1, result.getErrors().size());
+
+        ComponentVerifierExtension.VerificationError error = result.getErrors().get(0);
+
+        Assert.assertEquals(ComponentVerifierExtension.VerificationError.StandardCode.GENERIC, error.getCode());
+        Assert.assertEquals(getLocalServerUri("/redirected"), error.getDetails().get(ComponentVerifierExtension.VerificationError.HttpAttribute.HTTP_REDIRECT));
+        Assert.assertTrue(error.getParameterKeys().contains("httpUri"));
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/camel/blob/42529399/components/camel-http4/src/test/java/org/apache/camel/component/http4/CamelComponentVerifierTest.java
----------------------------------------------------------------------
diff --git a/components/camel-http4/src/test/java/org/apache/camel/component/http4/CamelComponentVerifierTest.java b/components/camel-http4/src/test/java/org/apache/camel/component/http4/CamelComponentVerifierTest.java
index dc4ef3f..5144a8d 100644
--- a/components/camel-http4/src/test/java/org/apache/camel/component/http4/CamelComponentVerifierTest.java
+++ b/components/camel-http4/src/test/java/org/apache/camel/component/http4/CamelComponentVerifierTest.java
@@ -22,7 +22,6 @@ import java.util.HashMap;
 import java.util.Map;
 
 import org.apache.camel.ComponentVerifier;
-import org.apache.camel.ComponentVerifier.VerificationError;
 import org.apache.camel.component.http4.handler.AuthenticationValidationHandler;
 import org.apache.camel.component.http4.handler.BasicValidationHandler;
 import org.apache.http.HttpException;
@@ -118,13 +117,13 @@ public class CamelComponentVerifierTest extends BaseHttpTest {
     }
 
     // *************************************************
-    // Tests
+    // Tests (parameters)
     // *************************************************
 
     @Test
     public void testParameters() throws Exception {
         HttpComponent component = context().getComponent("http4", HttpComponent.class);
-        HttpComponentVerifier verifier = (HttpComponentVerifier)component.getVerifier();
+        ComponentVerifier verifier = component.getVerifier();
 
         Map<String, Object> parameters = new HashMap<>();
         parameters.put("httpUri", getLocalServerUri("/basic"));
@@ -137,7 +136,7 @@ public class CamelComponentVerifierTest extends BaseHttpTest {
     @Test
     public void testMissingMandatoryParameters() throws Exception {
         HttpComponent component = context().getComponent("http4", HttpComponent.class);
-        HttpComponentVerifier verifier = (HttpComponentVerifier)component.getVerifier();
+        ComponentVerifier verifier = component.getVerifier();
 
         Map<String, Object> parameters = new HashMap<>();
 
@@ -146,16 +145,20 @@ public class CamelComponentVerifierTest extends BaseHttpTest {
         Assert.assertEquals(ComponentVerifier.Result.Status.ERROR, result.getStatus());
         Assert.assertEquals(1, result.getErrors().size());
 
-        VerificationError error = result.getErrors().get(0);
+        ComponentVerifier.VerificationError error = result.getErrors().get(0);
 
-        Assert.assertEquals(VerificationError.StandardCode.MISSING_PARAMETER, error.getCode());
+        Assert.assertEquals(ComponentVerifier.VerificationError.StandardCode.MISSING_PARAMETER, error.getCode());
         Assert.assertTrue(error.getParameterKeys().contains("httpUri"));
     }
 
+    // *************************************************
+    // Tests (connectivity)
+    // *************************************************
+
     @Test
     public void testConnectivity() throws Exception {
         HttpComponent component = context().getComponent("http4", HttpComponent.class);
-        HttpComponentVerifier verifier = (HttpComponentVerifier)component.getVerifier();
+        ComponentVerifier verifier = component.getVerifier();
 
         Map<String, Object> parameters = new HashMap<>();
         parameters.put("httpUri", getLocalServerUri("/basic"));
@@ -168,7 +171,7 @@ public class CamelComponentVerifierTest extends BaseHttpTest {
     @Test
     public void testConnectivityWithWrongUri() throws Exception {
         HttpComponent component = context().getComponent("http4", HttpComponent.class);
-        HttpComponentVerifier verifier = (HttpComponentVerifier)component.getVerifier();
+        ComponentVerifier verifier = component.getVerifier();
 
         Map<String, Object> parameters = new HashMap<>();
         parameters.put("httpUri", "http://www.not-existing-uri.unknown");
@@ -178,16 +181,16 @@ public class CamelComponentVerifierTest extends BaseHttpTest {
         Assert.assertEquals(ComponentVerifier.Result.Status.ERROR, result.getStatus());
         Assert.assertEquals(1, result.getErrors().size());
 
-        VerificationError error = result.getErrors().get(0);
+        ComponentVerifier.VerificationError error = result.getErrors().get(0);
 
-        Assert.assertEquals(VerificationError.StandardCode.EXCEPTION, error.getCode());
+        Assert.assertEquals(ComponentVerifier.VerificationError.StandardCode.EXCEPTION, error.getCode());
         Assert.assertTrue(error.getParameterKeys().contains("httpUri"));
     }
 
     @Test
     public void testConnectivityWithAuthentication() throws Exception {
         HttpComponent component = context().getComponent("http4", HttpComponent.class);
-        HttpComponentVerifier verifier = (HttpComponentVerifier)component.getVerifier();
+        ComponentVerifier verifier = component.getVerifier();
 
         Map<String, Object> parameters = new HashMap<>();
         parameters.put("httpUri", getLocalServerUri("/auth"));
@@ -202,7 +205,7 @@ public class CamelComponentVerifierTest extends BaseHttpTest {
     @Test
     public void testConnectivityWithWrongAuthenticationData() throws Exception {
         HttpComponent component = context().getComponent("http4", HttpComponent.class);
-        HttpComponentVerifier verifier = (HttpComponentVerifier)component.getVerifier();
+        ComponentVerifier verifier = component.getVerifier();
 
         Map<String, Object> parameters = new HashMap<>();
         parameters.put("httpUri", getLocalServerUri("/auth"));
@@ -214,10 +217,10 @@ public class CamelComponentVerifierTest extends BaseHttpTest {
         Assert.assertEquals(ComponentVerifier.Result.Status.ERROR, result.getStatus());
         Assert.assertEquals(1, result.getErrors().size());
 
-        VerificationError error = result.getErrors().get(0);
+        ComponentVerifier.VerificationError error = result.getErrors().get(0);
 
-        Assert.assertEquals(VerificationError.StandardCode.AUTHENTICATION, error.getCode());
-        Assert.assertEquals(401, error.getDetails().get(VerificationError.HttpAttribute.HTTP_CODE));
+        Assert.assertEquals(ComponentVerifier.VerificationError.StandardCode.AUTHENTICATION, error.getCode());
+        Assert.assertEquals(401, error.getDetails().get(ComponentVerifier.VerificationError.HttpAttribute.HTTP_CODE));
         Assert.assertTrue(error.getParameterKeys().contains("authUsername"));
         Assert.assertTrue(error.getParameterKeys().contains("authPassword"));
     }
@@ -225,7 +228,7 @@ public class CamelComponentVerifierTest extends BaseHttpTest {
     @Test
     public void testConnectivityWithRedirect() throws Exception {
         HttpComponent component = context().getComponent("http4", HttpComponent.class);
-        HttpComponentVerifier verifier = (HttpComponentVerifier)component.getVerifier();
+        ComponentVerifier verifier = component.getVerifier();
 
         Map<String, Object> parameters = new HashMap<>();
         parameters.put("httpUri", getLocalServerUri("/redirect"));
@@ -238,7 +241,7 @@ public class CamelComponentVerifierTest extends BaseHttpTest {
     @Test
     public void testConnectivityWithRedirectDisabled() throws Exception {
         HttpComponent component = context().getComponent("http4", HttpComponent.class);
-        HttpComponentVerifier verifier = (HttpComponentVerifier)component.getVerifier();
+        ComponentVerifier verifier = component.getVerifier();
 
         Map<String, Object> parameters = new HashMap<>();
         parameters.put("httpUri", getLocalServerUri("/redirect"));
@@ -249,10 +252,10 @@ public class CamelComponentVerifierTest extends BaseHttpTest {
         Assert.assertEquals(ComponentVerifier.Result.Status.ERROR, result.getStatus());
         Assert.assertEquals(1, result.getErrors().size());
 
-        VerificationError error = result.getErrors().get(0);
+        ComponentVerifier.VerificationError error = result.getErrors().get(0);
 
-        Assert.assertEquals(VerificationError.StandardCode.GENERIC, error.getCode());
-        Assert.assertEquals(getLocalServerUri("/redirected"), error.getDetails().get(VerificationError.HttpAttribute.HTTP_REDIRECT));
+        Assert.assertEquals(ComponentVerifier.VerificationError.StandardCode.GENERIC, error.getCode());
+        Assert.assertEquals(getLocalServerUri("/redirected"), error.getDetails().get(ComponentVerifier.VerificationError.HttpAttribute.HTTP_REDIRECT));
         Assert.assertTrue(error.getParameterKeys().contains("httpUri"));
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/camel/blob/42529399/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/SalesforceComponent.java
----------------------------------------------------------------------
diff --git a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/SalesforceComponent.java b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/SalesforceComponent.java
index 5609031..0ef308e 100644
--- a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/SalesforceComponent.java
+++ b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/SalesforceComponent.java
@@ -28,6 +28,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.ComponentVerifierExtension;
 import org.apache.camel.component.salesforce.api.SalesforceException;
 import org.apache.camel.component.salesforce.api.dto.AbstractSObjectBase;
 import org.apache.camel.component.salesforce.internal.OperationName;
@@ -199,10 +200,13 @@ public class SalesforceComponent extends DefaultComponent implements VerifiableC
     private SubscriptionHelper subscriptionHelper;
 
     public SalesforceComponent() {
+        this(null);
     }
 
     public SalesforceComponent(CamelContext context) {
         super(context);
+
+        registerExtension(SalesforceComponentVerifierExtension::new);
     }
 
     protected Endpoint createEndpoint(String uri, String remaining, Map<String, Object> parameters) throws Exception {
@@ -656,7 +660,8 @@ public class SalesforceComponent extends DefaultComponent implements VerifiableC
         return classMap;
     }
 
+    @Override
     public ComponentVerifier getVerifier() {
-        return new SalesforceComponentVerifier(this);
+        return (scope, parameters) -> getExtension(ComponentVerifierExtension.class).orElseThrow(UnsupportedOperationException::new).verify(scope, parameters);
     }
 }

http://git-wip-us.apache.org/repos/asf/camel/blob/42529399/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/SalesforceComponentVerifier.java
----------------------------------------------------------------------
diff --git a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/SalesforceComponentVerifier.java b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/SalesforceComponentVerifier.java
deleted file mode 100644
index 438f144..0000000
--- a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/SalesforceComponentVerifier.java
+++ /dev/null
@@ -1,204 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.camel.component.salesforce;
-
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.util.Map;
-import java.util.Optional;
-
-import org.apache.camel.NoSuchOptionException;
-import org.apache.camel.component.salesforce.api.SalesforceException;
-import org.apache.camel.component.salesforce.api.dto.RestError;
-import org.apache.camel.component.salesforce.internal.SalesforceSession;
-import org.apache.camel.component.salesforce.internal.client.DefaultRestClient;
-import org.apache.camel.impl.verifier.DefaultComponentVerifier;
-import org.apache.camel.impl.verifier.OptionsGroup;
-import org.apache.camel.impl.verifier.ResultBuilder;
-import org.apache.camel.impl.verifier.ResultErrorBuilder;
-import org.apache.camel.impl.verifier.ResultErrorHelper;
-import org.apache.camel.util.jsse.SSLContextParameters;
-import org.eclipse.jetty.client.HttpProxy;
-import org.eclipse.jetty.client.Origin;
-import org.eclipse.jetty.client.Socks4Proxy;
-import org.eclipse.jetty.client.util.BasicAuthentication;
-import org.eclipse.jetty.client.util.DigestAuthentication;
-import org.eclipse.jetty.util.ssl.SslContextFactory;
-
-public class SalesforceComponentVerifier extends DefaultComponentVerifier {
-    SalesforceComponentVerifier(SalesforceComponent component) {
-        super("salesforce", component.getCamelContext());
-    }
-
-    // *********************************
-    // Parameters validation
-    // *********************************
-
-    @Override
-    protected Result verifyParameters(Map<String, Object> parameters) {
-        // Validate mandatory component options, needed to be done here as these
-        // options are not properly marked as mandatory in the catalog.
-        //
-        // Validation rules are borrowed from SalesforceLoginConfig's validate
-        // method, which support 3 workflow:
-        //
-        // - OAuth Username/Password Flow
-        // - OAuth Refresh Token Flow:
-        // - OAuth JWT Flow
-        //
-        ResultBuilder builder = ResultBuilder.withStatusAndScope(Result.Status.OK, Scope.PARAMETERS)
-            .errors(ResultErrorHelper.requiresAny(parameters,
-                OptionsGroup.withName(AuthenticationType.USERNAME_PASSWORD)
-                    .options("clientId", "clientSecret", "userName", "password", "!refreshToken", "!keystore"),
-                OptionsGroup.withName(AuthenticationType.REFRESH_TOKEN)
-                    .options("clientId", "clientSecret", "refreshToken", "!password", "!keystore"),
-                OptionsGroup.withName(AuthenticationType.JWT)
-                    .options("clientId", "userName", "keystore", "!password", "!refreshToken")));
-
-        // Validate using the catalog
-        super.verifyParametersAgainstCatalog(builder, parameters);
-
-        return builder.build();
-    }
-
-    // *********************************
-    // Connectivity validation
-    // *********************************
-
-    @Override
-    protected Result verifyConnectivity(Map<String, Object> parameters) {
-        // Default is success
-        ResultBuilder builder = ResultBuilder.withStatusAndScope(Result.Status.OK, Scope.CONNECTIVITY);
-
-        try {
-            SalesforceEndpointConfig configuration = new SalesforceEndpointConfig();
-            setProperties(configuration, parameters);
-
-            SalesforceLoginConfig loginConfig = new SalesforceLoginConfig();
-            setProperties(loginConfig, parameters);
-
-            // Create a dummy SslContextFactory which is needed by SalesforceHttpClient
-            // or the underlying jetty client fails with a NPE
-            SSLContextParameters contextParameters = new SSLContextParameters();
-            SslContextFactory sslContextFactory = new SslContextFactory();
-            sslContextFactory.setSslContext(contextParameters.createSSLContext(getCamelContext()));
-
-            SalesforceHttpClient httpClient = new SalesforceHttpClient(sslContextFactory);
-            httpClient.setConnectTimeout(SalesforceComponent.CONNECTION_TIMEOUT);
-            configureHttpProxy(httpClient, parameters);
-
-            SalesforceSession session = new SalesforceSession(getCamelContext(), httpClient, httpClient.getTimeout(), loginConfig);
-            DefaultRestClient client = new DefaultRestClient(httpClient, configuration.getApiVersion(), configuration.getFormat(), session);
-
-            httpClient.setSession(session);
-            httpClient.start();
-
-            // For authentication check is is enough to use
-            session.start();
-
-            client.start();
-            client.getVersions((response, exception) -> processSalesforceException(builder, Optional.ofNullable(exception)));
-            client.stop();
-
-            session.stop();
-
-            httpClient.stop();
-            httpClient.destroy();
-        } catch (NoSuchOptionException e) {
-            builder.error(
-                ResultErrorBuilder.withMissingOption(e.getOptionName()).build()
-            );
-        } catch (SalesforceException e) {
-            processSalesforceException(builder, Optional.of(e));
-        } catch (Exception e) {
-            builder.error(
-                ResultErrorBuilder.withException(e).build()
-            );
-        }
-
-        return builder.build();
-    }
-
-    // *********************************
-    // Helpers
-    // *********************************
-
-    private void processSalesforceException(ResultBuilder builder, Optional<SalesforceException> exception) {
-        exception.ifPresent(e -> {
-            builder.error(
-                ResultErrorBuilder.withException(e)
-                    .detail(VerificationError.HttpAttribute.HTTP_CODE, e.getStatusCode())
-                    .build()
-            );
-
-            for (RestError error : e.getErrors()) {
-                builder.error(
-                    ResultErrorBuilder.withCode(VerificationError.StandardCode.GENERIC)
-                        .description(error.getMessage())
-                        .parameterKeys(error.getFields())
-                        .detail("salesforce_code", error.getErrorCode())
-                        .build()
-                );
-            }
-        });
-    }
-
-    private void configureHttpProxy(SalesforceHttpClient httpClient, Map<String, Object> parameters) throws NoSuchOptionException, URISyntaxException {
-        Optional<String> httpProxyHost = getOption(parameters, "httpProxyHost", String.class);
-        Optional<Integer> httpProxyPort = getOption(parameters, "httpProxyPort", Integer.class);
-        Optional<String> httpProxyUsername = getOption(parameters, "httpProxyUsername", String.class);
-        Optional<String> httpProxyPassword = getOption(parameters, "httpProxyPassword", String.class);
-
-        if (httpProxyHost.isPresent() && httpProxyPort.isPresent()) {
-            Origin.Address address = new Origin.Address(httpProxyHost.get(), httpProxyPort.get());
-            Boolean isHttpProxySocks4 = getOption(parameters, "isHttpProxySocks4", Boolean.class, () -> false);
-            Boolean isHttpProxySecure = getOption(parameters, "isHttpProxySecure", Boolean.class, () -> true);
-
-            if (isHttpProxySocks4) {
-                httpClient.getProxyConfiguration().getProxies().add(
-                    new Socks4Proxy(address, isHttpProxySecure)
-                );
-            } else {
-                httpClient.getProxyConfiguration().getProxies().add(
-                    new HttpProxy(address, isHttpProxySecure)
-                );
-            }
-        }
-
-        if (httpProxyUsername.isPresent() && httpProxyPassword.isPresent()) {
-            Boolean httpProxyUseDigestAuth = getOption(parameters, "httpProxyUseDigestAuth", Boolean.class, () -> false);
-            String httpProxyAuthUri = getMandatoryOption(parameters, "httpProxyAuthUri", String.class);
-            String httpProxyRealm = getMandatoryOption(parameters, "httpProxyRealm", String.class);
-
-            if (httpProxyUseDigestAuth) {
-                httpClient.getAuthenticationStore().addAuthentication(new DigestAuthentication(
-                    new URI(httpProxyAuthUri),
-                    httpProxyRealm,
-                    httpProxyUsername.get(),
-                    httpProxyPassword.get())
-                );
-            } else {
-                httpClient.getAuthenticationStore().addAuthentication(new BasicAuthentication(
-                    new URI(httpProxyAuthUri),
-                    httpProxyRealm,
-                    httpProxyUsername.get(),
-                    httpProxyPassword.get())
-                );
-            }
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/camel/blob/42529399/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/SalesforceComponentVerifierExtension.java
----------------------------------------------------------------------
diff --git a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/SalesforceComponentVerifierExtension.java b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/SalesforceComponentVerifierExtension.java
new file mode 100644
index 0000000..be71dde
--- /dev/null
+++ b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/SalesforceComponentVerifierExtension.java
@@ -0,0 +1,205 @@
+/**
+ * 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.salesforce;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.Map;
+import java.util.Optional;
+
+import org.apache.camel.component.extension.verifier.DefaultComponentVerifierExtension;
+import org.apache.camel.component.extension.verifier.NoSuchOptionException;
+import org.apache.camel.component.extension.verifier.OptionsGroup;
+import org.apache.camel.component.extension.verifier.ResultBuilder;
+import org.apache.camel.component.extension.verifier.ResultErrorBuilder;
+import org.apache.camel.component.extension.verifier.ResultErrorHelper;
+import org.apache.camel.component.salesforce.api.SalesforceException;
+import org.apache.camel.component.salesforce.api.dto.RestError;
+import org.apache.camel.component.salesforce.internal.SalesforceSession;
+import org.apache.camel.component.salesforce.internal.client.DefaultRestClient;
+import org.apache.camel.util.jsse.SSLContextParameters;
+import org.eclipse.jetty.client.HttpProxy;
+import org.eclipse.jetty.client.Origin;
+import org.eclipse.jetty.client.Socks4Proxy;
+import org.eclipse.jetty.client.util.BasicAuthentication;
+import org.eclipse.jetty.client.util.DigestAuthentication;
+import org.eclipse.jetty.util.ssl.SslContextFactory;
+
+public class SalesforceComponentVerifierExtension extends DefaultComponentVerifierExtension {
+
+    SalesforceComponentVerifierExtension() {
+        super("salesforce");
+    }
+
+    // *********************************
+    // Parameters validation
+    // *********************************
+
+    @Override
+    protected Result verifyParameters(Map<String, Object> parameters) {
+        // Validate mandatory component options, needed to be done here as these
+        // options are not properly marked as mandatory in the catalog.
+        //
+        // Validation rules are borrowed from SalesforceLoginConfig's validate
+        // method, which support 3 workflow:
+        //
+        // - OAuth Username/Password Flow
+        // - OAuth Refresh Token Flow:
+        // - OAuth JWT Flow
+        //
+        ResultBuilder builder = ResultBuilder.withStatusAndScope(Result.Status.OK, Scope.PARAMETERS)
+            .errors(ResultErrorHelper.requiresAny(parameters,
+                OptionsGroup.withName(AuthenticationType.USERNAME_PASSWORD)
+                    .options("clientId", "clientSecret", "userName", "password", "!refreshToken", "!keystore"),
+                OptionsGroup.withName(AuthenticationType.REFRESH_TOKEN)
+                    .options("clientId", "clientSecret", "refreshToken", "!password", "!keystore"),
+                OptionsGroup.withName(AuthenticationType.JWT)
+                    .options("clientId", "userName", "keystore", "!password", "!refreshToken")));
+
+        // Validate using the catalog
+        super.verifyParametersAgainstCatalog(builder, parameters);
+
+        return builder.build();
+    }
+
+    // *********************************
+    // Connectivity validation
+    // *********************************
+
+    @Override
+    protected Result verifyConnectivity(Map<String, Object> parameters) {
+        // Default is success
+        ResultBuilder builder = ResultBuilder.withStatusAndScope(Result.Status.OK, Scope.CONNECTIVITY);
+
+        try {
+            SalesforceEndpointConfig configuration = new SalesforceEndpointConfig();
+            setProperties(configuration, parameters);
+
+            SalesforceLoginConfig loginConfig = new SalesforceLoginConfig();
+            setProperties(loginConfig, parameters);
+
+            // Create a dummy SslContextFactory which is needed by SalesforceHttpClient
+            // or the underlying jetty client fails with a NPE
+            SSLContextParameters contextParameters = new SSLContextParameters();
+            SslContextFactory sslContextFactory = new SslContextFactory();
+            sslContextFactory.setSslContext(contextParameters.createSSLContext(getCamelContext()));
+
+            SalesforceHttpClient httpClient = new SalesforceHttpClient(sslContextFactory);
+            httpClient.setConnectTimeout(SalesforceComponent.CONNECTION_TIMEOUT);
+            configureHttpProxy(httpClient, parameters);
+
+            SalesforceSession session = new SalesforceSession(getCamelContext(), httpClient, httpClient.getTimeout(), loginConfig);
+            DefaultRestClient client = new DefaultRestClient(httpClient, configuration.getApiVersion(), configuration.getFormat(), session);
+
+            httpClient.setSession(session);
+            httpClient.start();
+
+            // For authentication check is is enough to use
+            session.start();
+
+            client.start();
+            client.getVersions((response, exception) -> processSalesforceException(builder, Optional.ofNullable(exception)));
+            client.stop();
+
+            session.stop();
+
+            httpClient.stop();
+            httpClient.destroy();
+        } catch (NoSuchOptionException e) {
+            builder.error(
+                ResultErrorBuilder.withMissingOption(e.getOptionName()).build()
+            );
+        } catch (SalesforceException e) {
+            processSalesforceException(builder, Optional.of(e));
+        } catch (Exception e) {
+            builder.error(
+                ResultErrorBuilder.withException(e).build()
+            );
+        }
+
+        return builder.build();
+    }
+
+    // *********************************
+    // Helpers
+    // *********************************
+
+    private void processSalesforceException(ResultBuilder builder, Optional<SalesforceException> exception) {
+        exception.ifPresent(e -> {
+            builder.error(
+                ResultErrorBuilder.withException(e)
+                    .detail(VerificationError.HttpAttribute.HTTP_CODE, e.getStatusCode())
+                    .build()
+            );
+
+            for (RestError error : e.getErrors()) {
+                builder.error(
+                    ResultErrorBuilder.withCode(VerificationError.StandardCode.GENERIC)
+                        .description(error.getMessage())
+                        .parameterKeys(error.getFields())
+                        .detail("salesforce_code", error.getErrorCode())
+                        .build()
+                );
+            }
+        });
+    }
+
+    private void configureHttpProxy(SalesforceHttpClient httpClient, Map<String, Object> parameters) throws NoSuchOptionException, URISyntaxException {
+        Optional<String> httpProxyHost = getOption(parameters, "httpProxyHost", String.class);
+        Optional<Integer> httpProxyPort = getOption(parameters, "httpProxyPort", Integer.class);
+        Optional<String> httpProxyUsername = getOption(parameters, "httpProxyUsername", String.class);
+        Optional<String> httpProxyPassword = getOption(parameters, "httpProxyPassword", String.class);
+
+        if (httpProxyHost.isPresent() && httpProxyPort.isPresent()) {
+            Origin.Address address = new Origin.Address(httpProxyHost.get(), httpProxyPort.get());
+            Boolean isHttpProxySocks4 = getOption(parameters, "isHttpProxySocks4", Boolean.class, () -> false);
+            Boolean isHttpProxySecure = getOption(parameters, "isHttpProxySecure", Boolean.class, () -> true);
+
+            if (isHttpProxySocks4) {
+                httpClient.getProxyConfiguration().getProxies().add(
+                    new Socks4Proxy(address, isHttpProxySecure)
+                );
+            } else {
+                httpClient.getProxyConfiguration().getProxies().add(
+                    new HttpProxy(address, isHttpProxySecure)
+                );
+            }
+        }
+
+        if (httpProxyUsername.isPresent() && httpProxyPassword.isPresent()) {
+            Boolean httpProxyUseDigestAuth = getOption(parameters, "httpProxyUseDigestAuth", Boolean.class, () -> false);
+            String httpProxyAuthUri = getMandatoryOption(parameters, "httpProxyAuthUri", String.class);
+            String httpProxyRealm = getMandatoryOption(parameters, "httpProxyRealm", String.class);
+
+            if (httpProxyUseDigestAuth) {
+                httpClient.getAuthenticationStore().addAuthentication(new DigestAuthentication(
+                    new URI(httpProxyAuthUri),
+                    httpProxyRealm,
+                    httpProxyUsername.get(),
+                    httpProxyPassword.get())
+                );
+            } else {
+                httpClient.getAuthenticationStore().addAuthentication(new BasicAuthentication(
+                    new URI(httpProxyAuthUri),
+                    httpProxyRealm,
+                    httpProxyUsername.get(),
+                    httpProxyPassword.get())
+                );
+            }
+        }
+    }
+}


[15/19] camel git commit: CAMEL-11555: ServiceNow : create a maven plugin to generate models based on table layout

Posted by lb...@apache.org.
http://git-wip-us.apache.org/repos/asf/camel/blob/109da7c9/components/camel-servicenow/camel-servicenow-component/src/test/java/org/apache/camel/component/servicenow/ServiceNowServiceCatalogTest.java
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/camel-servicenow-component/src/test/java/org/apache/camel/component/servicenow/ServiceNowServiceCatalogTest.java b/components/camel-servicenow/camel-servicenow-component/src/test/java/org/apache/camel/component/servicenow/ServiceNowServiceCatalogTest.java
new file mode 100644
index 0000000..9562be8
--- /dev/null
+++ b/components/camel-servicenow/camel-servicenow-component/src/test/java/org/apache/camel/component/servicenow/ServiceNowServiceCatalogTest.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.servicenow;
+
+import java.util.List;
+import java.util.Map;
+
+import org.apache.camel.CamelExecutionException;
+import org.apache.camel.Produce;
+import org.apache.camel.ProducerTemplate;
+import org.apache.camel.builder.RouteBuilder;
+import org.junit.Test;
+
+public class ServiceNowServiceCatalogTest extends ServiceNowTestSupport {
+    @Produce(uri = "direct:servicenow")
+    ProducerTemplate template;
+
+    @Test
+    public void testRetrieveServiceCatalogsAndCategories() throws Exception {
+        List<Map> result1 = template.requestBodyAndHeaders(
+            "direct:servicenow",
+            null,
+            kvBuilder()
+                .put(ServiceNowConstants.RESOURCE, ServiceNowConstants.RESOURCE_SERVICE_CATALOG)
+                .put(ServiceNowConstants.ACTION, ServiceNowConstants.ACTION_RETRIEVE)
+                .build(),
+            List.class
+        );
+
+        assertFalse(result1.isEmpty());
+
+        List<Map> result2 = template.requestBodyAndHeaders(
+            "direct:servicenow",
+            null,
+            kvBuilder()
+                .put(ServiceNowConstants.RESOURCE, ServiceNowConstants.RESOURCE_SERVICE_CATALOG)
+                .put(ServiceNowConstants.ACTION, ServiceNowConstants.ACTION_RETRIEVE)
+                .put(ServiceNowConstants.ACTION_SUBJECT, ServiceNowConstants.ACTION_SUBJECT_CATEGORIES)
+                .put(ServiceNowParams.PARAM_SYS_ID, result1.get(0).get("sys_id"))
+                .build(),
+            List.class
+        );
+
+        assertFalse(result2.isEmpty());
+    }
+
+    @Test(expected = CamelExecutionException.class)
+    public void testWrongSubject() throws Exception {
+        List<Map> result = template.requestBodyAndHeaders(
+            "direct:servicenow",
+            null,
+            kvBuilder()
+                .put(ServiceNowConstants.RESOURCE, ServiceNowConstants.RESOURCE_SERVICE_CATALOG)
+                .put(ServiceNowConstants.ACTION, ServiceNowConstants.ACTION_RETRIEVE)
+                .put(ServiceNowConstants.ACTION_SUBJECT, "Invalid")
+                .build(),
+            List.class
+        );
+
+        assertFalse(result.isEmpty());
+    }
+
+    // *************************************************************************
+    //
+    // *************************************************************************
+
+    @Override
+    protected RouteBuilder createRouteBuilder() throws Exception {
+        return new RouteBuilder() {
+            public void configure() {
+                from("direct:servicenow")
+                    .to("servicenow:{{env:SERVICENOW_INSTANCE}}")
+                    .to("log:org.apache.camel.component.servicenow?level=INFO&showAll=true")
+                    .to("mock:servicenow");
+            }
+        };
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/109da7c9/components/camel-servicenow/camel-servicenow-component/src/test/java/org/apache/camel/component/servicenow/ServiceNowTableTest.java
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/camel-servicenow-component/src/test/java/org/apache/camel/component/servicenow/ServiceNowTableTest.java b/components/camel-servicenow/camel-servicenow-component/src/test/java/org/apache/camel/component/servicenow/ServiceNowTableTest.java
new file mode 100644
index 0000000..e775e85
--- /dev/null
+++ b/components/camel-servicenow/camel-servicenow-component/src/test/java/org/apache/camel/component/servicenow/ServiceNowTableTest.java
@@ -0,0 +1,361 @@
+/**
+ * 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.servicenow;
+
+import java.util.List;
+
+import org.apache.camel.CamelExecutionException;
+import org.apache.camel.Exchange;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.component.servicenow.model.Incident;
+import org.apache.camel.component.servicenow.model.IncidentWithParms;
+import org.junit.Test;
+
+public class ServiceNowTableTest extends ServiceNowTestSupport {
+
+    @Test
+    public void testRetrieveSome() throws Exception {
+        MockEndpoint mock = getMockEndpoint("mock:servicenow");
+        mock.expectedMessageCount(1);
+
+        template().sendBodyAndHeaders(
+            "direct:servicenow",
+            null,
+            kvBuilder()
+                .put(ServiceNowConstants.RESOURCE, "table")
+                .put(ServiceNowConstants.ACTION, ServiceNowConstants.ACTION_RETRIEVE)
+                .put(ServiceNowParams.SYSPARM_LIMIT, 10)
+                .put(ServiceNowParams.PARAM_TABLE_NAME, "incident")
+                .build()
+        );
+
+        mock.assertIsSatisfied();
+
+        Exchange exchange = mock.getExchanges().get(0);
+        List<Incident> items = exchange.getIn().getBody(List.class);
+
+        assertNotNull(items);
+        assertTrue(items.size() <= 10);
+        assertNotNull(exchange.getIn().getHeader(ServiceNowConstants.RESPONSE_TYPE));
+        assertNotNull(exchange.getIn().getHeader(ServiceNowConstants.OFFSET_FIRST));
+        assertNotNull(exchange.getIn().getHeader(ServiceNowConstants.OFFSET_NEXT));
+        assertNotNull(exchange.getIn().getHeader(ServiceNowConstants.OFFSET_LAST));
+    }
+
+    @Test
+    public void testRetrieveSomeWithParams() throws Exception {
+        MockEndpoint mock = getMockEndpoint("mock:servicenow");
+        mock.expectedMessageCount(1);
+
+        template().sendBodyAndHeaders(
+            "direct:servicenow",
+            null,
+            kvBuilder()
+                .put(ServiceNowConstants.RESOURCE, "table")
+                .put(ServiceNowConstants.ACTION, ServiceNowConstants.ACTION_RETRIEVE)
+                .put(ServiceNowParams.SYSPARM_LIMIT, 10)
+                .put(ServiceNowParams.SYSPARM_EXCLUDE_REFERENCE_LINK, false)
+                .put(ServiceNowParams.PARAM_TABLE_NAME, "incident")
+                .put(ServiceNowConstants.MODEL, IncidentWithParms.class)
+                .build()
+        );
+
+        mock.assertIsSatisfied();
+
+        Exchange exchange = mock.getExchanges().get(0);
+        List<Incident> items = exchange.getIn().getBody(List.class);
+
+        assertNotNull(items);
+        assertFalse(items.isEmpty());
+        assertTrue(items.size() <= 10);
+        assertNotNull(exchange.getIn().getHeader(ServiceNowConstants.RESPONSE_TYPE));
+        assertNotNull(exchange.getIn().getHeader(ServiceNowConstants.OFFSET_FIRST));
+        assertNotNull(exchange.getIn().getHeader(ServiceNowConstants.OFFSET_NEXT));
+        assertNotNull(exchange.getIn().getHeader(ServiceNowConstants.OFFSET_LAST));
+    }
+
+    @Test
+    public void testRetrieveSomeWithDefaults() throws Exception {
+        MockEndpoint mock = getMockEndpoint("mock:servicenow-defaults");
+        mock.expectedMessageCount(1);
+
+        template().sendBodyAndHeaders(
+            "direct:servicenow-defaults",
+            null,
+            kvBuilder()
+                .put(ServiceNowConstants.ACTION, ServiceNowConstants.ACTION_RETRIEVE)
+                .put(ServiceNowParams.SYSPARM_LIMIT, 10)
+                .build()
+        );
+
+        mock.assertIsSatisfied();
+
+        Exchange exchange = mock.getExchanges().get(0);
+        List<Incident> items = exchange.getIn().getBody(List.class);
+
+        assertNotNull(items);
+        assertTrue(items.size() <= 10);
+    }
+
+    @Test
+    public void testIncidentWorkflow() throws Exception {
+
+        Incident incident = null;
+        String sysId;
+        String number;
+        MockEndpoint mock = getMockEndpoint("mock:servicenow");
+
+        // ************************
+        // Create incident
+        // ************************
+
+        {
+            mock.reset();
+            mock.expectedMessageCount(1);
+
+            incident = new Incident();
+            incident.setDescription("my incident");
+            incident.setShortDescription("An incident");
+            incident.setSeverity(1);
+            incident.setImpact(1);
+
+            template().sendBodyAndHeaders(
+                "direct:servicenow",
+                incident,
+                kvBuilder()
+                    .put(ServiceNowConstants.RESOURCE, "table")
+                    .put(ServiceNowConstants.ACTION, ServiceNowConstants.ACTION_CREATE)
+                    .put(ServiceNowParams.PARAM_TABLE_NAME, "incident")
+                    .build()
+            );
+
+            mock.assertIsSatisfied();
+
+            incident = mock.getExchanges().get(0).getIn().getBody(Incident.class);
+            sysId = incident.getId();
+            number = incident.getNumber();
+
+            LOGGER.info("****************************************************");
+            LOGGER.info(" Incident created");
+            LOGGER.info("  sysid  = {}", sysId);
+            LOGGER.info("  number = {}", number);
+            LOGGER.info("****************************************************");
+        }
+
+        // ************************
+        // Search for the incident
+        // ************************
+
+        {
+            LOGGER.info("Search the record {}", sysId);
+
+            mock.reset();
+            mock.expectedMessageCount(1);
+
+            template().sendBodyAndHeaders(
+                "direct:servicenow",
+                null,
+                kvBuilder()
+                    .put(ServiceNowConstants.RESOURCE, "table")
+                    .put(ServiceNowConstants.ACTION, ServiceNowConstants.ACTION_RETRIEVE)
+                    .put(ServiceNowParams.PARAM_TABLE_NAME, "incident")
+                    .put(ServiceNowParams.SYSPARM_QUERY, "number=" + number)
+                    .build()
+            );
+
+            mock.assertIsSatisfied();
+
+            List<Incident> incidents = mock.getExchanges().get(0).getIn().getBody(List.class);
+            assertEquals(1, incidents.size());
+            assertEquals(number, incidents.get(0).getNumber());
+            assertEquals(sysId, incidents.get(0).getId());
+        }
+
+        // ************************
+        // Modify the incident
+        // ************************
+
+        {
+            LOGGER.info("Update the record {}", sysId);
+
+            mock.reset();
+            mock.expectedMessageCount(1);
+
+            incident = new Incident();
+            incident.setDescription("my incident");
+            incident.setShortDescription("The incident");
+            incident.setSeverity(2);
+            incident.setImpact(3);
+
+            template().sendBodyAndHeaders(
+                "direct:servicenow",
+                incident,
+                kvBuilder()
+                    .put(ServiceNowConstants.RESOURCE, "table")
+                    .put(ServiceNowConstants.ACTION, ServiceNowConstants.ACTION_MODIFY)
+                    .put(ServiceNowParams.PARAM_TABLE_NAME, "incident")
+                    .put(ServiceNowParams.PARAM_SYS_ID, sysId)
+                    .build()
+            );
+
+            mock.assertIsSatisfied();
+
+            incident = mock.getExchanges().get(0).getIn().getBody(Incident.class);
+            assertEquals(number, incident.getNumber());
+            assertEquals(2, incident.getSeverity());
+            assertEquals(3, incident.getImpact());
+            assertEquals("The incident", incident.getShortDescription());
+        }
+
+        // ************************
+        // Retrieve it via query
+        // ************************
+
+        {
+            LOGGER.info("Retrieve the record {}", sysId);
+
+            mock.reset();
+            mock.expectedMessageCount(1);
+
+            template().sendBodyAndHeaders(
+                "direct:servicenow",
+                null,
+                kvBuilder()
+                    .put(ServiceNowConstants.RESOURCE, "table")
+                    .put(ServiceNowConstants.ACTION, ServiceNowConstants.ACTION_RETRIEVE)
+                    .put(ServiceNowParams.PARAM_TABLE_NAME, "incident")
+                    .put(ServiceNowParams.SYSPARM_QUERY, "number=" + number)
+                    .build()
+            );
+
+            mock.assertIsSatisfied();
+
+            List<Incident> incidents = mock.getExchanges().get(0).getIn().getBody(List.class);
+            assertEquals(1, incidents.size());
+            assertEquals(number, incidents.get(0).getNumber());
+            assertEquals(sysId, incidents.get(0).getId());
+            assertEquals(2, incidents.get(0).getSeverity());
+            assertEquals(3, incidents.get(0).getImpact());
+            assertEquals("The incident", incidents.get(0).getShortDescription());
+        }
+
+        // ************************
+        // Retrieve by sys id
+        // ************************
+
+        {
+            LOGGER.info("Search the record {}", sysId);
+
+            mock.reset();
+            mock.expectedMessageCount(1);
+
+            template().sendBodyAndHeaders(
+                "direct:servicenow",
+                null,
+                kvBuilder()
+                    .put(ServiceNowConstants.RESOURCE, "table")
+                    .put(ServiceNowConstants.ACTION, ServiceNowConstants.ACTION_RETRIEVE)
+                    .put(ServiceNowParams.PARAM_TABLE_NAME, "incident")
+                    .put(ServiceNowParams.PARAM_SYS_ID, sysId)
+                    .build()
+            );
+
+            mock.assertIsSatisfied();
+
+            incident = mock.getExchanges().get(0).getIn().getBody(Incident.class);
+            assertEquals(2, incident.getSeverity());
+            assertEquals(3, incident.getImpact());
+            assertEquals("The incident", incident.getShortDescription());
+            assertEquals(number, incident.getNumber());
+        }
+
+        // ************************
+        // Delete it
+        // ************************
+
+        {
+            LOGGER.info("Delete the record {}", sysId);
+
+            mock.reset();
+            mock.expectedMessageCount(1);
+
+            template().sendBodyAndHeaders(
+                "direct:servicenow",
+                null,
+                kvBuilder()
+                    .put(ServiceNowConstants.RESOURCE, "table")
+                    .put(ServiceNowConstants.ACTION, ServiceNowConstants.ACTION_DELETE)
+                    .put(ServiceNowParams.PARAM_TABLE_NAME, "incident")
+                    .put(ServiceNowParams.PARAM_SYS_ID, sysId)
+                    .build()
+            );
+
+            mock.assertIsSatisfied();
+        }
+
+        // ************************
+        // Retrieve by id, should fail
+        // ************************
+
+        {
+            LOGGER.info("Find the record {}, should fail", sysId);
+
+            try {
+                template().sendBodyAndHeaders(
+                    "direct:servicenow",
+                    null,
+                    kvBuilder()
+                        .put(ServiceNowConstants.RESOURCE, "table")
+                        .put(ServiceNowConstants.ACTION, ServiceNowConstants.ACTION_RETRIEVE)
+                        .put(ServiceNowParams.PARAM_SYS_ID, sysId)
+                        .put(ServiceNowParams.PARAM_TABLE_NAME, "incident")
+                        .build()
+                );
+
+                fail("Record " + number + " should have been deleted");
+            } catch (CamelExecutionException e) {
+                assertTrue(e.getCause() instanceof ServiceNowException);
+                // we are good
+            }
+        }
+    }
+
+    // *************************************************************************
+    //
+    // *************************************************************************
+
+    @Override
+    protected RouteBuilder createRouteBuilder() throws Exception {
+        return new RouteBuilder() {
+            public void configure() {
+                from("direct:servicenow")
+                    .to("servicenow:{{env:SERVICENOW_INSTANCE}}"
+                        + "?model.incident=org.apache.camel.component.servicenow.model.Incident")
+                    .to("log:org.apache.camel.component.servicenow?level=INFO&showAll=true")
+                    .to("mock:servicenow");
+                from("direct:servicenow-defaults")
+                    .to("servicenow:{{env:SERVICENOW_INSTANCE}}"
+                        + "?model.incident=org.apache.camel.component.servicenow.model.Incident"
+                        + "&resource=table"
+                        + "&table=incident")
+                    .to("log:org.apache.camel.component.servicenow?level=INFO&showAll=true")
+                    .to("mock:servicenow-defaults");
+            }
+        };
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/109da7c9/components/camel-servicenow/camel-servicenow-component/src/test/java/org/apache/camel/component/servicenow/ServiceNowTest.java
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/camel-servicenow-component/src/test/java/org/apache/camel/component/servicenow/ServiceNowTest.java b/components/camel-servicenow/camel-servicenow-component/src/test/java/org/apache/camel/component/servicenow/ServiceNowTest.java
new file mode 100644
index 0000000..426a8bfa
--- /dev/null
+++ b/components/camel-servicenow/camel-servicenow-component/src/test/java/org/apache/camel/component/servicenow/ServiceNowTest.java
@@ -0,0 +1,174 @@
+/**
+ * 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.servicenow;
+
+import java.util.UUID;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import org.apache.camel.CamelExecutionException;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.component.servicenow.model.Incident;
+import org.junit.Test;
+
+public class ServiceNowTest extends ServiceNowTestSupport {
+
+    @Test
+    public void testExceptions() throws Exception {
+        // 404
+        try {
+            template().sendBodyAndHeaders(
+                "direct:servicenow",
+                null,
+                kvBuilder()
+                    .put(ServiceNowConstants.RESOURCE, "table")
+                    .put(ServiceNowConstants.ACTION, ServiceNowConstants.ACTION_RETRIEVE)
+                    .put(ServiceNowParams.SYSPARM_QUERY, "number=" + UUID.randomUUID().toString())
+                    .put(ServiceNowParams.PARAM_TABLE_NAME, "incident")
+                    .build()
+            );
+        } catch (CamelExecutionException e) {
+            assertTrue(e.getCause() instanceof ServiceNowException);
+
+            ServiceNowException sne = (ServiceNowException)e.getCause();
+            assertEquals("failure", sne.getStatus());
+            assertTrue(sne.getMessage().contains("No Record found"));
+            assertTrue(sne.getDetail().contains("Records matching query not found"));
+        }
+
+        // 400
+        try {
+            template().sendBodyAndHeaders(
+                "direct:servicenow",
+                null,
+                kvBuilder()
+                    .put(ServiceNowConstants.RESOURCE, "table")
+                    .put(ServiceNowConstants.ACTION, ServiceNowConstants.ACTION_RETRIEVE)
+                    .put(ServiceNowParams.SYSPARM_QUERY, "number=" + UUID.randomUUID().toString())
+                    .put(ServiceNowParams.PARAM_TABLE_NAME, "notExistingTable")
+                    .build()
+            );
+        } catch (CamelExecutionException e) {
+            assertTrue(e.getCause() instanceof ServiceNowException);
+
+            ServiceNowException sne = (ServiceNowException)e.getCause();
+            assertEquals("failure", sne.getStatus());
+            assertTrue(sne.getMessage().contains("Invalid table notExistingTable"));
+            assertNull(sne.getDetail());
+        }
+    }
+
+    @Test
+    public void testBodyMismatch() throws Exception {
+        try {
+            template().sendBodyAndHeaders(
+                "direct:servicenow",
+                "NotAnIncidentObject",
+                kvBuilder()
+                    .put(ServiceNowConstants.RESOURCE, "table")
+                    .put(ServiceNowConstants.ACTION, ServiceNowConstants.ACTION_CREATE)
+                    .put(ServiceNowParams.PARAM_TABLE_NAME, "incident")
+                    .build()
+            );
+
+            fail("Should fail as body is not compatible with model defined in route for table incident");
+        } catch (CamelExecutionException e) {
+            assertTrue(e.getCause() instanceof IllegalArgumentException);
+        }
+    }
+
+    @Test
+    public void testRequestResponseModels() throws Exception {
+        MockEndpoint mock = getMockEndpoint("mock:servicenow");
+
+        mock.reset();
+        mock.expectedMessageCount(1);
+
+        Incident incident = new Incident();
+        incident.setDescription("my incident");
+        incident.setShortDescription("An incident");
+        incident.setSeverity(1);
+        incident.setImpact(1);
+
+        template().sendBodyAndHeaders(
+            "direct:servicenow",
+            incident,
+            kvBuilder()
+                .put(ServiceNowConstants.RESOURCE, ServiceNowConstants.RESOURCE_TABLE)
+                .put(ServiceNowConstants.ACTION, ServiceNowConstants.ACTION_CREATE)
+                .put(ServiceNowConstants.REQUEST_MODEL, Incident.class)
+                .put(ServiceNowConstants.RESPONSE_MODEL, JsonNode.class)
+                .put(ServiceNowParams.PARAM_TABLE_NAME, "incident")
+                .build()
+        );
+
+        mock.assertIsSatisfied();
+
+        Object body = mock.getExchanges().get(0).getIn().getBody();
+        assertNotNull(body);
+        assertTrue(body instanceof JsonNode);
+    }
+
+    @Test
+    public void testVersionedApiRequest() throws Exception {
+        MockEndpoint mock = getMockEndpoint("mock:servicenow");
+
+        mock.reset();
+        mock.expectedMessageCount(1);
+
+        Incident incident = new Incident();
+        incident.setDescription("my incident");
+        incident.setShortDescription("An incident");
+        incident.setSeverity(1);
+        incident.setImpact(1);
+
+        template().sendBodyAndHeaders(
+            "direct:servicenow",
+            incident,
+            kvBuilder()
+                .put(ServiceNowConstants.RESOURCE, ServiceNowConstants.RESOURCE_TABLE)
+                .put(ServiceNowConstants.API_VERSION, "v1")
+                .put(ServiceNowConstants.ACTION, ServiceNowConstants.ACTION_CREATE)
+                .put(ServiceNowConstants.REQUEST_MODEL, Incident.class)
+                .put(ServiceNowConstants.RESPONSE_MODEL, JsonNode.class)
+                .put(ServiceNowParams.PARAM_TABLE_NAME, "incident")
+                .build()
+        );
+
+        mock.assertIsSatisfied();
+
+        Object body = mock.getExchanges().get(0).getIn().getBody();
+        assertNotNull(body);
+        assertTrue(body instanceof JsonNode);
+    }
+
+    // *************************************************************************
+    //
+    // *************************************************************************
+
+    @Override
+    protected RouteBuilder createRouteBuilder() throws Exception {
+        return new RouteBuilder() {
+            public void configure() {
+                from("direct:servicenow")
+                    .to("servicenow:{{env:SERVICENOW_INSTANCE}}")
+                    .to("log:org.apache.camel.component.servicenow?level=INFO&showAll=true")
+                    .to("mock:servicenow");
+            }
+        };
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/109da7c9/components/camel-servicenow/camel-servicenow-component/src/test/java/org/apache/camel/component/servicenow/ServiceNowTestSupport.java
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/camel-servicenow-component/src/test/java/org/apache/camel/component/servicenow/ServiceNowTestSupport.java b/components/camel-servicenow/camel-servicenow-component/src/test/java/org/apache/camel/component/servicenow/ServiceNowTestSupport.java
new file mode 100644
index 0000000..b3cc5c4
--- /dev/null
+++ b/components/camel-servicenow/camel-servicenow-component/src/test/java/org/apache/camel/component/servicenow/ServiceNowTestSupport.java
@@ -0,0 +1,122 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.servicenow;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.test.junit4.CamelTestSupport;
+import org.apache.camel.util.ObjectHelper;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+class ServiceNowTestSupport extends CamelTestSupport {
+    protected static final Logger LOGGER = LoggerFactory.getLogger(ServiceNowTestSupport.class);
+
+    private final boolean setUpComponent;
+
+    ServiceNowTestSupport() {
+        this(true);
+    }
+
+    ServiceNowTestSupport(boolean setUpComponent) {
+        this.setUpComponent = setUpComponent;
+    }
+
+    @Override
+    protected CamelContext createCamelContext() throws Exception {
+        CamelContext context = super.createCamelContext();
+        if (setUpComponent) {
+            configureServicenowComponent(context);
+        }
+
+        return context;
+    }
+
+    protected Map<String, Object> getParameters() {
+        HashMap<String, Object> parameters = new HashMap<>();
+        parameters.put("instanceName", getSystemPropertyOrEnvVar("servicenow.instance"));
+        parameters.put("userName", getSystemPropertyOrEnvVar("servicenow.username"));
+        parameters.put("password", getSystemPropertyOrEnvVar("servicenow.password"));
+        parameters.put("oauthClientId", getSystemPropertyOrEnvVar("servicenow.oauth2.client.id"));
+        parameters.put("oauthClientSecret", getSystemPropertyOrEnvVar("servicenow.oauth2.client.secret"));
+
+        return parameters;
+    }
+
+    public void configureServicenowComponent(CamelContext camelContext) throws Exception {
+        String userName = getSystemPropertyOrEnvVar("servicenow.username");
+        String password = getSystemPropertyOrEnvVar("servicenow.password");
+        String oauthClientId = getSystemPropertyOrEnvVar("servicenow.oauth2.client.id");
+        String oauthClientSecret = getSystemPropertyOrEnvVar("servicenow.oauth2.client.secret");
+
+        if (ObjectHelper.isNotEmpty(userName) && ObjectHelper.isNotEmpty(password)) {
+            ServiceNowComponent component = new ServiceNowComponent();
+            component.setUserName(userName);
+            component.setPassword(password);
+
+            if (ObjectHelper.isNotEmpty(oauthClientId) && ObjectHelper.isNotEmpty(oauthClientSecret)) {
+                component.setOauthClientId(oauthClientId);
+                component.setOauthClientSecret(oauthClientSecret);
+            }
+
+            camelContext.addComponent("servicenow", component);
+        }
+    }
+
+    public static String getSystemPropertyOrEnvVar(String systemProperty) {
+        String answer = System.getProperty(systemProperty);
+        if (ObjectHelper.isEmpty(answer)) {
+            String envProperty = systemProperty.toUpperCase().replaceAll("[.-]", "_");
+            answer = System.getenv(envProperty);
+        }
+
+        return answer;
+    }
+
+    protected static KVBuilder kvBuilder() {
+        return new KVBuilder(new HashMap<>());
+    }
+
+    protected static KVBuilder kvBuilder(Map<String, Object> headers) {
+        return new KVBuilder(headers);
+    }
+
+    protected static final class KVBuilder {
+        private final Map<String, Object> headers;
+
+        private KVBuilder(Map<String, Object> headers) {
+            this.headers = new HashMap<>(headers);
+        }
+
+        public KVBuilder put(String key, Object val) {
+            headers.put(key, val);
+            return this;
+        }
+
+        public KVBuilder put(ServiceNowParam key, Object val) {
+            headers.put(key.getHeader(), val);
+            return this;
+        }
+
+        public Map<String, Object> build() {
+            return Collections.unmodifiableMap(this.headers);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/109da7c9/components/camel-servicenow/camel-servicenow-component/src/test/java/org/apache/camel/component/servicenow/model/AttachmentMeta.java
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/camel-servicenow-component/src/test/java/org/apache/camel/component/servicenow/model/AttachmentMeta.java b/components/camel-servicenow/camel-servicenow-component/src/test/java/org/apache/camel/component/servicenow/model/AttachmentMeta.java
new file mode 100644
index 0000000..21fbb38
--- /dev/null
+++ b/components/camel-servicenow/camel-servicenow-component/src/test/java/org/apache/camel/component/servicenow/model/AttachmentMeta.java
@@ -0,0 +1,92 @@
+/**
+ * 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.servicenow.model;
+
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+@JsonIgnoreProperties(ignoreUnknown = true)
+@JsonInclude(JsonInclude.Include.NON_NULL)
+public class AttachmentMeta {
+    @JsonProperty("sys_id")
+    private String id;
+
+    @JsonProperty("download_link")
+    private String downloadLink;
+
+    @JsonProperty("table_name")
+    private String tableName;
+
+    @JsonProperty("table_sys_id")
+    private String tableSysId;
+
+    @JsonProperty("compressed")
+    private Boolean compressed;
+
+    @JsonProperty("file_name")
+    private String fileName;
+
+    public String getId() {
+        return id;
+    }
+
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    public String getDownloadLink() {
+        return downloadLink;
+    }
+
+    public void setDownloadLink(String downloadLink) {
+        this.downloadLink = downloadLink;
+    }
+
+    public String getTableName() {
+        return tableName;
+    }
+
+    public void setTableName(String tableName) {
+        this.tableName = tableName;
+    }
+
+    public String getTableSysId() {
+        return tableSysId;
+    }
+
+    public void setTableSysId(String tableSysId) {
+        this.tableSysId = tableSysId;
+    }
+
+    public Boolean getCompressed() {
+        return compressed;
+    }
+
+    public void setCompressed(Boolean compressed) {
+        this.compressed = compressed;
+    }
+
+    public String getFileName() {
+        return fileName;
+    }
+
+    public void setFileName(String fileName) {
+        this.fileName = fileName;
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/109da7c9/components/camel-servicenow/camel-servicenow-component/src/test/java/org/apache/camel/component/servicenow/model/Incident.java
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/camel-servicenow-component/src/test/java/org/apache/camel/component/servicenow/model/Incident.java b/components/camel-servicenow/camel-servicenow-component/src/test/java/org/apache/camel/component/servicenow/model/Incident.java
new file mode 100644
index 0000000..c909413
--- /dev/null
+++ b/components/camel-servicenow/camel-servicenow-component/src/test/java/org/apache/camel/component/servicenow/model/Incident.java
@@ -0,0 +1,97 @@
+/**
+ * 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.servicenow.model;
+
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+@JsonIgnoreProperties(ignoreUnknown = true)
+@JsonInclude(JsonInclude.Include.NON_NULL)
+public class Incident {
+    @JsonProperty("sys_id")
+    private String id;
+
+    @JsonProperty("number")
+    private String number;
+
+    @JsonProperty("description")
+    private String description;
+
+    @JsonProperty("short_description")
+    private String shortDescription;
+
+    @JsonProperty("severity")
+    private int severity;
+
+    @JsonProperty("impact")
+    private int impact;
+
+
+    public Incident() {
+    }
+
+
+    public String getId() {
+        return id;
+    }
+
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    public String getNumber() {
+        return number;
+    }
+
+    public void setNumber(String number) {
+        this.number = number;
+    }
+
+    public String getDescription() {
+        return description;
+    }
+
+    public void setDescription(String description) {
+        this.description = description;
+    }
+
+    public String getShortDescription() {
+        return shortDescription;
+    }
+
+    public void setShortDescription(String shortDescription) {
+        this.shortDescription = shortDescription;
+    }
+
+    public int getSeverity() {
+        return severity;
+    }
+
+    public void setSeverity(int severity) {
+        this.severity = severity;
+    }
+
+    public int getImpact() {
+        return impact;
+    }
+
+    public void setImpact(int impact) {
+        this.impact = impact;
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/109da7c9/components/camel-servicenow/camel-servicenow-component/src/test/java/org/apache/camel/component/servicenow/model/IncidentWithParms.java
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/camel-servicenow-component/src/test/java/org/apache/camel/component/servicenow/model/IncidentWithParms.java b/components/camel-servicenow/camel-servicenow-component/src/test/java/org/apache/camel/component/servicenow/model/IncidentWithParms.java
new file mode 100644
index 0000000..03ff9ff
--- /dev/null
+++ b/components/camel-servicenow/camel-servicenow-component/src/test/java/org/apache/camel/component/servicenow/model/IncidentWithParms.java
@@ -0,0 +1,64 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.camel.component.servicenow.model;
+
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import org.apache.camel.component.servicenow.annotations.ServiceNowSysParm;
+
+@ServiceNowSysParm(name = "sysparm_exclude_reference_link", value = "true")
+@ServiceNowSysParm(name = "sysparm_fields", value = "id%2Cnumber%2Ccaller_id")
+@JsonIgnoreProperties(ignoreUnknown = true)
+@JsonInclude(JsonInclude.Include.NON_NULL)
+public class IncidentWithParms {
+    @JsonProperty("sys_id")
+    private String id;
+    @JsonProperty("number")
+    private String number;
+    @JsonProperty("caller_id")
+    private String callerId;
+
+    public IncidentWithParms() {
+    }
+
+
+    public String getId() {
+        return id;
+    }
+
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    public String getNumber() {
+        return number;
+    }
+
+    public void setNumber(String number) {
+        this.number = number;
+    }
+
+    public String getCallerId() {
+        return callerId;
+    }
+
+    public void setCallerId(String callerId) {
+        this.callerId = callerId;
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/109da7c9/components/camel-servicenow/camel-servicenow-component/src/test/java/org/apache/camel/component/servicenow/model/Scorecard.java
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/camel-servicenow-component/src/test/java/org/apache/camel/component/servicenow/model/Scorecard.java b/components/camel-servicenow/camel-servicenow-component/src/test/java/org/apache/camel/component/servicenow/model/Scorecard.java
new file mode 100644
index 0000000..dabb23e
--- /dev/null
+++ b/components/camel-servicenow/camel-servicenow-component/src/test/java/org/apache/camel/component/servicenow/model/Scorecard.java
@@ -0,0 +1,46 @@
+/**
+ * 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.servicenow.model;
+
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+@JsonIgnoreProperties(ignoreUnknown = true)
+@JsonInclude(JsonInclude.Include.NON_NULL)
+public class Scorecard {
+    @JsonProperty("name")
+    private String name;
+    @JsonProperty("description")
+    private String description;
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public String getDescription() {
+        return description;
+    }
+
+    public void setDescription(String description) {
+        this.description = description;
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/109da7c9/components/camel-servicenow/camel-servicenow-component/src/test/resources/OSGI-INF/blueprint/blueprint-component-auth.xml
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/camel-servicenow-component/src/test/resources/OSGI-INF/blueprint/blueprint-component-auth.xml b/components/camel-servicenow/camel-servicenow-component/src/test/resources/OSGI-INF/blueprint/blueprint-component-auth.xml
new file mode 100644
index 0000000..14c4c1f
--- /dev/null
+++ b/components/camel-servicenow/camel-servicenow-component/src/test/resources/OSGI-INF/blueprint/blueprint-component-auth.xml
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You under the Apache License, Version 2.0
+    (the "License"); you may not use this file except in compliance with
+    the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+
+-->
+<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
+           xmlns:ext="http://aries.apache.org/blueprint/xmlns/blueprint-ext/v1.0.0">
+
+  <ext:property-placeholder placeholder-prefix="$[" placeholder-suffix="]"/>
+
+  <bean id="servicenow" class="org.apache.camel.component.servicenow.ServiceNowComponent">
+    <property name="userName" value="$[servicenow.username]"/>
+    <property name="password" value="$[servicenow.password]"/>
+  </bean>
+
+  <camelContext xmlns="http://camel.apache.org/schema/blueprint">
+    <route>
+      <from uri="direct:servicenow"/>
+      <multicast>
+        <to uri="direct:route-1"/>
+        <to uri="direct:route-2"/>
+      </multicast>
+    </route>
+
+    <route>
+      <from uri="direct:route-1"/>
+      <to uri="servicenow:{{sys:servicenow.instance}}?excludeReferenceLink=true"/>
+      <to uri="log:org.apache.camel.component.servicenow-1?level=INFO"/>
+      <to uri="mock:servicenow-1"/>
+    </route>
+
+    <route>
+      <from uri="direct:route-2"/>
+      <to uri="servicenow:{{sys:servicenow.instance}}?excludeReferenceLink=false"/>
+      <to uri="log:org.apache.camel.component.servicenow-2?level=INFO"/>
+      <to uri="mock:servicenow-2"/>
+    </route>
+
+  </camelContext>
+
+</blueprint>

http://git-wip-us.apache.org/repos/asf/camel/blob/109da7c9/components/camel-servicenow/camel-servicenow-component/src/test/resources/OSGI-INF/blueprint/blueprint-endpoint-auth.xml
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/camel-servicenow-component/src/test/resources/OSGI-INF/blueprint/blueprint-endpoint-auth.xml b/components/camel-servicenow/camel-servicenow-component/src/test/resources/OSGI-INF/blueprint/blueprint-endpoint-auth.xml
new file mode 100644
index 0000000..f0d1f8b
--- /dev/null
+++ b/components/camel-servicenow/camel-servicenow-component/src/test/resources/OSGI-INF/blueprint/blueprint-endpoint-auth.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You under the Apache License, Version 2.0
+    (the "License"); you may not use this file except in compliance with
+    the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+
+-->
+<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
+           xmlns:ext="http://aries.apache.org/blueprint/xmlns/blueprint-ext/v1.0.0">
+
+  <ext:property-placeholder placeholder-prefix="$[" placeholder-suffix="]"/>
+
+  <bean id="servicenow" class="org.apache.camel.component.servicenow.ServiceNowComponent">
+  </bean>
+
+  <camelContext xmlns="http://camel.apache.org/schema/blueprint">
+    <route>
+      <from uri="direct:servicenow"/>
+        <to uri="servicenow:{{sys:servicenow.instance}}?userName={{sys:servicenow.username}}&amp;password={{sys:servicenow.password}}"/>
+        <to uri="log:org.apache.camel.component.servicenow?level=INFO"/>
+        <to uri="mock:servicenow"/>
+    </route>
+  </camelContext>
+
+</blueprint>

http://git-wip-us.apache.org/repos/asf/camel/blob/109da7c9/components/camel-servicenow/camel-servicenow-component/src/test/resources/log4j2.properties
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/camel-servicenow-component/src/test/resources/log4j2.properties b/components/camel-servicenow/camel-servicenow-component/src/test/resources/log4j2.properties
new file mode 100644
index 0000000..d412256
--- /dev/null
+++ b/components/camel-servicenow/camel-servicenow-component/src/test/resources/log4j2.properties
@@ -0,0 +1,43 @@
+## ---------------------------------------------------------------------------
+## Licensed to the Apache Software Foundation (ASF) under one or more
+## contributor license agreements.  See the NOTICE file distributed with
+## this work for additional information regarding copyright ownership.
+## The ASF licenses this file to You under the Apache License, Version 2.0
+## (the "License"); you may not use this file except in compliance with
+## the License.  You may obtain a copy of the License at
+##
+##      http://www.apache.org/licenses/LICENSE-2.0
+##
+## Unless required by applicable law or agreed to in writing, software
+## distributed under the License is distributed on an "AS IS" BASIS,
+## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+## See the License for the specific language governing permissions and
+## limitations under the License.
+## ---------------------------------------------------------------------------
+
+appender.file.type = File
+appender.file.name = file
+appender.file.fileName = target/camel-servicenow-test.log
+appender.file.layout.type = PatternLayout
+appender.file.layout.pattern = %d %-5p %c{1} - %m %n
+
+appender.out.type = Console
+appender.out.name = out
+appender.out.layout.type = PatternLayout
+appender.out.layout.pattern = %d{HH:mm:ss.SSS} [%-15.15t] %-30.30c{1} %-5p %m%n
+
+logger.servicenow.name = org.apache.camel.component.servicenow
+logger.servicenow.level = DEBUG
+
+logger.metadata.name = org.apache.camel.component.servicenow.ServiceNowMetaDataExtensionTest
+logger.metadata.level = DEBUG
+#logger.metadata.additivity = true
+#logger.metadata.appenderRef.metadata.ref = out
+
+logger.metadata-ext.name = org.apache.camel.component.servicenow.ServiceNowMetaDataExtension
+logger.metadata-ext.level = DEBUG
+#logger.metadata-ext.additivity = true
+#logger.metadata-ext.appenderRef.metadata-ext.ref = out
+
+rootLogger.level = INFO
+rootLogger.appenderRef.root.ref = file

http://git-wip-us.apache.org/repos/asf/camel/blob/109da7c9/components/camel-servicenow/camel-servicenow-component/src/test/resources/my-content.txt
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/camel-servicenow-component/src/test/resources/my-content.txt b/components/camel-servicenow/camel-servicenow-component/src/test/resources/my-content.txt
new file mode 100644
index 0000000..63b8767
--- /dev/null
+++ b/components/camel-servicenow/camel-servicenow-component/src/test/resources/my-content.txt
@@ -0,0 +1,16 @@
+## ---------------------------------------------------------------------------
+## 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.
+## ---------------------------------------------------------------------------
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/camel/blob/109da7c9/components/camel-servicenow/camel-servicenow-maven-plugin/pom.xml
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/camel-servicenow-maven-plugin/pom.xml b/components/camel-servicenow/camel-servicenow-maven-plugin/pom.xml
new file mode 100644
index 0000000..c2b881f
--- /dev/null
+++ b/components/camel-servicenow/camel-servicenow-maven-plugin/pom.xml
@@ -0,0 +1,319 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You under the Apache License, Version 2.0
+    (the "License"); you may not use this file except in compliance with
+    the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+
+  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+    <groupId>org.apache.camel</groupId>
+    <artifactId>camel-servicenow-parent</artifactId>
+    <version>2.20.0-SNAPSHOT</version>
+  </parent>
+
+  <groupId>org.apache.camel.maven</groupId>
+  <artifactId>camel-servicenow-maven-plugin</artifactId>
+  <packaging>maven-plugin</packaging>
+  <name>Camel :: ServiceNow :: Maven plugin</name>
+  <description>Camel ServiceNow Maven plugin</description>
+
+  <properties>
+    <servicenow.component.root>..</servicenow.component.root>
+  </properties>
+
+  <dependencyManagement>
+    <dependencies>
+      <dependency>
+        <groupId>org.apache.camel</groupId>
+        <artifactId>tooling-parent</artifactId>
+        <version>${project.version}</version>
+        <type>pom</type>
+        <scope>import</scope>
+      </dependency>
+    </dependencies>
+  </dependencyManagement>
+
+  <dependencies>
+
+    <dependency>
+      <groupId>org.apache.maven</groupId>
+      <artifactId>maven-core</artifactId>
+      <exclusions>
+        <exclusion>
+          <groupId>org.slf4j</groupId>
+          <artifactId>slf4j-jdk14</artifactId>
+        </exclusion>
+        <exclusion>
+          <groupId>org.slf4j</groupId>
+          <artifactId>jcl-over-slf4j</artifactId>
+        </exclusion>
+        <exclusion>
+          <groupId>org.slf4j</groupId>
+          <artifactId>slf4j-nop</artifactId>
+        </exclusion>
+      </exclusions>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.maven</groupId>
+      <artifactId>maven-artifact</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.maven</groupId>
+      <artifactId>maven-plugin-api</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.maven</groupId>
+      <artifactId>maven-plugin-descriptor</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.maven</groupId>
+      <artifactId>maven-project</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.codehaus.plexus</groupId>
+      <artifactId>plexus-container-default</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.codehaus.plexus</groupId>
+      <artifactId>plexus-utils</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.sonatype.plexus</groupId>
+      <artifactId>plexus-build-api</artifactId>
+    </dependency>
+
+    <dependency>
+      <groupId>org.apache.maven.plugin-tools</groupId>
+      <artifactId>maven-plugin-annotations</artifactId>
+      <version>${maven-plugin-annotations-version}</version>
+      <scope>provided</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.camel</groupId>
+      <artifactId>camel-servicenow</artifactId>
+    </dependency>
+
+    <dependency>
+      <groupId>com.squareup</groupId>
+      <artifactId>javapoet</artifactId>
+      <version>${javapoet-version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.commons</groupId>
+      <artifactId>commons-text</artifactId>
+      <version>${commons-text-version}</version>
+    </dependency>
+
+    <!-- logging -->
+    <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>slf4j-api</artifactId>
+    </dependency>
+      
+    <dependency>
+      <groupId>org.apache.logging.log4j</groupId>
+      <artifactId>log4j-api</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.logging.log4j</groupId>
+      <artifactId>log4j-core</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.logging.log4j</groupId>
+      <artifactId>log4j-slf4j-impl</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.logging.log4j</groupId>
+      <artifactId>log4j-1.2-api</artifactId>
+    </dependency>
+
+    <!-- testing -->
+    <dependency>
+      <groupId>org.apache.maven.plugin-testing</groupId>
+      <artifactId>maven-plugin-testing-harness</artifactId>
+      <version>${maven-plugin-testing-harness-version}</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.camel</groupId>
+      <artifactId>camel-test</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>commons-io</groupId>
+      <artifactId>commons-io</artifactId>
+      <scope>test</scope>
+    </dependency>
+  </dependencies>
+
+  <build>
+    <plugins>
+      <!-- maven-jar-plugin config for Maven plugins. -->
+      <plugin>
+        <artifactId>maven-jar-plugin</artifactId>
+        <configuration>
+          <archive combine.self="override">
+            <manifestFile/>
+            <manifest>
+              <addDefaultSpecificationEntries>true</addDefaultSpecificationEntries>
+              <addDefaultImplementationEntries>true</addDefaultImplementationEntries>
+            </manifest>
+          </archive>
+        </configuration>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.felix</groupId>
+        <artifactId>maven-bundle-plugin</artifactId>
+        <executions>
+          <execution>
+            <phase>none</phase>
+          </execution>
+          <execution>
+            <id>versions</id>
+            <phase>none</phase>
+          </execution>
+          <execution>
+            <id>bundle-manifest</id>
+            <phase>none</phase>
+          </execution>
+        </executions>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.camel</groupId>
+        <artifactId>camel-package-maven-plugin</artifactId>
+        <executions>
+          <execution>
+            <id>prepare</id>
+            <phase>none</phase>
+          </execution>
+          <execution>
+            <id>validate</id>
+            <phase>none</phase>
+          </execution>
+          <execution>
+            <id>readme</id>
+            <phase>none</phase>
+          </execution>
+        </executions>
+      </plugin>
+
+      <!-- Generate plugin help -->
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-plugin-plugin</artifactId>
+        <configuration>
+          <goalPrefix>camel-servicenow</goalPrefix>
+          <skipErrorNoDescriptorsFound>true</skipErrorNoDescriptorsFound>
+        </configuration>
+        <executions>
+          <execution>
+            <id>mojo-descriptor</id>
+            <goals>
+              <goal>descriptor</goal>
+            </goals>
+          </execution>
+          <execution>
+            <id>help-goal</id>
+            <goals>
+              <goal>helpmojo</goal>
+            </goals>
+          </execution>
+        </executions>
+      </plugin>
+      <plugin>
+        <artifactId>maven-surefire-plugin</artifactId>
+        <configuration>
+          <skipTests>true</skipTests>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
+
+  <profiles>
+    <profile>
+      <id>plugin-tests</id>
+      <activation>
+        <property>
+          <name>env.SERVICENOW_INSTANCE</name>
+        </property>
+      </activation>
+      <build>
+        <plugins>
+          <plugin>
+            <artifactId>maven-surefire-plugin</artifactId>
+            <configuration>
+              <skipTests>false</skipTests>
+              <systemPropertyVariables>
+                <servicenow.instance>${env.SERVICENOW_INSTANCE}</servicenow.instance>
+                <servicenow.username>${env.SERVICENOW_USERNAME}</servicenow.username>
+                <servicenow.password>${env.SERVICENOW_PASSWORD}</servicenow.password>
+              </systemPropertyVariables>
+            </configuration>
+          </plugin>
+        </plugins>
+      </build>
+    </profile>
+    <profile>
+      <id>plugin-itest</id>
+      <activation>
+        <activeByDefault>false</activeByDefault>
+      </activation>
+      <build>
+        <plugins>
+          <plugin>
+            <groupId>org.apache.maven.plugins</groupId>
+            <artifactId>maven-invoker-plugin</artifactId>
+            <version>1.8</version>
+            <configuration>
+              <debug>true</debug>
+              <cloneProjectsTo>${project.build.directory}/it</cloneProjectsTo>
+              <pomIncludes>
+                <pomInclude>*/pom.xml</pomInclude>
+              </pomIncludes>
+              <postBuildHookScript>verify</postBuildHookScript>
+              <localRepositoryPath>${project.build.directory}/local-repo</localRepositoryPath>
+              <settingsFile>src/it/settings.xml</settingsFile>
+              <goals>
+                <goal>clean</goal>
+                <goal>test-compile</goal>
+              </goals>
+            </configuration>
+            <executions>
+              <execution>
+                <id>integration-test</id>
+                <goals>
+                  <goal>install</goal>
+                  <goal>integration-test</goal>
+                  <goal>verify</goal>
+                </goals>
+              </execution>
+            </executions>
+          </plugin>
+        </plugins>
+      </build>
+    </profile>
+  </profiles>
+
+</project>

http://git-wip-us.apache.org/repos/asf/camel/blob/109da7c9/components/camel-servicenow/camel-servicenow-maven-plugin/src/it/settings.xml
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/camel-servicenow-maven-plugin/src/it/settings.xml b/components/camel-servicenow/camel-servicenow-maven-plugin/src/it/settings.xml
new file mode 100644
index 0000000..c72c23c
--- /dev/null
+++ b/components/camel-servicenow/camel-servicenow-maven-plugin/src/it/settings.xml
@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You under the Apache License, Version 2.0
+    (the "License"); you may not use this file except in compliance with
+    the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+
+-->
+<settings>
+  <profiles>
+    <profile>
+      <id>it-repo</id>
+      <activation>
+        <activeByDefault>true</activeByDefault>
+      </activation>
+      <repositories>
+        <repository>
+          <id>local.central</id>
+          <url>@localRepositoryUrl@</url>
+          <releases>
+            <enabled>true</enabled>
+          </releases>
+          <snapshots>
+            <enabled>true</enabled>
+          </snapshots>
+        </repository>
+      </repositories>
+      <pluginRepositories>
+        <pluginRepository>
+          <id>local.central</id>
+          <url>@localRepositoryUrl@</url>
+          <releases>
+            <enabled>true</enabled>
+          </releases>
+          <snapshots>
+            <enabled>true</enabled>
+          </snapshots>
+        </pluginRepository>
+      </pluginRepositories>
+    </profile>
+  </profiles>
+</settings>

http://git-wip-us.apache.org/repos/asf/camel/blob/109da7c9/components/camel-servicenow/camel-servicenow-maven-plugin/src/it/simple-it/pom.xml
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/camel-servicenow-maven-plugin/src/it/simple-it/pom.xml b/components/camel-servicenow/camel-servicenow-maven-plugin/src/it/simple-it/pom.xml
new file mode 100644
index 0000000..1d942b0
--- /dev/null
+++ b/components/camel-servicenow/camel-servicenow-maven-plugin/src/it/simple-it/pom.xml
@@ -0,0 +1,64 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You under the Apache License, Version 2.0
+    (the "License"); you may not use this file except in compliance with
+    the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+
+  <groupId>org.apache.camel</groupId>
+  <artifactId>camel-servicenow-maven-plugin-it</artifactId>
+  <version>1.0-SNAPSHOT</version>
+
+  <description>A simple IT verifying the basic use case.</description>
+
+  <properties>
+    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+  </properties>
+
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>@project.groupId@</groupId>
+        <artifactId>@project.artifactId@</artifactId>
+        <version>@project.version@</version>
+        <executions>
+          <execution>
+            <id>generate</id>
+            <goals>
+              <goal>generate</goal>
+            </goals>
+            <configuration>
+              <instanceName>${env.SERVICENOW_INSTANCE}</instanceName>
+              <userName>${env.SERVICENOW_USERNAME}</userName>
+              <userPassword>${env.SERVICENOW_PASSWORD}</userPassword>
+              <objects>incident</objects>
+              <fields>
+                <incident>sys_id</incident>
+              </fields>
+              <fieldsExcludePattern>
+                <incident>^sys_.*$</incident>
+              </fieldsExcludePattern>
+            </configuration>
+          </execution>
+        </executions>
+      </plugin>
+    </plugins>
+  </build>
+
+</project>

http://git-wip-us.apache.org/repos/asf/camel/blob/109da7c9/components/camel-servicenow/camel-servicenow-maven-plugin/src/it/simple-it/verify.groovy
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/camel-servicenow-maven-plugin/src/it/simple-it/verify.groovy b/components/camel-servicenow/camel-servicenow-maven-plugin/src/it/simple-it/verify.groovy
new file mode 100644
index 0000000..91d565d
--- /dev/null
+++ b/components/camel-servicenow/camel-servicenow-maven-plugin/src/it/simple-it/verify.groovy
@@ -0,0 +1,21 @@
+/**
+ * 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.
+ */
+
+// assert that the generated files directory exists
+File sourceDir = new File(basedir, "target/generated-sources/camel-servicenow")
+
+assert sourceDir.isDirectory()

http://git-wip-us.apache.org/repos/asf/camel/blob/109da7c9/components/camel-servicenow/camel-servicenow-maven-plugin/src/main/java/org/apache/camel/maven/CamelServiceNowGenerateMojo.java
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/camel-servicenow-maven-plugin/src/main/java/org/apache/camel/maven/CamelServiceNowGenerateMojo.java b/components/camel-servicenow/camel-servicenow-maven-plugin/src/main/java/org/apache/camel/maven/CamelServiceNowGenerateMojo.java
new file mode 100644
index 0000000..58213ad
--- /dev/null
+++ b/components/camel-servicenow/camel-servicenow-maven-plugin/src/main/java/org/apache/camel/maven/CamelServiceNowGenerateMojo.java
@@ -0,0 +1,324 @@
+/**
+ * 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.maven;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Collections;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+import javax.annotation.Generated;
+import javax.lang.model.element.Modifier;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import com.squareup.javapoet.AnnotationSpec;
+import com.squareup.javapoet.FieldSpec;
+import com.squareup.javapoet.JavaFile;
+import com.squareup.javapoet.MethodSpec;
+import com.squareup.javapoet.TypeSpec;
+import org.apache.camel.component.extension.MetaDataExtension;
+import org.apache.camel.component.servicenow.ServiceNowComponent;
+import org.apache.camel.component.servicenow.annotations.ServiceNowSysParm;
+import org.apache.camel.impl.DefaultCamelContext;
+import org.apache.camel.util.jsse.SSLContextParameters;
+import org.apache.maven.plugin.AbstractMojo;
+import org.apache.maven.plugin.MojoExecutionException;
+import org.apache.maven.plugin.MojoFailureException;
+import org.apache.maven.plugins.annotations.LifecyclePhase;
+import org.apache.maven.plugins.annotations.Mojo;
+import org.apache.maven.plugins.annotations.Parameter;
+
+/**
+ * Goal to generate DTOs for ServiceNow objects
+ */
+@Mojo(name = "generate", requiresProject = false, defaultPhase = LifecyclePhase.GENERATE_SOURCES)
+public class CamelServiceNowGenerateMojo extends AbstractMojo {
+    /**
+     * Location of generated DTO files, defaults to target/generated-sources/camel-salesforce.
+     */
+    @Parameter(
+        property = "camel.servicenow.output.directory",
+        defaultValue = "${project.build.directory}/generated-sources/camel-servicenow")
+    protected File outputDirectory;
+
+    /**
+     * Java package name for generated DTOs.
+     */
+    @Parameter(
+        property = "camel.servicenow.output.package",
+        defaultValue = "org.apache.camel.servicenow.dto")
+    protected String packageName;
+
+    /**
+     * ServiceNow instance name.
+     */
+    @Parameter(
+        property = "camel.servicenow.instance.name", required = true)
+    protected String instanceName;
+
+    /**
+     * ServiceName user name.
+     */
+    @Parameter(
+        property = "camel.servicenow.user.name", required = true)
+    protected String userName;
+
+    /**
+     * ServiceNow user password.
+     */
+    @Parameter(
+        property = "camel.servicenow.user.password", required = true)
+    protected String userPassword;
+
+    /**
+     * ServiceNow OAuth2 client id.
+     */
+    @Parameter(
+        property = "camel.servicenow.oauth2.client.id")
+    protected String oauthClientId;
+
+    /**
+     * ServiceNow OAuth2 client secret.
+     */
+    @Parameter(
+        property = "camel.servicenow.oauth2.client.secret")
+    protected String oauthClientSecret;
+
+    /**
+     * SSL Context parameters.
+     */
+    @Parameter(
+        property = "camel.servicenow.ssl.parameters")
+    protected SSLContextParameters sslParameters;
+
+    /**
+     * ServiceNow objects for which DTOs must be generated.
+     */
+    @Parameter(required = true)
+    protected List<String> objects = Collections.emptyList();
+
+    /**
+     * ServiceNow fields to include in generated DTOs.
+     */
+    @Parameter
+    protected Map<String, String> fields = Collections.emptyMap();
+
+    /**
+     * ServiceNow fields to exclude from generated DTOs, fields explicit included
+     * have the precedence.
+     */
+    @Parameter
+    protected Map<String, String> fieldsExcludePattern = Collections.emptyMap();
+
+    // ************************************
+    //
+    // ************************************
+
+    @Override
+    public void execute() throws MojoExecutionException, MojoFailureException {
+        final DefaultCamelContext context = new DefaultCamelContext();
+        final ServiceNowComponent component = new ServiceNowComponent(context);
+
+        for (String objectName : objects) {
+            Map<String, Object> parameters = new HashMap<>();
+            parameters.put("instanceName", instanceName);
+            parameters.put("userName", userName);
+            parameters.put("password", userPassword);
+            parameters.put("oauthClientId", oauthClientId);
+            parameters.put("oauthClientSecret", oauthClientSecret);
+            parameters.put("objectType", "table");
+            parameters.put("objectName", objectName);
+
+            for (Map.Entry<String, String> entry : fields.entrySet()) {
+                parameters.put("object." + entry.getKey() + ".fields", entry.getValue());
+            }
+            for (Map.Entry<String, String> entry : fieldsExcludePattern.entrySet()) {
+                parameters.put("object." + entry.getKey() + ".fields.exclude.pattern", entry.getValue());
+            }
+
+            JsonNode schema = component.getExtension(MetaDataExtension.class)
+                .flatMap(e -> e.meta(parameters))
+                .flatMap(m -> Optional.ofNullable(m.getPayload(JsonNode.class)))
+                .orElseThrow(() -> new MojoExecutionException("Unable to get grab MetaData for object: " + objectName)
+            );
+
+            validateSchema(schema);
+
+            generateBean(objectName, schema);
+        }
+    }
+
+    // ************************************
+    // Beans
+    // ************************************
+
+    private void generateBean(String name, JsonNode schema) throws MojoExecutionException {
+        try {
+            TypeSpec.Builder typeBuilder = TypeSpec.classBuilder(toCamelCase(name, false))
+                .addModifiers(Modifier.PUBLIC, Modifier.FINAL)
+                .addAnnotation(Generated.class)
+                .addAnnotation(AnnotationSpec.builder(ServiceNowSysParm.class)
+                    .addMember("name", "$S", "sysparm_exclude_reference_link")
+                    .addMember("value", "$S", "true")
+                    .build())
+                .addAnnotation(AnnotationSpec.builder(JsonIgnoreProperties.class)
+                    .addMember("ignoreUnknown", "$L", "true")
+                    .build())
+                .addAnnotation(AnnotationSpec.builder(JsonInclude.class)
+                    .addMember("value", "$L", "JsonInclude.Include.NON_NULL")
+                    .build());
+
+            schema.get("properties").fields().forEachRemaining(
+                entry -> generateBeanProperty(typeBuilder, schema, entry.getKey(), entry.getValue())
+            );
+
+            JavaFile.builder(packageName, typeBuilder.build())
+                .indent("    ")
+                .build()
+                .writeTo(outputDirectory);
+        } catch (IOException e) {
+            throw new MojoExecutionException("Unable to generate Class", e);
+        }
+    }
+
+    private void generateBeanProperty(TypeSpec.Builder typeBuilder, JsonNode schema, String name, JsonNode definition) {
+        final ArrayNode required = (ArrayNode)schema.get("required");
+        final ObjectNode definitions = (ObjectNode)schema.get("definitions");
+        final String fieldName = toCamelCase(name, true);
+        final String methodName = toCamelCase(name, false);
+
+        Class<?> javaType = String.class;
+        Optional<String> format = Optional.empty();
+
+        JsonNode type = definition.get("type");
+        if (type != null) {
+            if ("boolean".equalsIgnoreCase(type.textValue())) {
+                javaType = boolean.class;
+            }
+            if ("integer".equalsIgnoreCase(type.textValue())) {
+                javaType = Integer.class;
+            }
+            if ("number".equalsIgnoreCase(type.textValue())) {
+                javaType = Double.class;
+            }
+        }
+
+        JsonNode ref = definition.get("$ref");
+        if (ref != null) {
+            if ("#/definitions/guid".equalsIgnoreCase(ref.textValue())) {
+                javaType = String.class;
+            }
+            if ("#/definitions/date".equalsIgnoreCase(ref.textValue())) {
+                javaType = Date.class;
+                format = getNodeTextValue(definitions, "date", "format");
+            }
+            if ("#/definitions/time".equalsIgnoreCase(ref.textValue())) {
+                javaType = Date.class;
+                format = getNodeTextValue(definitions, "time", "format");
+            }
+            if ("#/definitions/date-time".equalsIgnoreCase(ref.textValue())) {
+                javaType = Date.class;
+                format = getNodeTextValue(definitions, "date-time", "format");
+            }
+        }
+
+        FieldSpec.Builder field = FieldSpec.builder(javaType, toCamelCase(name, true))
+            .addModifiers(Modifier.PRIVATE)
+            .addAnnotation(AnnotationSpec.builder(JsonProperty.class)
+                .addMember("value", "$S", name)
+                .addMember("required", "$L", required.has(name))
+                .build());
+
+        format.ifPresent(f ->
+            field.addAnnotation(AnnotationSpec.builder(JsonFormat.class)
+                .addMember("shape", "$L","JsonFormat.Shape.STRING")
+                .addMember("pattern", "$S", f)
+                .build())
+        );
+
+        MethodSpec.Builder getter = MethodSpec.methodBuilder("get" + methodName)
+            .addModifiers(Modifier.PUBLIC)
+            .returns(javaType)
+            .addStatement("return this.$L", fieldName);
+
+        MethodSpec.Builder setter = MethodSpec.methodBuilder("set" + methodName)
+            .addModifiers(Modifier.PUBLIC)
+            .returns(void.class)
+            .addParameter(javaType, fieldName)
+            .addStatement("this.$L = $L", fieldName, fieldName);
+
+        typeBuilder.addField(field.build());
+        typeBuilder.addMethod(getter.build());
+        typeBuilder.addMethod(setter.build());
+    }
+
+    // ************************************
+    // Helpers
+    // ************************************
+
+    private String toCamelCase(String text, boolean lowerCaseFirst) {
+        String result = Stream.of(text.split("[^a-zA-Z0-9]"))
+            .map(v -> v.substring(0, 1).toUpperCase() + v.substring(1).toLowerCase())
+            .collect(Collectors.joining());
+
+        if (lowerCaseFirst) {
+            result = result.substring(0, 1).toLowerCase() + result.substring(1);
+        }
+
+        return result;
+    }
+
+    private Optional<String> getNodeTextValue(JsonNode root, String... path) {
+        return getNode(root, path).map(JsonNode::asText);
+    }
+
+    private Optional<JsonNode> getNode(JsonNode root, String... path) {
+        JsonNode node = root;
+        for (String name : path) {
+            node = node.get(name);
+            if (node == null) {
+                break;
+            }
+        }
+
+        return Optional.ofNullable(node);
+    }
+
+    private void validateSchema(JsonNode schema) throws MojoExecutionException {
+        getNode(schema, "required")
+            .orElseThrow(() -> new MojoExecutionException("Invalid JsonSchema: 'required' element not found"));
+        getNode(schema, "definitions")
+            .orElseThrow(() -> new MojoExecutionException("Invalid JsonSchema: 'definitions' element not found"));
+        getNode(schema, "definitions", "date", "format")
+            .orElseThrow(() -> new MojoExecutionException("Invalid JsonSchema: '#/definitions/date' element not found"));
+        getNode(schema, "definitions", "time", "format")
+            .orElseThrow(() -> new MojoExecutionException("Invalid JsonSchema: '#/definitions/time' element not found"));
+        getNode(schema, "definitions", "date-time", "format")
+            .orElseThrow(() -> new MojoExecutionException("Invalid JsonSchema: '#/definitions/date-time' element not found"));
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/109da7c9/components/camel-servicenow/camel-servicenow-maven-plugin/src/test/java/org/apache/camel/maven/CamelServiceNowGenerateMojoTest.java
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/camel-servicenow-maven-plugin/src/test/java/org/apache/camel/maven/CamelServiceNowGenerateMojoTest.java b/components/camel-servicenow/camel-servicenow-maven-plugin/src/test/java/org/apache/camel/maven/CamelServiceNowGenerateMojoTest.java
new file mode 100644
index 0000000..ef06fcc
--- /dev/null
+++ b/components/camel-servicenow/camel-servicenow-maven-plugin/src/test/java/org/apache/camel/maven/CamelServiceNowGenerateMojoTest.java
@@ -0,0 +1,40 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.maven;
+
+import java.util.Arrays;
+
+import edu.emory.mathcs.backport.java.util.Collections;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class CamelServiceNowGenerateMojoTest extends CamelServiceNowMojoTestSupport {
+
+    @Test
+    public void testExecute() throws Exception {
+        final CamelServiceNowGenerateMojo mojo = createMojo();
+
+        mojo.objects = Arrays.asList("incident");
+        mojo.fields = Collections.singletonMap("incident", "sys_id");
+        mojo.fieldsExcludePattern = Collections.singletonMap("incident", "^sys_.*$");
+
+        mojo.execute();
+
+        Assert.assertTrue("Output directory was not created", mojo.outputDirectory.exists());
+        Assert.assertTrue("Output directory is empty", mojo.outputDirectory.list().length > 0);
+    }
+}


[17/19] camel git commit: CAMEL-11555: ServiceNow : create a maven plugin to generate models based on table layout

Posted by lb...@apache.org.
http://git-wip-us.apache.org/repos/asf/camel/blob/109da7c9/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/auth/OAuthToken.java
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/auth/OAuthToken.java b/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/auth/OAuthToken.java
new file mode 100644
index 0000000..880cf7f
--- /dev/null
+++ b/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/auth/OAuthToken.java
@@ -0,0 +1,107 @@
+/**
+ * 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.servicenow.auth;
+
+import java.util.concurrent.TimeUnit;
+
+import org.apache.camel.component.servicenow.ServiceNowConfiguration;
+import org.apache.cxf.jaxrs.client.WebClient;
+import org.apache.cxf.rs.security.oauth2.client.Consumer;
+import org.apache.cxf.rs.security.oauth2.client.OAuthClientUtils;
+import org.apache.cxf.rs.security.oauth2.common.ClientAccessToken;
+import org.apache.cxf.rs.security.oauth2.grants.owner.ResourceOwnerGrant;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class OAuthToken {
+    private static final Logger LOGGER = LoggerFactory.getLogger(OAuthToken.class);
+
+    private final ServiceNowConfiguration configuration;
+    private ClientAccessToken token;
+    private String authString;
+    private long expireAt;
+
+    public OAuthToken(ServiceNowConfiguration configuration) {
+        this.configuration = configuration;
+        this.token = null;
+        this.authString = null;
+        this.expireAt = 0;
+    }
+
+    private synchronized void getOrRefreshAccessToken() {
+        if (token == null) {
+            LOGGER.debug("Generate OAuth token");
+
+            token = OAuthClientUtils.getAccessToken(
+                WebClient.create(configuration.getOauthTokenUrl()),
+                new Consumer(
+                    configuration.getOauthClientId(),
+                    configuration.getOauthClientSecret()),
+                new ResourceOwnerGrant(
+                    configuration.getUserName(),
+                    configuration.getPassword()),
+                true
+            );
+
+            LOGGER.debug("OAuth token expires in {}s", token.getExpiresIn());
+
+            // Set expiration time related info in milliseconds
+            token.setIssuedAt(System.currentTimeMillis());
+            token.setExpiresIn(TimeUnit.MILLISECONDS.convert(token.getExpiresIn(), TimeUnit.SECONDS));
+
+            authString = token.toString();
+
+            if (token.getExpiresIn() > 0) {
+                expireAt = token.getIssuedAt() + token.getExpiresIn();
+            }
+        } else if (expireAt > 0 && System.currentTimeMillis() >= expireAt) {
+            LOGGER.debug("OAuth token is expired, refresh it");
+
+            token = OAuthClientUtils.refreshAccessToken(
+                WebClient.create(configuration.getOauthTokenUrl()),
+                new Consumer(
+                    configuration.getOauthClientId(),
+                    configuration.getOauthClientSecret()),
+                token,
+                null,
+                false
+            );
+
+            LOGGER.debug("Refreshed OAuth token expires in {}s", token.getExpiresIn());
+
+            // Set expiration time related info in milliseconds
+            token.setIssuedAt(System.currentTimeMillis());
+            token.setExpiresIn(TimeUnit.MILLISECONDS.convert(token.getExpiresIn(), TimeUnit.SECONDS));
+
+            authString = token.toString();
+
+            if (token.getExpiresIn() > 0) {
+                expireAt = token.getIssuedAt() + token.getExpiresIn();
+            }
+        }
+    }
+
+    public ClientAccessToken getClientAccess() {
+        getOrRefreshAccessToken();
+        return token;
+    }
+
+    public String getAuthString() {
+        getOrRefreshAccessToken();
+        return authString;
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/109da7c9/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/model/DictionaryEntry.java
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/model/DictionaryEntry.java b/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/model/DictionaryEntry.java
new file mode 100644
index 0000000..af7aa5b
--- /dev/null
+++ b/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/model/DictionaryEntry.java
@@ -0,0 +1,56 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.servicenow.model;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+public class DictionaryEntry {
+    private final Reference internalType;
+    private final Reference reference;
+    private final Integer maxLength;
+    private final boolean mandatory;
+
+    @JsonCreator
+    public DictionaryEntry(
+        @JsonProperty(value = "internal_type") Reference internalType,
+        @JsonProperty(value = "reference") Reference reference,
+        @JsonProperty(value = "max_length") Integer maxLength,
+        @JsonProperty(value = "mandatory", defaultValue = "false") boolean mandatory) {
+
+        this.internalType = internalType;
+        this.reference = reference;
+        this.maxLength = maxLength;
+        this.mandatory = mandatory;
+    }
+
+    public Reference getInternalType() {
+        return internalType;
+    }
+
+    public Reference getReference() {
+        return reference;
+    }
+
+    public Integer getMaxLength() {
+        return maxLength;
+    }
+
+    public boolean isMandatory() {
+        return mandatory;
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/109da7c9/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/model/ImportSetResponse.java
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/model/ImportSetResponse.java b/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/model/ImportSetResponse.java
new file mode 100644
index 0000000..348dd8d
--- /dev/null
+++ b/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/model/ImportSetResponse.java
@@ -0,0 +1,57 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.servicenow.model;
+
+import java.util.Collections;
+import java.util.List;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import org.apache.camel.component.servicenow.annotations.ServiceNowSysParm;
+
+@ServiceNowSysParm(name = "sysparm_exclude_reference_link", value = "true")
+@JsonIgnoreProperties(ignoreUnknown = true)
+@JsonInclude(JsonInclude.Include.NON_NULL)
+public class ImportSetResponse {
+    private final String importSet;
+    private final String stagingTable;
+    private final List<ImportSetResult> results;
+
+    @JsonCreator
+    public ImportSetResponse(
+        @JsonProperty("import_set") String importSet,
+        @JsonProperty("staging_table") String stagingTable,
+        @JsonProperty("result") List<ImportSetResult> results) {
+        this.importSet = importSet;
+        this.stagingTable = stagingTable;
+        this.results = results == null ? Collections.emptyList() : results;
+    }
+
+    public String getImportSet() {
+        return importSet;
+    }
+
+    public String getStagingTable() {
+        return stagingTable;
+    }
+
+    public List<ImportSetResult> getResults() {
+        return results;
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/109da7c9/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/model/ImportSetResult.java
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/model/ImportSetResult.java b/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/model/ImportSetResult.java
new file mode 100644
index 0000000..e5962e0
--- /dev/null
+++ b/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/model/ImportSetResult.java
@@ -0,0 +1,83 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.servicenow.model;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import org.apache.camel.component.servicenow.annotations.ServiceNowSysParm;
+
+@ServiceNowSysParm(name = "sysparm_exclude_reference_link", value = "true")
+@JsonIgnoreProperties(ignoreUnknown = true)
+@JsonInclude(JsonInclude.Include.NON_NULL)
+public class ImportSetResult {
+    private final String transformMap;
+    private final String table;
+    private final String displayName;
+    private final String displayValue;
+    private final String recordLink;
+    private final String status;
+    private final String sysId;
+
+    @JsonCreator
+    public ImportSetResult(
+        @JsonProperty(value = "transform_map") String transformMap,
+        @JsonProperty(value = "table", required = true) String table,
+        @JsonProperty(value = "display_name") String displayName,
+        @JsonProperty(value = "display_value") String displayValue,
+        @JsonProperty(value = "record_link") String recordLink,
+        @JsonProperty(value = "status", required = true) String status,
+        @JsonProperty(value = "sys_id", required = true) String sysId) {
+
+        this.transformMap = transformMap;
+        this.table = table;
+        this.displayName = displayName;
+        this.displayValue = displayValue;
+        this.recordLink = recordLink;
+        this.status = status;
+        this.sysId = sysId;
+    }
+
+    public String getTransformMap() {
+        return transformMap;
+    }
+
+    public String getTable() {
+        return table;
+    }
+
+    public String getDisplayName() {
+        return displayName;
+    }
+
+    public String getDisplayValue() {
+        return displayValue;
+    }
+
+    public String getRecordLink() {
+        return recordLink;
+    }
+
+    public String getStatus() {
+        return status;
+    }
+
+    public String getSysId() {
+        return sysId;
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/109da7c9/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/model/Reference.java
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/model/Reference.java b/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/model/Reference.java
new file mode 100644
index 0000000..1bcb2a7
--- /dev/null
+++ b/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/model/Reference.java
@@ -0,0 +1,56 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.servicenow.model;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+public class Reference {
+    private final String link;
+    private final String value;
+    private final String displayValue;
+
+    @JsonCreator
+    public Reference(String value) {
+        this.link = null;
+        this.value = value;
+        this.displayValue = null;
+    }
+
+    @JsonCreator
+    public Reference(
+        @JsonProperty(value = "link", required = false) String link,
+        @JsonProperty(value = "value", required = true) String value,
+        @JsonProperty(value = "display_value", required = false) String displayValue) {
+
+        this.link = link;
+        this.value = value;
+        this.displayValue = displayValue;
+    }
+
+    public String getLink() {
+        return link;
+    }
+
+    public String getValue() {
+        return value;
+    }
+
+    public String getDisplayValue() {
+        return displayValue;
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/109da7c9/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/releases/fuji/FujiServiceNowAggregateProcessor.java
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/releases/fuji/FujiServiceNowAggregateProcessor.java b/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/releases/fuji/FujiServiceNowAggregateProcessor.java
new file mode 100644
index 0000000..7fe9352
--- /dev/null
+++ b/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/releases/fuji/FujiServiceNowAggregateProcessor.java
@@ -0,0 +1,72 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.camel.component.servicenow.releases.fuji;
+
+import javax.ws.rs.HttpMethod;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+import org.apache.camel.Exchange;
+import org.apache.camel.Message;
+import org.apache.camel.component.servicenow.ServiceNowConstants;
+import org.apache.camel.component.servicenow.ServiceNowEndpoint;
+import org.apache.camel.component.servicenow.ServiceNowParams;
+import org.apache.camel.util.ObjectHelper;
+
+class FujiServiceNowAggregateProcessor extends FujiServiceNowProcessor {
+
+    FujiServiceNowAggregateProcessor(ServiceNowEndpoint endpoint) throws Exception {
+        super(endpoint);
+    }
+
+    @Override
+    protected void doProcess(Exchange exchange, Class<?> requestModel, Class<?> responseModel, String action, String apiVersion, String tableName, String sysId) throws Exception {
+        Response response;
+        if (ObjectHelper.equal(ServiceNowConstants.ACTION_RETRIEVE, action, true)) {
+            response = retrieveStats(exchange.getIn(), requestModel, responseModel, tableName);
+        } else {
+            throw new IllegalArgumentException("Unknown action " + action);
+        }
+
+        setBodyAndHeaders(exchange.getIn(), responseModel, response);
+    }
+
+    private Response retrieveStats(Message in, Class<?> requestModel, Class<?> responseModel, String tableName) throws Exception {
+        final String apiVersion = getApiVersion(in);
+
+        return client.reset()
+            .types(MediaType.APPLICATION_JSON_TYPE)
+            .path("now")
+            .path(apiVersion)
+            .path("stats")
+            .path(tableName)
+            .query(ServiceNowParams.SYSPARM_QUERY, in)
+            .query(ServiceNowParams.SYSPARM_AVG_FIELDS, in)
+            .query(ServiceNowParams.SYSPARM_COUNT, in)
+            .query(ServiceNowParams.SYSPARM_MIN_FIELDS, in)
+            .query(ServiceNowParams.SYSPARM_QUERY, in)
+            .query(ServiceNowParams.SYSPARM_MAX_FIELDS, in)
+            .query(ServiceNowParams.SYSPARM_SUM_FIELDS, in)
+            .query(ServiceNowParams.SYSPARM_GROUP_BY, in)
+            .query(ServiceNowParams.SYSPARM_ORDER_BY, in)
+            .query(ServiceNowParams.SYSPARM_HAVING, in)
+            .query(ServiceNowParams.SYSPARM_DISPLAY_VALUE, in)
+            .query(responseModel)
+            .invoke(HttpMethod.GET);
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/109da7c9/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/releases/fuji/FujiServiceNowImportSetProcessor.java
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/releases/fuji/FujiServiceNowImportSetProcessor.java b/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/releases/fuji/FujiServiceNowImportSetProcessor.java
new file mode 100644
index 0000000..2080045
--- /dev/null
+++ b/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/releases/fuji/FujiServiceNowImportSetProcessor.java
@@ -0,0 +1,86 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.camel.component.servicenow.releases.fuji;
+
+import javax.ws.rs.HttpMethod;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+import org.apache.camel.Exchange;
+import org.apache.camel.Message;
+import org.apache.camel.component.servicenow.ServiceNowConstants;
+import org.apache.camel.component.servicenow.ServiceNowEndpoint;
+import org.apache.camel.util.ObjectHelper;
+
+class FujiServiceNowImportSetProcessor extends FujiServiceNowProcessor {
+
+    FujiServiceNowImportSetProcessor(ServiceNowEndpoint endpoint) throws Exception {
+        super(endpoint);
+    }
+
+    @Override
+    protected void doProcess(Exchange exchange, Class<?> requestModel, Class<?> responseModel, String action, String apiVersion, String tableName, String sysId) throws Exception {
+        Response response;
+        if (ObjectHelper.equal(ServiceNowConstants.ACTION_RETRIEVE, action, true)) {
+            response = retrieveRecord(exchange.getIn(), requestModel, responseModel, apiVersion, tableName, sysId);
+        } else if (ObjectHelper.equal(ServiceNowConstants.ACTION_CREATE, action, true)) {
+            response = createRecord(exchange.getIn(), requestModel, responseModel, apiVersion, tableName);
+        } else {
+            throw new IllegalArgumentException("Unknown action " + action);
+        }
+
+        setBodyAndHeaders(exchange.getIn(), responseModel, response);
+    }
+
+    /*
+     * GET
+     * https://instance.service-now.com/api/now/import/{tableName}/{sys_id}
+     */
+    private Response retrieveRecord(Message in, Class<?> requestModel, Class<?> responseModel, String apiVersion, String tableName, String sysId) throws Exception {
+        return client.reset()
+            .types(MediaType.APPLICATION_JSON_TYPE)
+            .path("now")
+            .path(apiVersion)
+            .path("import")
+            .path(tableName)
+            .path(ObjectHelper.notNull(sysId, "sysId"))
+            .query(responseModel)
+            .invoke(HttpMethod.GET);
+    }
+
+    /*
+     * POST
+     * https://instance.service-now.com/api/now/import/{tableName}
+     */
+    private Response createRecord(Message in, Class<?> requestModel, Class<?> responseModel, String apiVersion, String tableName) throws Exception {
+        if (in.getHeader(ServiceNowConstants.RETRIEVE_TARGET_RECORD, config::getRetrieveTargetRecordOnImport, Boolean.class)) {
+            throw new UnsupportedOperationException("RetrieveTargetRecordOnImport is supported from Helsinky");
+        }
+
+        validateBody(in, requestModel);
+
+        return client.reset()
+            .types(MediaType.APPLICATION_JSON_TYPE)
+            .path("now")
+            .path(apiVersion)
+            .path("import")
+            .path(tableName)
+            .query(responseModel)
+            .invoke(HttpMethod.POST, in.getMandatoryBody());
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/109da7c9/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/releases/fuji/FujiServiceNowProcessor.java
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/releases/fuji/FujiServiceNowProcessor.java b/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/releases/fuji/FujiServiceNowProcessor.java
new file mode 100644
index 0000000..52b81bb
--- /dev/null
+++ b/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/releases/fuji/FujiServiceNowProcessor.java
@@ -0,0 +1,60 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.camel.component.servicenow.releases.fuji;
+
+import org.apache.camel.Exchange;
+import org.apache.camel.Message;
+import org.apache.camel.component.servicenow.AbstractServiceNowProcessor;
+import org.apache.camel.component.servicenow.ServiceNowConstants;
+import org.apache.camel.component.servicenow.ServiceNowEndpoint;
+import org.apache.camel.util.ObjectHelper;
+
+public abstract class FujiServiceNowProcessor extends AbstractServiceNowProcessor {
+    protected FujiServiceNowProcessor(ServiceNowEndpoint endpoint) throws Exception {
+        super(endpoint);
+    }
+
+    @Override
+    public void process(Exchange exchange) throws Exception {
+        final Message in = exchange.getIn();
+        final String tableName = getTableName(in);
+        final Class<?> requestModel = getRequestModel(in, tableName);
+        final Class<?> responseModel = getResponseModel(in, tableName);
+        final String apiVersion = getApiVersion(in);
+        final String action = in.getHeader(ServiceNowConstants.ACTION, String.class);
+        final String sysId = getSysID(in);
+
+        doProcess(
+            exchange,
+            ObjectHelper.notNull(requestModel, "requestModel"),
+            ObjectHelper.notNull(responseModel, "responseModel"),
+            apiVersion,
+            ObjectHelper.notNull(action, "action"),
+            ObjectHelper.notNull(tableName, "tableName"),
+            sysId);
+    }
+
+    protected abstract void doProcess(
+        Exchange exchange,
+        Class<?> requestModel,
+        Class<?> responseModel,
+        String apiVersion,
+        String action,
+        String tableName,
+        String sysId) throws Exception;
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/109da7c9/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/releases/fuji/FujiServiceNowProducer.java
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/releases/fuji/FujiServiceNowProducer.java b/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/releases/fuji/FujiServiceNowProducer.java
new file mode 100644
index 0000000..3d2f6cc
--- /dev/null
+++ b/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/releases/fuji/FujiServiceNowProducer.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.component.servicenow.releases.fuji;
+
+import org.apache.camel.component.servicenow.AbstractServiceNowProducer;
+import org.apache.camel.component.servicenow.ServiceNowConstants;
+import org.apache.camel.component.servicenow.ServiceNowEndpoint;
+import org.apache.camel.component.servicenow.ServiceNowRelease;
+
+/**
+ * The Fuji ServiceNow producer.
+ */
+public class FujiServiceNowProducer extends AbstractServiceNowProducer {
+    public FujiServiceNowProducer(ServiceNowEndpoint endpoint) throws Exception {
+        super(endpoint, ServiceNowRelease.FUJI);
+
+        bind(ServiceNowConstants.RESOURCE_TABLE, new FujiServiceNowTableProcessor(endpoint));
+        bind(ServiceNowConstants.RESOURCE_AGGREGATE, new FujiServiceNowAggregateProcessor(endpoint));
+        bind(ServiceNowConstants.RESOURCE_IMPORT, new FujiServiceNowImportSetProcessor(endpoint));
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/109da7c9/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/releases/fuji/FujiServiceNowTableProcessor.java
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/releases/fuji/FujiServiceNowTableProcessor.java b/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/releases/fuji/FujiServiceNowTableProcessor.java
new file mode 100644
index 0000000..0781811
--- /dev/null
+++ b/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/releases/fuji/FujiServiceNowTableProcessor.java
@@ -0,0 +1,175 @@
+/**
+ * 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.servicenow.releases.fuji;
+
+import javax.ws.rs.HttpMethod;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+import org.apache.camel.Exchange;
+import org.apache.camel.Message;
+import org.apache.camel.component.servicenow.ServiceNowConstants;
+import org.apache.camel.component.servicenow.ServiceNowEndpoint;
+import org.apache.camel.component.servicenow.ServiceNowParams;
+import org.apache.camel.util.ObjectHelper;
+
+class FujiServiceNowTableProcessor extends FujiServiceNowProcessor {
+    FujiServiceNowTableProcessor(ServiceNowEndpoint endpoint) throws Exception {
+        super(endpoint);
+    }
+
+    @Override
+    protected void doProcess(Exchange exchange, Class<?> requestModel, Class<?> responseModel, String apiVersion, String action, String tableName, String sysId) throws Exception {
+        Response response;
+        if (ObjectHelper.equal(ServiceNowConstants.ACTION_RETRIEVE, action, true)) {
+            response = retrieveRecord(exchange.getIn(), requestModel, responseModel, apiVersion, tableName, sysId);
+        } else if (ObjectHelper.equal(ServiceNowConstants.ACTION_CREATE, action, true)) {
+            response = createRecord(exchange.getIn(), requestModel, responseModel, apiVersion, tableName);
+        } else if (ObjectHelper.equal(ServiceNowConstants.ACTION_MODIFY, action, true)) {
+            response = modifyRecord(exchange.getIn(), requestModel, responseModel, apiVersion, tableName, sysId);
+        } else if (ObjectHelper.equal(ServiceNowConstants.ACTION_DELETE, action, true)) {
+            response = deleteRecord(exchange.getIn(), requestModel, responseModel, apiVersion, tableName, sysId);
+        } else if (ObjectHelper.equal(ServiceNowConstants.ACTION_UPDATE, action, true)) {
+            response = updateRecord(exchange.getIn(), requestModel, responseModel, apiVersion, tableName, sysId);
+        } else {
+            throw new IllegalArgumentException("Unknown action " + action);
+        }
+
+        setBodyAndHeaders(exchange.getIn(), responseModel, response);
+    }
+
+    /*
+     * GET
+     * https://instance.service-now.com/api/now/table/{tableName}
+     * https://instance.service-now.com/api/now/table/{tableName}/{sys_id}
+     */
+    private Response retrieveRecord(Message in, Class<?> requestModel, Class<?> responseModel, String apiVersion, String tableName, String sysId) throws Exception {
+        return ObjectHelper.isEmpty(sysId)
+            ? client.reset()
+                .types(MediaType.APPLICATION_JSON_TYPE)
+                .path("now")
+                .path(apiVersion)
+                .path("table")
+                .path(tableName)
+                .query(ServiceNowParams.SYSPARM_QUERY, in)
+                .query(ServiceNowParams.SYSPARM_DISPLAY_VALUE, in)
+                .query(ServiceNowParams.SYSPARM_EXCLUDE_REFERENCE_LINK, in)
+                .query(ServiceNowParams.SYSPARM_FIELDS, in)
+                .query(ServiceNowParams.SYSPARM_LIMIT, in)
+                .query(ServiceNowParams.SYSPARM_VIEW, in)
+                .query(responseModel)
+                .invoke(HttpMethod.GET)
+            : client.reset()
+                .types(MediaType.APPLICATION_JSON_TYPE)
+                .path("now")
+                .path(apiVersion)
+                .path("table")
+                .path(tableName)
+                .path(sysId)
+                .query(ServiceNowParams.SYSPARM_DISPLAY_VALUE, in)
+                .query(ServiceNowParams.SYSPARM_EXCLUDE_REFERENCE_LINK, in)
+                .query(ServiceNowParams.SYSPARM_FIELDS, in)
+                .query(ServiceNowParams.SYSPARM_VIEW, in)
+                .query(responseModel)
+                .invoke(HttpMethod.GET);
+    }
+
+    /*
+     * POST
+     * https://instance.service-now.com/api/now/table/{tableName}
+     */
+    private Response createRecord(Message in, Class<?> requestModel, Class<?> responseModel, String apiVersion, String tableName) throws Exception {
+        validateBody(in, requestModel);
+        return client.reset()
+            .types(MediaType.APPLICATION_JSON_TYPE)
+            .path("now")
+            .path(apiVersion)
+            .path("table")
+            .path(tableName)
+            .query(ServiceNowParams.SYSPARM_DISPLAY_VALUE, in)
+            .query(ServiceNowParams.SYSPARM_EXCLUDE_REFERENCE_LINK, in)
+            .query(ServiceNowParams.SYSPARM_FIELDS, in)
+            .query(ServiceNowParams.SYSPARM_INPUT_DISPLAY_VALUE, in)
+            .query(ServiceNowParams.SYSPARM_SUPPRESS_AUTO_SYS_FIELD, in)
+            .query(ServiceNowParams.SYSPARM_VIEW, in)
+            .query(responseModel)
+            .invoke(HttpMethod.POST, in.getMandatoryBody());
+    }
+
+    /*
+     * PUT
+     * https://instance.service-now.com/api/now/table/{tableName}/{sys_id}
+     */
+    private Response modifyRecord(Message in, Class<?> requestModel, Class<?> responseModel, String apiVersion, String tableName, String sysId) throws Exception {
+        validateBody(in, requestModel);
+        return client.reset()
+            .types(MediaType.APPLICATION_JSON_TYPE)
+            .path("now")
+            .path(apiVersion)
+            .path("table")
+            .path(tableName)
+            .path(ObjectHelper.notNull(sysId, "sysId"))
+            .query(ServiceNowParams.SYSPARM_DISPLAY_VALUE, in)
+            .query(ServiceNowParams.SYSPARM_EXCLUDE_REFERENCE_LINK, in)
+            .query(ServiceNowParams.SYSPARM_FIELDS, in)
+            .query(ServiceNowParams.SYSPARM_INPUT_DISPLAY_VALUE, in)
+            .query(ServiceNowParams.SYSPARM_SUPPRESS_AUTO_SYS_FIELD, in)
+            .query(ServiceNowParams.SYSPARM_VIEW, in)
+            .query(responseModel)
+            .invoke(HttpMethod.PUT, in.getMandatoryBody());
+    }
+
+    /*
+     * DELETE
+     * https://instance.service-now.com/api/now/table/{tableName}/{sys_id}
+     */
+    private Response deleteRecord(Message in, Class<?> requestModel, Class<?> responseModel, String apiVersion, String tableName, String sysId) throws Exception {
+        return client.reset()
+            .types(MediaType.APPLICATION_JSON_TYPE)
+            .path("now")
+            .path(apiVersion)
+            .path("table")
+            .path(tableName)
+            .path(ObjectHelper.notNull(sysId, "sysId"))
+            .query(responseModel)
+            .invoke(HttpMethod.DELETE);
+    }
+
+    /*
+     * PATCH
+     * http://instance.service-now.com/api/now/table/{tableName}/{sys_id}
+     */
+    private Response updateRecord(Message in, Class<?> requestModel, Class<?> responseModel, String apiVersion, String tableName, String sysId) throws Exception {
+        validateBody(in, requestModel);
+        return client.reset()
+            .types(MediaType.APPLICATION_JSON_TYPE)
+            .path("now")
+            .path(apiVersion)
+            .path("table")
+            .path(tableName)
+            .path(ObjectHelper.notNull(sysId, "sysId"))
+            .query(ServiceNowParams.SYSPARM_DISPLAY_VALUE, in)
+            .query(ServiceNowParams.SYSPARM_EXCLUDE_REFERENCE_LINK, in)
+            .query(ServiceNowParams.SYSPARM_FIELDS, in)
+            .query(ServiceNowParams.SYSPARM_INPUT_DISPLAY_VALUE, in)
+            .query(ServiceNowParams.SYSPARM_SUPPRESS_AUTO_SYS_FIELD, in)
+            .query(ServiceNowParams.SYSPARM_VIEW, in)
+            .query(responseModel)
+            .invoke("PATCH", in.getMandatoryBody());
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/109da7c9/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/releases/helsinki/HelsinkiServiceNowAggregateProcessor.java
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/releases/helsinki/HelsinkiServiceNowAggregateProcessor.java b/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/releases/helsinki/HelsinkiServiceNowAggregateProcessor.java
new file mode 100644
index 0000000..d895718
--- /dev/null
+++ b/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/releases/helsinki/HelsinkiServiceNowAggregateProcessor.java
@@ -0,0 +1,77 @@
+/**
+ * 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.servicenow.releases.helsinki;
+
+import javax.ws.rs.HttpMethod;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+import org.apache.camel.Exchange;
+import org.apache.camel.Message;
+import org.apache.camel.component.servicenow.AbstractServiceNowProcessor;
+import org.apache.camel.component.servicenow.ServiceNowEndpoint;
+import org.apache.camel.component.servicenow.ServiceNowParams;
+
+import static org.apache.camel.component.servicenow.ServiceNowConstants.ACTION_RETRIEVE;
+
+class HelsinkiServiceNowAggregateProcessor extends AbstractServiceNowProcessor {
+
+    HelsinkiServiceNowAggregateProcessor(ServiceNowEndpoint endpoint) throws Exception {
+        super(endpoint);
+
+        addDispatcher(ACTION_RETRIEVE, this::retrieveStats);
+    }
+
+    /*
+     * This method retrieves records for the specified table and performs aggregate
+     * functions on the returned values.
+     *
+     * Method:
+     * - GET
+     *
+     * URL Format:
+     * - /api/now/api/stats/{tableName}
+     */
+    private void retrieveStats(Exchange exchange) throws Exception {
+        final Message in = exchange.getIn();
+        final String tableName = getTableName(in);
+        final String apiVersion = getApiVersion(in);
+        final Class<?> responseModel = getResponseModel(in, tableName);
+
+        Response response = client.reset()
+            .types(MediaType.APPLICATION_JSON_TYPE)
+            .path("now")
+            .path(apiVersion)
+            .path("stats")
+            .path(tableName)
+            .query(ServiceNowParams.SYSPARM_QUERY, in)
+            .query(ServiceNowParams.SYSPARM_AVG_FIELDS, in)
+            .query(ServiceNowParams.SYSPARM_COUNT, in)
+            .query(ServiceNowParams.SYSPARM_MIN_FIELDS, in)
+            .query(ServiceNowParams.SYSPARM_QUERY, in)
+            .query(ServiceNowParams.SYSPARM_MAX_FIELDS, in)
+            .query(ServiceNowParams.SYSPARM_SUM_FIELDS, in)
+            .query(ServiceNowParams.SYSPARM_GROUP_BY, in)
+            .query(ServiceNowParams.SYSPARM_ORDER_BY, in)
+            .query(ServiceNowParams.SYSPARM_HAVING, in)
+            .query(ServiceNowParams.SYSPARM_DISPLAY_VALUE, in)
+            .query(responseModel)
+            .invoke(HttpMethod.GET);
+
+        setBodyAndHeaders(in, responseModel, response);
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/109da7c9/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/releases/helsinki/HelsinkiServiceNowAttachmentProcessor.java
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/releases/helsinki/HelsinkiServiceNowAttachmentProcessor.java b/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/releases/helsinki/HelsinkiServiceNowAttachmentProcessor.java
new file mode 100644
index 0000000..b25bcc0
--- /dev/null
+++ b/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/releases/helsinki/HelsinkiServiceNowAttachmentProcessor.java
@@ -0,0 +1,179 @@
+/**
+ * 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.servicenow.releases.helsinki;
+
+import java.io.InputStream;
+import javax.ws.rs.HttpMethod;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+import org.apache.camel.Exchange;
+import org.apache.camel.Message;
+import org.apache.camel.component.servicenow.AbstractServiceNowProcessor;
+import org.apache.camel.component.servicenow.ServiceNowConstants;
+import org.apache.camel.component.servicenow.ServiceNowEndpoint;
+import org.apache.camel.component.servicenow.ServiceNowParams;
+import org.apache.camel.util.ObjectHelper;
+
+import static org.apache.camel.component.servicenow.ServiceNowConstants.ACTION_CONTENT;
+import static org.apache.camel.component.servicenow.ServiceNowConstants.ACTION_DELETE;
+import static org.apache.camel.component.servicenow.ServiceNowConstants.ACTION_RETRIEVE;
+import static org.apache.camel.component.servicenow.ServiceNowConstants.ACTION_UPLOAD;
+
+public class HelsinkiServiceNowAttachmentProcessor extends AbstractServiceNowProcessor {
+    protected HelsinkiServiceNowAttachmentProcessor(ServiceNowEndpoint endpoint) throws Exception {
+        super(endpoint);
+
+        addDispatcher(ACTION_RETRIEVE, this::retrieveMeta);
+        addDispatcher(ACTION_CONTENT, this::retrieveContent);
+        addDispatcher(ACTION_UPLOAD, this::uploadContent);
+        addDispatcher(ACTION_DELETE, this::deleteContent);
+    }
+
+    /*
+     * This method gets the metadata for multiple attachments or for a specific
+     * attachment with a specific sys_id value
+     *
+     * Method:
+     * - GET
+     *
+     * URL Format:
+     * - /api/now/api/now/attachment
+     * - /api/now/api/now/attachment/{sys_id}
+     */
+    private void retrieveMeta(Exchange exchange) throws Exception {
+        final Message in = exchange.getIn();
+        final String tableName = getTableName(in);
+        final String apiVersion = getApiVersion(in);
+        final Class<?> responseModel = getResponseModel(in, tableName);
+        final String sysId = getSysID(in);
+
+        Response response = ObjectHelper.isEmpty(sysId)
+            ? client.reset()
+                .types(MediaType.APPLICATION_JSON_TYPE)
+                .path("now")
+                .path(apiVersion)
+                .path("attachment")
+                .query(ServiceNowParams.SYSPARM_QUERY, in)
+                .query(ServiceNowParams.SYSPARM_LIMIT, in)
+                .query(ServiceNowParams.SYSPARM_OFFSET, in)
+                .query(ServiceNowParams.SYSPARM_SUPPRESS_PAGINATION_HEADER, in)
+                .invoke(HttpMethod.GET)
+            : client.reset()
+                .types(MediaType.APPLICATION_JSON_TYPE)
+                .path("now")
+                .path(apiVersion)
+                .path("attachment")
+                .path(ObjectHelper.notNull(sysId, "sysId"))
+                .invoke(HttpMethod.GET);
+
+        setBodyAndHeaders(in, responseModel, response);
+    }
+
+    /*
+     * This method gets the binary file attachment with a specific sys_id value.
+     *
+     * Method:
+     * - GET
+     *
+     * URL Format:
+     * - /api/now/attachment/{sys_id}/file
+     */
+    private void retrieveContent(Exchange exchange) throws Exception {
+        final Message in = exchange.getIn();
+        final String apiVersion = getApiVersion(in);
+        final String sysId = getSysID(in);
+
+        Response response = client.reset()
+            .type(MediaType.APPLICATION_JSON_TYPE)
+            .accept("*/*")
+            .path("now")
+            .path(apiVersion)
+            .path("attachment")
+            .path(ObjectHelper.notNull(sysId, "sysId"))
+            .path("file")
+            .invoke(HttpMethod.GET);
+
+        // Header
+        setHeaders(in, null, response);
+
+        in.setBody(response.readEntity(InputStream.class));
+    }
+
+    /*
+     * This method uploads a binary file specified in the request body as an attachment.
+     *
+     * Method:
+     * - POST
+     *
+     * URL Format:
+     * - /api/now/api/now/attachment/file
+     */
+    private void uploadContent(Exchange exchange) throws Exception {
+        final Message in = exchange.getIn();
+        final String tableName = getTableName(in);
+        final String apiVersion = getApiVersion(in);
+        final Class<?> responseModel = getResponseModel(in, tableName);
+
+        Response response = client.reset()
+            .type(ObjectHelper.notNull(
+                in.getHeader(ServiceNowConstants.CONTENT_TYPE, String.class),
+                ServiceNowConstants.CONTENT_TYPE))
+            .accept(MediaType.APPLICATION_JSON_TYPE)
+            .path("now")
+            .path(apiVersion)
+            .path("attachment")
+            .path("file")
+            .query(ServiceNowParams.PARAM_FILE_NAME, in)
+            .query(ServiceNowParams.PARAM_TABLE_NAME, in)
+            .query(ServiceNowParams.PARAM_TABLE_SYS_ID, in)
+            .query(ServiceNowParams.PARAM_ENCRYPTION_CONTEXT, in)
+            .query(responseModel)
+            .invoke(HttpMethod.POST, in.getMandatoryBody(InputStream.class));
+
+        setBodyAndHeaders(in, responseModel, response);
+    }
+
+    /*
+     * This method deletes the attachment with a specific sys_id value.
+     *
+     * Method:
+     * - DELETE
+     *
+     * URL Format:
+     * - /api/now/attachment/{sys_id}
+     */
+    private void deleteContent(Exchange exchange) throws Exception {
+        final Message in = exchange.getIn();
+        final String tableName = getTableName(in);
+        final String apiVersion = getApiVersion(in);
+        final Class<?> responseModel = getResponseModel(in, tableName);
+        final String sysId = getSysID(in);
+
+        Response response = client.reset()
+            .types(MediaType.APPLICATION_JSON_TYPE)
+            .path("now")
+            .path(apiVersion)
+            .path("attachment")
+            .path(ObjectHelper.notNull(sysId, "sysId"))
+            .query(responseModel)
+            .invoke(HttpMethod.DELETE);
+
+        setBodyAndHeaders(in, responseModel, response);
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/109da7c9/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/releases/helsinki/HelsinkiServiceNowImportSetProcessor.java
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/releases/helsinki/HelsinkiServiceNowImportSetProcessor.java b/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/releases/helsinki/HelsinkiServiceNowImportSetProcessor.java
new file mode 100644
index 0000000..feb5d47
--- /dev/null
+++ b/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/releases/helsinki/HelsinkiServiceNowImportSetProcessor.java
@@ -0,0 +1,143 @@
+/**
+ * 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.servicenow.releases.helsinki;
+
+import javax.ws.rs.HttpMethod;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+import org.apache.camel.Exchange;
+import org.apache.camel.Message;
+import org.apache.camel.component.servicenow.AbstractServiceNowProcessor;
+import org.apache.camel.component.servicenow.ServiceNowConstants;
+import org.apache.camel.component.servicenow.ServiceNowEndpoint;
+import org.apache.camel.component.servicenow.ServiceNowParams;
+import org.apache.camel.component.servicenow.model.ImportSetResponse;
+import org.apache.camel.component.servicenow.model.ImportSetResult;
+import org.apache.camel.util.ObjectHelper;
+
+import static org.apache.camel.component.servicenow.ServiceNowConstants.ACTION_CREATE;
+import static org.apache.camel.component.servicenow.ServiceNowConstants.ACTION_RETRIEVE;
+
+class HelsinkiServiceNowImportSetProcessor extends AbstractServiceNowProcessor {
+
+    HelsinkiServiceNowImportSetProcessor(ServiceNowEndpoint endpoint) throws Exception {
+        super(endpoint);
+
+        addDispatcher(ACTION_RETRIEVE, this::retrieveRecord);
+        addDispatcher(ACTION_CREATE, this::createRecord);
+    }
+
+    /*
+     * GET
+     * https://instance.service-now.com/api/now/import/{tableName}/{sys_id}
+     */
+    private void retrieveRecord(Exchange exchange) throws Exception {
+        final Message in = exchange.getIn();
+        final String tableName = getTableName(in);
+        final String apiVersion = getApiVersion(in);
+        final Class<?> responseModel = getResponseModel(in, tableName);
+        final String sysId = getSysID(in);
+
+        Response response = client.reset()
+            .types(MediaType.APPLICATION_JSON_TYPE)
+            .path("now")
+            .path(apiVersion)
+            .path("import")
+            .path(ObjectHelper.notNull(tableName, "tableName"))
+            .path(ObjectHelper.notNull(sysId, "sysId"))
+            .query(responseModel)
+            .invoke(HttpMethod.GET);
+
+        setBodyAndHeaders(in, responseModel, response);
+    }
+
+    /*
+     * POST
+     * https://instance.service-now.com/api/now/import/{tableName}
+     */
+    private void createRecord(Exchange exchange) throws Exception {
+        final Message in = exchange.getIn();
+        final String tableName = getTableName(in);
+        final String apiVersion = getApiVersion(in);
+        final Class<?> requestModel = getRequestModel(in, tableName);
+        final boolean retrieve = in.getHeader(ServiceNowConstants.RETRIEVE_TARGET_RECORD, config::getRetrieveTargetRecordOnImport, Boolean.class);
+
+        Class<?> responseModel = getResponseModel(in, tableName);
+        Response response;
+
+        validateBody(in, requestModel);
+
+        if (retrieve) {
+            // If the endpoint is configured to retrieve the target record, the
+            // import response model is ignored and the response is ImportSetResponse
+
+            response = client.reset()
+                .types(MediaType.APPLICATION_JSON_TYPE)
+                .path("now")
+                .path(apiVersion)
+                .path("import")
+                .path(tableName)
+                .invoke(HttpMethod.POST, in.getMandatoryBody());
+
+            if (ObjectHelper.isNotEmpty(response.getHeaderString(HttpHeaders.CONTENT_TYPE))) {
+                for (ImportSetResult result : response.readEntity(ImportSetResponse.class).getResults()) {
+                    final String status = result.getStatus();
+                    final String table = result.getTable();
+                    final String sysId = result.getSysId();
+
+                    if (ObjectHelper.equalIgnoreCase("inserted", status)) {
+
+                        // If the endpoint is configured to retrieve the target
+                        // record, the response model is related to the target
+                        // table
+                        responseModel = getResponseModel(in, table);
+
+                        // Do get the record
+                        response = client.reset()
+                            .types(MediaType.APPLICATION_JSON_TYPE)
+                            .path("now")
+                            .path(apiVersion)
+                            .path("table")
+                            .path(ObjectHelper.notNull(table, "table"))
+                            .path(ObjectHelper.notNull(sysId, "sys_id"))
+                            .query(ServiceNowParams.SYSPARM_DISPLAY_VALUE, in)
+                            .query(ServiceNowParams.SYSPARM_EXCLUDE_REFERENCE_LINK, in)
+                            .query(ServiceNowParams.SYSPARM_FIELDS, in)
+                            .query(ServiceNowParams.SYSPARM_VIEW, in)
+                            .query(responseModel)
+                            .invoke(HttpMethod.GET);
+
+                        break;
+                    }
+                }
+            }
+        } else {
+            response = client.reset()
+                .types(MediaType.APPLICATION_JSON_TYPE)
+                .path("now")
+                .path(apiVersion)
+                .path("import")
+                .path(tableName)
+                .query(responseModel)
+                .invoke(HttpMethod.POST, in.getMandatoryBody());
+        }
+
+        setBodyAndHeaders(in, responseModel, response);
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/109da7c9/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/releases/helsinki/HelsinkiServiceNowMiscProcessor.java
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/releases/helsinki/HelsinkiServiceNowMiscProcessor.java b/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/releases/helsinki/HelsinkiServiceNowMiscProcessor.java
new file mode 100644
index 0000000..c4e9d1b
--- /dev/null
+++ b/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/releases/helsinki/HelsinkiServiceNowMiscProcessor.java
@@ -0,0 +1,94 @@
+/**
+ * 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.servicenow.releases.helsinki;
+
+import javax.ws.rs.HttpMethod;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+import org.apache.camel.Exchange;
+import org.apache.camel.Message;
+import org.apache.camel.component.servicenow.AbstractServiceNowProcessor;
+import org.apache.camel.component.servicenow.ServiceNowEndpoint;
+import org.apache.camel.component.servicenow.ServiceNowParams;
+
+import static org.apache.camel.component.servicenow.ServiceNowConstants.ACTION_CREATE;
+import static org.apache.camel.component.servicenow.ServiceNowConstants.ACTION_RETRIEVE;
+import static org.apache.camel.component.servicenow.ServiceNowConstants.ACTION_SUBJECT_IDENTIFY_RECONCILE;
+import static org.apache.camel.component.servicenow.ServiceNowConstants.ACTION_SUBJECT_USER_ROLE_INHERITANCE;
+
+class HelsinkiServiceNowMiscProcessor extends AbstractServiceNowProcessor {
+
+    HelsinkiServiceNowMiscProcessor(ServiceNowEndpoint endpoint) throws Exception {
+        super(endpoint);
+
+        addDispatcher(ACTION_RETRIEVE, ACTION_SUBJECT_USER_ROLE_INHERITANCE, this::retrieveUserRoleInheritance);
+        addDispatcher(ACTION_CREATE, ACTION_SUBJECT_IDENTIFY_RECONCILE, this::uploadIdentifyReconcile);
+    }
+
+    /*
+     * This method retrieves the roles the user has an determine what was inherited.
+     *
+     * Method:
+     * - GET
+     *
+     * URL Format:
+     * - /api/global/user_role_inheritance
+     */
+    private void retrieveUserRoleInheritance(Exchange exchange) throws Exception {
+        final Message in = exchange.getIn();
+        final Class<?> responseModel = getResponseModel(in);
+        final String apiVersion = getApiVersion(in);
+
+        Response response = client.reset()
+            .types(MediaType.APPLICATION_JSON_TYPE)
+            .path("global")
+            .path("user_role_inheritance")
+            .query(ServiceNowParams.PARAM_USER_SYS_ID, in)
+            .query(responseModel)
+            .invoke(HttpMethod.GET);
+
+        setBodyAndHeaders(in, responseModel, response);
+    }
+
+    /*
+     * This method retrieves the roles the user has an determine what was inherited.
+     *
+     * Method:
+     * - POST
+     *
+     * URL Format:
+     * - /api/now/identifyreconcile
+     */
+    private void uploadIdentifyReconcile(Exchange exchange) throws Exception {
+        final Message in = exchange.getIn();
+        final Class<?> responseModel = getResponseModel(in);
+        final String apiVersion = getApiVersion(in);
+
+        Response response = client.reset()
+            .types(MediaType.APPLICATION_JSON_TYPE)
+            .path("now")
+            .path(apiVersion)
+            .path("identifyreconcile")
+            .query(ServiceNowParams.SYSPARM_DATA_SOURCE, in)
+            .query(responseModel)
+            .invoke(HttpMethod.POST, in.getMandatoryBody());
+
+        setBodyAndHeaders(in, responseModel, response);
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/109da7c9/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/releases/helsinki/HelsinkiServiceNowProducer.java
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/releases/helsinki/HelsinkiServiceNowProducer.java b/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/releases/helsinki/HelsinkiServiceNowProducer.java
new file mode 100644
index 0000000..69a86af
--- /dev/null
+++ b/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/releases/helsinki/HelsinkiServiceNowProducer.java
@@ -0,0 +1,42 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.servicenow.releases.helsinki;
+
+import org.apache.camel.component.servicenow.AbstractServiceNowProducer;
+import org.apache.camel.component.servicenow.ServiceNowConstants;
+import org.apache.camel.component.servicenow.ServiceNowEndpoint;
+import org.apache.camel.component.servicenow.ServiceNowRelease;
+
+/**
+ * The Helsinki ServiceNow producer.
+ */
+public class HelsinkiServiceNowProducer extends AbstractServiceNowProducer {
+    public HelsinkiServiceNowProducer(ServiceNowEndpoint endpoint) throws Exception {
+        super(endpoint, ServiceNowRelease.HELSINKI);
+
+        bind(ServiceNowConstants.RESOURCE_TABLE, new HelsinkiServiceNowTableProcessor(endpoint));
+        bind(ServiceNowConstants.RESOURCE_AGGREGATE, new HelsinkiServiceNowAggregateProcessor(endpoint));
+        bind(ServiceNowConstants.RESOURCE_IMPORT, new HelsinkiServiceNowImportSetProcessor(endpoint));
+        bind(ServiceNowConstants.RESOURCE_ATTACHMENT, new HelsinkiServiceNowAttachmentProcessor(endpoint));
+        bind(ServiceNowConstants.RESOURCE_SCORECARDS, new HelsinkiServiceNowScorecardProcessor(endpoint));
+        bind(ServiceNowConstants.RESOURCE_MISC, new HelsinkiServiceNowMiscProcessor(endpoint));
+        bind(ServiceNowConstants.RESOURCE_SERVICE_CATALOG, new HelsinkiServiceNowServiceCatalogProcessor(endpoint));
+        bind(ServiceNowConstants.RESOURCE_SERVICE_CATALOG_ITEMS, new HelsinkiServiceNowServiceCatalogItemsProcessor(endpoint));
+        bind(ServiceNowConstants.RESOURCE_SERVICE_CATALOG_CARTS, new HelsinkiServiceNowServiceCatalogCartsProcessor(endpoint));
+        bind(ServiceNowConstants.RESOURCE_SERVICE_CATALOG_CATEGORIES, new HelsinkiServiceNowServiceCatalogCategoriesProcessor(endpoint));
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/109da7c9/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/releases/helsinki/HelsinkiServiceNowScorecardProcessor.java
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/releases/helsinki/HelsinkiServiceNowScorecardProcessor.java b/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/releases/helsinki/HelsinkiServiceNowScorecardProcessor.java
new file mode 100644
index 0000000..78cace8
--- /dev/null
+++ b/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/releases/helsinki/HelsinkiServiceNowScorecardProcessor.java
@@ -0,0 +1,87 @@
+/**
+ * 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.servicenow.releases.helsinki;
+
+import javax.ws.rs.HttpMethod;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+import org.apache.camel.Exchange;
+import org.apache.camel.Message;
+import org.apache.camel.component.servicenow.AbstractServiceNowProcessor;
+import org.apache.camel.component.servicenow.ServiceNowEndpoint;
+import org.apache.camel.component.servicenow.ServiceNowParams;
+
+import static org.apache.camel.component.servicenow.ServiceNowConstants.ACTION_RETRIEVE;
+import static org.apache.camel.component.servicenow.ServiceNowConstants.ACTION_SUBJECT_PERFORMANCE_ANALYTICS;
+
+class HelsinkiServiceNowScorecardProcessor extends AbstractServiceNowProcessor {
+
+    HelsinkiServiceNowScorecardProcessor(ServiceNowEndpoint endpoint) throws Exception {
+        super(endpoint);
+
+        addDispatcher(ACTION_RETRIEVE, ACTION_SUBJECT_PERFORMANCE_ANALYTICS, this::retrievePerformanceAnalytics);
+    }
+
+    /*
+     * This method retrieves Performance Analytics scorecard details.
+     *
+     * Method:
+     * - GET
+     *
+     * URL Format:
+     * - /api/now/pa/scorecards
+     */
+    private void retrievePerformanceAnalytics(Exchange exchange) throws Exception {
+        final Message in = exchange.getIn();
+        final Class<?> responseModel = getResponseModel(in);
+        final String apiVersion = getApiVersion(in);
+
+        Response response = client.reset()
+            .types(MediaType.APPLICATION_JSON_TYPE)
+            .path("now")
+            .path(apiVersion)
+            .path("pa")
+            .path("scorecards")
+            .query(ServiceNowParams.SYSPARM_UUID, in)
+            .query(ServiceNowParams.SYSPARM_BREAKDOWN, in)
+            .query(ServiceNowParams.SYSPARM_INCLUDE_SCORES, in)
+            .query(ServiceNowParams.SYSPARM_INCLUDE_AGGREGATES, in)
+            .query(ServiceNowParams.SYSPARM_INCLUDE_AVAILABLE_BREAKDOWNS, in)
+            .query(ServiceNowParams.SYSPARM_INCLUDE_AVAILABLE_AGGREGATES, in)
+            .query(ServiceNowParams.SYSPARM_DISPLAY_VALUE, in)
+            .query(ServiceNowParams.SYSPARM_EXCLUDE_REFERENCE_LINK, in)
+            .query(ServiceNowParams.SYSPARM_FAVORITES, in)
+            .query(ServiceNowParams.SYSPARM_KEY, in)
+            .query(ServiceNowParams.SYSPARM_TARGET, in)
+            .query(ServiceNowParams.SYSPARM_DISPLAY, in)
+            .query(ServiceNowParams.SYSPARM_CONTAINS, in)
+            .query(ServiceNowParams.SYSPARM_TAGS, in)
+            .query(ServiceNowParams.SYSPARM_PER_PAGE, in)
+            .query(ServiceNowParams.SYSPARM_PAGE, in)
+            .query(ServiceNowParams.SYSPARM_SORT_BY, in)
+            .query(ServiceNowParams.SYSPARM_SORT_DIR, in)
+            .query(ServiceNowParams.SYSPARM_ELEMENTS_FILTER, in)
+            .query(ServiceNowParams.SYSPARM_BREAKDOWN_RELATION, in)
+            .query(ServiceNowParams.SYSPARM_INCLUDE_SCORE_NOTES, in)
+            .query(responseModel)
+            .invoke(HttpMethod.GET);
+
+        setBodyAndHeaders(in, responseModel, response);
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/109da7c9/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/releases/helsinki/HelsinkiServiceNowServiceCatalogCartsProcessor.java
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/releases/helsinki/HelsinkiServiceNowServiceCatalogCartsProcessor.java b/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/releases/helsinki/HelsinkiServiceNowServiceCatalogCartsProcessor.java
new file mode 100644
index 0000000..d890172
--- /dev/null
+++ b/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/releases/helsinki/HelsinkiServiceNowServiceCatalogCartsProcessor.java
@@ -0,0 +1,218 @@
+/**
+ * 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.servicenow.releases.helsinki;
+
+import javax.ws.rs.HttpMethod;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+import org.apache.camel.Exchange;
+import org.apache.camel.Message;
+import org.apache.camel.component.servicenow.AbstractServiceNowProcessor;
+import org.apache.camel.component.servicenow.ServiceNowEndpoint;
+import org.apache.camel.component.servicenow.ServiceNowParams;
+
+import static org.apache.camel.component.servicenow.ServiceNowConstants.ACTION_DELETE;
+import static org.apache.camel.component.servicenow.ServiceNowConstants.ACTION_RETRIEVE;
+import static org.apache.camel.component.servicenow.ServiceNowConstants.ACTION_SUBJECT_CHECKOUT;
+import static org.apache.camel.component.servicenow.ServiceNowConstants.ACTION_SUBJECT_DELIVERY_ADDRESS;
+import static org.apache.camel.component.servicenow.ServiceNowConstants.ACTION_UPDATE;
+    
+class HelsinkiServiceNowServiceCatalogCartsProcessor extends AbstractServiceNowProcessor {
+
+    HelsinkiServiceNowServiceCatalogCartsProcessor(ServiceNowEndpoint endpoint) throws Exception {
+        super(endpoint);
+
+        addDispatcher(ACTION_RETRIEVE, ACTION_SUBJECT_DELIVERY_ADDRESS, this::retrieveDeliveryAddress);
+        addDispatcher(ACTION_RETRIEVE, ACTION_SUBJECT_CHECKOUT, this::retrieveCheckoutCart);
+        addDispatcher(ACTION_RETRIEVE, ACTION_SUBJECT_CHECKOUT, this::retrieveCarts);
+        addDispatcher(ACTION_UPDATE, ACTION_SUBJECT_CHECKOUT, this::checkoutCart);
+        addDispatcher(ACTION_UPDATE, this::updateCart);
+        addDispatcher(ACTION_DELETE, this::deleteCart);
+    }
+
+    /*
+     * This method retrieves the default list of cart contents, cart details,
+     * and price shown on the two-step checkout page.
+     *
+     * Method:
+     * - GET
+     *
+     * URL Format:
+     * - /sn_sc/servicecatalog/cart
+     */
+    private void retrieveCarts(Exchange exchange) throws Exception {
+        final Message in = exchange.getIn();
+        final Class<?> responseModel = getResponseModel(in);
+        final String apiVersion = getApiVersion(in);
+
+        Response response = client.reset()
+            .types(MediaType.APPLICATION_JSON_TYPE)
+            .path("sn_sc")
+            .path(apiVersion)
+            .path("servicecatalog")
+            .path("cart")
+            .query(responseModel)
+            .invoke(HttpMethod.GET);
+
+        setBodyAndHeaders(in, responseModel, response);
+    }
+
+    /*
+     * This method retrieves the shipping address of the requested user.
+     *
+     * Method:
+     * - GET
+     *
+     * URL Format:
+     * - /sn_sc/servicecatalog/cart/delivery_address/{user_id}
+     */
+    private void retrieveDeliveryAddress(Exchange exchange) throws Exception {
+        final Message in = exchange.getIn();
+        final Class<?> responseModel = getResponseModel(in);
+        final String apiVersion = getApiVersion(in);
+
+        Response response = client.reset()
+            .types(MediaType.APPLICATION_JSON_TYPE)
+            .path("sn_sc")
+            .path(apiVersion)
+            .path("servicecatalog")
+            .path("cart")
+            .path("delivery_address")
+            .path(getMandatoryRequestParamFromHeader(ServiceNowParams.PARAM_USER_ID, in))
+            .query(responseModel)
+            .invoke(HttpMethod.GET);
+
+        setBodyAndHeaders(in, responseModel, response);
+    }
+
+    /*
+     * This method edits and updates any item in the cart.
+     *
+     * Method:
+     * - POST
+     *
+     * URL Format:
+     * - /sn_sc/servicecatalog/cart/{cart_item_id}
+     */
+    private void updateCart(Exchange exchange) throws Exception {
+        final Message in = exchange.getIn();
+        final Class<?> responseModel = getResponseModel(in);
+        final String apiVersion = getApiVersion(in);
+
+        Response response = client.reset()
+            .types(MediaType.APPLICATION_JSON_TYPE)
+            .path("sn_sc")
+            .path(apiVersion)
+            .path("servicecatalog")
+            .path("cart")
+            .path(getMandatoryRequestParamFromHeader(ServiceNowParams.PARAM_CART_ITEM_ID, in))
+            .query(responseModel)
+            .invoke(HttpMethod.POST, in.getMandatoryBody());
+
+        setBodyAndHeaders(in, responseModel, response);
+    }
+
+    /*
+     * This method deletes the cart and contents of the cart for a given user
+     * role and sys_id.
+     *
+     * Method:
+     * - DELETE
+     *
+     * URL Format:
+     * - /sn_sc/servicecatalog/cart/{sys_id}/empty
+     */
+    private void deleteCart(Exchange exchange) throws Exception {
+        final Message in = exchange.getIn();
+        final Class<?> responseModel = getResponseModel(in);
+        final String apiVersion = getApiVersion(in);
+
+        Response response = client.reset()
+            .types(MediaType.APPLICATION_JSON_TYPE)
+            .path("sn_sc")
+            .path(apiVersion)
+            .path("servicecatalog")
+            .path("cart")
+            .path(getMandatoryRequestParamFromHeader(ServiceNowParams.PARAM_SYS_ID, in))
+            .path("empty")
+            .query(responseModel)
+            .invoke(HttpMethod.DELETE);
+
+        setBodyAndHeaders(in, responseModel, response);
+    }
+
+    /*
+     * This method retrieves the checkout cart details based on the two-step
+     * checkout process enabled or disabled. If the user enables two-step checkout,
+     * the method returns cart order status and all the information required for
+     * two-step checkout. If the user disables two-step checkout, the method
+     * checks out the cart and returns the request number and request order ID.
+     *
+     * Method:
+     * - POST
+     *
+     * URL Format:
+     * - /sn_sc/servicecatalog/cart/checkout
+     */
+    private void retrieveCheckoutCart(Exchange exchange) throws Exception {
+        final Message in = exchange.getIn();
+        final Class<?> responseModel = getResponseModel(in);
+        final String apiVersion = getApiVersion(in);
+
+        Response response = client.reset()
+            .types(MediaType.APPLICATION_JSON_TYPE)
+            .path("sn_sc")
+            .path(apiVersion)
+            .path("servicecatalog")
+            .path("cart")
+            .path("checkout")
+            .query(responseModel)
+            .invoke(HttpMethod.POST);
+
+        setBodyAndHeaders(in, responseModel, response);
+    }
+
+    /*
+     * This method checks out the user cart, whether two-step parameter is
+     * enabled or disabled.
+     *
+     * Method:
+     * - POST
+     *
+     * URL Format:
+     * - /sn_sc/servicecatalog/cart/submit_order
+     */
+    private void checkoutCart(Exchange exchange) throws Exception {
+        final Message in = exchange.getIn();
+        final Class<?> responseModel = getResponseModel(in);
+        final String apiVersion = getApiVersion(in);
+
+        Response response = client.reset()
+            .types(MediaType.APPLICATION_JSON_TYPE)
+            .path("sn_sc")
+            .path(apiVersion)
+            .path("servicecatalog")
+            .path("cart")
+            .path("submit_order")
+            .query(responseModel)
+            .invoke(HttpMethod.POST);
+
+        setBodyAndHeaders(in, responseModel, response);
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/109da7c9/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/releases/helsinki/HelsinkiServiceNowServiceCatalogCategoriesProcessor.java
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/releases/helsinki/HelsinkiServiceNowServiceCatalogCategoriesProcessor.java b/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/releases/helsinki/HelsinkiServiceNowServiceCatalogCategoriesProcessor.java
new file mode 100644
index 0000000..bd5e905
--- /dev/null
+++ b/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/releases/helsinki/HelsinkiServiceNowServiceCatalogCategoriesProcessor.java
@@ -0,0 +1,69 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.camel.component.servicenow.releases.helsinki;
+
+import javax.ws.rs.HttpMethod;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+import org.apache.camel.Exchange;
+import org.apache.camel.Message;
+import org.apache.camel.component.servicenow.AbstractServiceNowProcessor;
+import org.apache.camel.component.servicenow.ServiceNowEndpoint;
+import org.apache.camel.component.servicenow.ServiceNowParams;
+import org.apache.camel.util.ObjectHelper;
+
+import static org.apache.camel.component.servicenow.ServiceNowConstants.ACTION_RETRIEVE;
+
+class HelsinkiServiceNowServiceCatalogCategoriesProcessor extends AbstractServiceNowProcessor {
+
+    HelsinkiServiceNowServiceCatalogCategoriesProcessor(ServiceNowEndpoint endpoint) throws Exception {
+        super(endpoint);
+
+        addDispatcher(ACTION_RETRIEVE, this::retrieveCategory);
+    }
+
+    /*
+     * This method retrieves all the information about a requested category.
+     *
+     * Method:
+     * - GET
+     *
+     * URL Format:
+     * - /sn_sc/servicecatalog/categories/{sys_id}
+     */
+    private void retrieveCategory(Exchange exchange) throws Exception {
+        final Message in = exchange.getIn();
+        final Class<?> responseModel = getResponseModel(in);
+        final String sysId = getSysID(in);
+        final String apiVersion = getApiVersion(in);
+
+        Response response = client.reset()
+            .types(MediaType.APPLICATION_JSON_TYPE)
+            .path("sn_sc")
+            .path(apiVersion)
+            .path("servicecatalog")
+            .path("categories")
+            .path(ObjectHelper.notNull(sysId, "sysId"))
+            .query(ServiceNowParams.SYSPARM_VIEW, in)
+            .query(responseModel)
+            .invoke(HttpMethod.GET);
+
+        setBodyAndHeaders(in, responseModel, response);
+    }
+}


[13/19] camel git commit: CAMEL-11555: ServiceNow : create a maven plugin to generate models based on table layout

Posted by lb...@apache.org.
http://git-wip-us.apache.org/repos/asf/camel/blob/109da7c9/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowConfiguration.java
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowConfiguration.java b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowConfiguration.java
deleted file mode 100644
index bc46bcb..0000000
--- a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowConfiguration.java
+++ /dev/null
@@ -1,689 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.camel.component.servicenow;
-
-import java.util.HashMap;
-import java.util.Map;
-
-import com.fasterxml.jackson.annotation.JsonInclude;
-import com.fasterxml.jackson.databind.DeserializationFeature;
-import com.fasterxml.jackson.databind.ObjectMapper;
-
-import org.apache.camel.RuntimeCamelException;
-import org.apache.camel.spi.Metadata;
-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;
-import org.apache.cxf.configuration.security.ProxyAuthorizationPolicy;
-import org.apache.cxf.transports.http.configuration.HTTPClientPolicy;
-
-@UriParams
-public class ServiceNowConfiguration implements Cloneable {
-
-    private static final ObjectMapper MAPPER = new ObjectMapper()
-        .configure(
-            DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES,
-            false)
-        .setSerializationInclusion(
-            JsonInclude.Include.NON_NULL
-        );
-
-    @UriParam(label = "security", secret = true)
-    @Metadata(required = "true")
-    private String userName;
-    @UriParam(label = "security", secret = true)
-    @Metadata(required = "true")
-    private String password;
-    @UriParam(label = "security", secret = true)
-    private String oauthClientId;
-    @UriParam(label = "security", secret = true)
-    private String oauthClientSecret;
-    @UriParam(label = "security", secret = true)
-    private String oauthTokenUrl;
-    @UriParam(label = "security")
-    private String apiUrl;
-    @UriParam(label = "advanced")
-    private String apiVersion;
-    @UriParam
-    private String resource;
-    @UriParam
-    private String table;
-    @UriParam
-    private Boolean excludeReferenceLink = false;
-    @UriParam
-    private Boolean suppressAutoSysField = false;
-    @UriParam
-    private Boolean includeScores = false;
-    @UriParam
-    private Boolean includeAggregates = false;
-    @UriParam
-    private Boolean includeAvailableBreakdowns = false;
-    @UriParam
-    private Boolean includeAvailableAggregates = false;
-    @UriParam
-    private Boolean includeScoreNotes = false;
-    @UriParam
-    private Boolean topLevelOnly;
-    @UriParam
-    private Boolean favorites;
-    @UriParam(label = "advanced", defaultValue = "false")
-    private Boolean retrieveTargetRecordOnImport = false;
-    @UriParam
-    private Boolean key;
-    @UriParam
-    private Boolean target;
-    @UriParam(defaultValue = "true", enums = "false,true,all")
-    private String display = "true";
-    @UriParam(defaultValue = "10")
-    private Integer perPage = 10;
-    @UriParam(enums = "value,change,changeperc,gap,gapperc,duedate,name,order,default,group,indicator_group,frequency,target,date,trend,bullet,direction")
-    private String sortBy;
-    @UriParam(enums = "asc,desc")
-    private String sortDir;
-    @UriParam
-    private Boolean suppressPaginationHeader = false;
-    @UriParam(defaultValue = "false", enums = "false,true,all")
-    private String displayValue = "false";
-    @UriParam
-    private Boolean inputDisplayValue = false;
-    @UriParam(prefix = "model.", multiValue = true, javaType = "java.lang.String", description = "Defines both request and response models")
-    private transient Map<String, Class<?>> models; // field not in use as its a shortcut for both requestModels/responseModels
-    @UriParam(prefix = "request-model.", multiValue = true, javaType = "java.lang.String")
-    private Map<String, Class<?>> requestModels;
-    @UriParam(prefix = "response-model.", multiValue = true, javaType = "java.lang.String")
-    private Map<String, Class<?>> responseModels;
-    @UriParam(label = "advanced")
-    private ObjectMapper mapper = MAPPER;
-    @UriParam(defaultValue = "HELSINKI", enums = "FUJI,GENEVA,HELSINKI")
-    private ServiceNowRelease release = ServiceNowRelease.HELSINKI;
-    @UriParam(label = "security")
-    private SSLContextParameters sslContextParameters;
-    @UriParam(label = "advanced")
-    private HTTPClientPolicy httpClientPolicy;
-    @UriParam(label = "advanced")
-    private ProxyAuthorizationPolicy proxyAuthorizationPolicy;
-    @UriParam(label = "proxy")
-    private String proxyHost;
-    @UriParam(label = "proxy")
-    private Integer proxyPort;
-    @UriParam(label = "proxy,security")
-    private String proxyUserName;
-    @UriParam(label = "proxy,security")
-    private String proxyPassword;
-
-    public String getUserName() {
-        return userName;
-    }
-
-    public String getApiUrl() {
-        return apiUrl;
-    }
-
-    /**
-     * The ServiceNow REST API url
-     */
-    public void setApiUrl(String apiUrl) {
-        this.apiUrl = apiUrl;
-    }
-
-    public boolean hasApiUrl() {
-        return apiUrl != null;
-    }
-
-    public String getApiVersion() {
-        return apiVersion;
-    }
-
-    /**
-     * The ServiceNow REST API version, default latest
-     */
-    public void setApiVersion(String apiVersion) {
-        this.apiVersion = apiVersion;
-    }
-
-    /**
-     * ServiceNow user account name, MUST be provided
-     */
-    public void setUserName(String userName) {
-        this.userName = userName;
-    }
-
-    public String getPassword() {
-        return password;
-    }
-
-    /**
-     * ServiceNow account password, MUST be provided
-     */
-    public void setPassword(String password) {
-        this.password = password;
-    }
-
-    public String getOauthClientId() {
-        return oauthClientId;
-    }
-
-    /**
-     * OAuth2 ClientID
-     */
-    public void setOauthClientId(String oauthClientId) {
-        this.oauthClientId = oauthClientId;
-    }
-
-    public String getOauthClientSecret() {
-        return oauthClientSecret;
-    }
-
-    /**
-     * OAuth2 ClientSecret
-     */
-    public void setOauthClientSecret(String oauthClientSecret) {
-        this.oauthClientSecret = oauthClientSecret;
-    }
-
-    public String getOauthTokenUrl() {
-        return oauthTokenUrl;
-    }
-
-    public boolean hasOauthTokenUrl() {
-        return oauthTokenUrl != null;
-    }
-
-    /**
-     * OAuth token Url
-     */
-    public void setOauthTokenUrl(String oauthTokenUrl) {
-        this.oauthTokenUrl = oauthTokenUrl;
-    }
-
-    public boolean hasBasicAuthentication() {
-        return ObjectHelper.isNotEmpty(userName)
-            && ObjectHelper.isNotEmpty(password);
-    }
-
-    public boolean hasOAuthAuthentication() {
-        return ObjectHelper.isNotEmpty(userName)
-            && ObjectHelper.isNotEmpty(password)
-            && ObjectHelper.isNotEmpty(oauthClientId)
-            && ObjectHelper.isNotEmpty(oauthClientSecret);
-    }
-
-    public String getResource() {
-        return resource;
-    }
-
-    /**
-     * The default resource, can be overridden by header CamelServiceNowResource
-     */
-    public void setResource(String resource) {
-        this.resource = resource;
-    }
-
-    public String getTable() {
-        return table;
-    }
-
-    /**
-     * The default table, can be overridden by header CamelServiceNowTable
-     */
-    public void setTable(String table) {
-        this.table = table;
-    }
-
-    public Boolean getExcludeReferenceLink() {
-        return excludeReferenceLink;
-    }
-
-    /**
-     * True to exclude Table API links for reference fields (default: false)
-     */
-    public void setExcludeReferenceLink(Boolean excludeReferenceLink) {
-        this.excludeReferenceLink = excludeReferenceLink;
-    }
-
-    public Boolean getSuppressAutoSysField() {
-        return suppressAutoSysField;
-    }
-
-    /**
-     * True to suppress auto generation of system fields (default: false)
-     */
-    public void setSuppressAutoSysField(Boolean suppressAutoSysField) {
-        this.suppressAutoSysField = suppressAutoSysField;
-    }
-
-    public Boolean getSuppressPaginationHeader() {
-        return suppressPaginationHeader;
-    }
-
-    /**
-     * Set this value to true to remove the Link header from the response. The
-     * Link header allows you to request additional pages of data when the number
-     * of records matching your query exceeds the query limit
-     */
-    public void setSuppressPaginationHeader(Boolean suppressPaginationHeader) {
-        this.suppressPaginationHeader = suppressPaginationHeader;
-    }
-
-    public Boolean getIncludeScores() {
-        return includeScores;
-    }
-
-    /**
-     * Set this parameter to true to return all scores for a scorecard. If a value
-     * is not specified, this parameter defaults to false and returns only the most
-     * recent score value.
-     */
-    public void setIncludeScores(Boolean includeScores) {
-        this.includeScores = includeScores;
-    }
-
-    public Boolean getIncludeAggregates() {
-        return includeAggregates;
-    }
-
-    /**
-     * Set this parameter to true to always return all available aggregates for
-     * an indicator, including when an aggregate has already been applied. If a
-     * value is not specified, this parameter defaults to false and returns no
-     * aggregates.
-     */
-    public void setIncludeAggregates(Boolean includeAggregates) {
-        this.includeAggregates = includeAggregates;
-    }
-
-    public Boolean getIncludeAvailableBreakdowns() {
-        return includeAvailableBreakdowns;
-    }
-
-    /**
-     * Set this parameter to true to return all available breakdowns for an indicator.
-     * If a value is not specified, this parameter defaults to false and returns
-     * no breakdowns.
-     */
-    public void setIncludeAvailableBreakdowns(Boolean includeAvailableBreakdowns) {
-        this.includeAvailableBreakdowns = includeAvailableBreakdowns;
-    }
-
-    public Boolean getIncludeAvailableAggregates() {
-        return includeAvailableAggregates;
-    }
-
-    /**
-     * Set this parameter to true to return all available aggregates for an indicator
-     * when no aggregate has been applied. If a value is not specified, this parameter
-     * defaults to false and returns no aggregates.
-     */
-    public void setIncludeAvailableAggregates(Boolean includeAvailableAggregates) {
-        this.includeAvailableAggregates = includeAvailableAggregates;
-    }
-
-    public Boolean getIncludeScoreNotes() {
-        return includeScoreNotes;
-    }
-
-    /**
-     * Set this parameter to true to return all notes associated with the score.
-     * The note element contains the note text as well as the author and timestamp
-     * when the note was added.
-     */
-    public void setIncludeScoreNotes(Boolean includeScoreNotes) {
-        this.includeScoreNotes = includeScoreNotes;
-    }
-
-    public Boolean getFavorites() {
-        return favorites;
-    }
-
-    /**
-     * Set this parameter to true to return only scorecards that are favorites of
-     * the querying user.
-     */
-    public void setFavorites(Boolean favorites) {
-        this.favorites = favorites;
-    }
-
-    public Boolean getRetrieveTargetRecordOnImport() {
-        return retrieveTargetRecordOnImport;
-    }
-
-    /**
-     * Set this parameter to true to retrieve the target record when using import
-     * set api. The import set result is then replaced by the target record
-     */
-    public void setRetrieveTargetRecordOnImport(Boolean retrieveTargetRecordOnImport) {
-        this.retrieveTargetRecordOnImport = retrieveTargetRecordOnImport;
-    }
-
-    public Boolean getKey() {
-        return key;
-    }
-
-    /**
-     * Set this parameter to true to return only scorecards for key indicators.
-     */
-    public void setKey(Boolean key) {
-        this.key = key;
-    }
-
-    public Boolean getTarget() {
-        return target;
-    }
-
-    /**
-     * Set this parameter to true to return only scorecards that have a target.
-     */
-    public void setTarget(Boolean target) {
-        this.target = target;
-    }
-
-    public String getDisplay() {
-        return display;
-    }
-
-    /**
-     * Set this parameter to true to return only scorecards where the indicator
-     * Display field is selected. Set this parameter to all to return scorecards
-     * with any Display field value. This parameter is true by default.
-     */
-    public void setDisplay(String display) {
-        this.display = display;
-    }
-
-    public Integer getPerPage() {
-        return perPage;
-    }
-
-    /**
-     * Enter the maximum number of scorecards each query can return. By default
-     * this value is 10, and the maximum is 100.
-     */
-    public void setPerPage(Integer perPage) {
-        this.perPage = perPage;
-    }
-
-    public String getSortBy() {
-        return sortBy;
-    }
-
-    /**
-     * Specify the value to use when sorting results. By default, queries sort
-     * records by value.
-     */
-    public void setSortBy(String sortBy) {
-        this.sortBy = sortBy;
-    }
-
-    public String getSortDir() {
-        return sortDir;
-    }
-
-    /**
-     * Specify the sort direction, ascending or descending. By default, queries
-     * sort records in descending order. Use sysparm_sortdir=asc to sort in
-     * ascending order.
-     */
-    public void setSortDir(String sortDir) {
-        this.sortDir = sortDir;
-    }
-
-    public String getDisplayValue() {
-        return displayValue;
-    }
-
-    /**
-     * Return the display value (true), actual value (false), or both (all) for
-     * reference fields (default: false)
-     */
-    public void setDisplayValue(String displayValue) {
-        this.displayValue = displayValue;
-    }
-
-    public Boolean getInputDisplayValue() {
-        return inputDisplayValue;
-    }
-
-    /**
-     * True to set raw value of input fields (default: false)
-     */
-    public void setInputDisplayValue(Boolean inputDisplayValue) {
-        this.inputDisplayValue = inputDisplayValue;
-    }
-
-    public Map<String, Class<?>> getRequestModels() {
-        return requestModels;
-    }
-
-    /**
-     * Sets Jackson's ObjectMapper to use for request/reply
-     */
-    public void setMapper(ObjectMapper mapper) {
-        this.mapper = mapper;
-    }
-
-    public ObjectMapper getMapper() {
-        return mapper;
-    }
-
-    public boolean hasMapper() {
-        return mapper != null;
-    }
-
-    /**
-     * The ServiceNow release to target, default to Helsinki
-     *
-     * See https://docs.servicenow.com
-     */
-    public void setRelease(ServiceNowRelease release) {
-        this.release = release;
-    }
-
-    public ServiceNowRelease getRelease() {
-        return release;
-    }
-
-    public Boolean getTopLevelOnly() {
-        return topLevelOnly;
-    }
-
-    /**
-     * Gets only those categories whose parent is a catalog.
-     */
-    public void setTopLevelOnly(Boolean topLevelOnly) {
-        this.topLevelOnly = topLevelOnly;
-    }
-
-    public SSLContextParameters getSslContextParameters() {
-        return sslContextParameters;
-    }
-
-    /**
-     * To configure security using SSLContextParameters. See http://camel.apache.org/camel-configuration-utilities.html
-     */
-    public void setSslContextParameters(SSLContextParameters sslContextParameters) {
-        this.sslContextParameters = sslContextParameters;
-    }
-
-    public HTTPClientPolicy getHttpClientPolicy() {
-        return httpClientPolicy;
-    }
-
-    /**
-     * To configure http-client
-     */
-    public void setHttpClientPolicy(HTTPClientPolicy httpClientPolicy) {
-        this.httpClientPolicy = httpClientPolicy;
-    }
-
-    public ProxyAuthorizationPolicy getProxyAuthorizationPolicy() {
-        return proxyAuthorizationPolicy;
-    }
-
-    /**
-     * To configure proxy authentication
-     */
-    public void setProxyAuthorizationPolicy(ProxyAuthorizationPolicy proxyAuthorizationPolicy) {
-        this.proxyAuthorizationPolicy = proxyAuthorizationPolicy;
-    }
-
-    public String getProxyHost() {
-        return proxyHost;
-    }
-
-    /**
-     * The proxy host name
-     */
-    public void setProxyHost(String proxyHost) {
-        this.proxyHost = proxyHost;
-    }
-
-    public Integer getProxyPort() {
-        return proxyPort;
-    }
-
-    /**
-     * The proxy port number
-     */
-    public void setProxyPort(Integer proxyPort) {
-        this.proxyPort = proxyPort;
-    }
-
-    public String getProxyUserName() {
-        return proxyUserName;
-    }
-
-    /**
-     * Username for proxy authentication
-     */
-    public void setProxyUserName(String proxyUserName) {
-        this.proxyUserName = proxyUserName;
-    }
-
-    public String getProxyPassword() {
-        return proxyPassword;
-    }
-
-    /**
-     * Password for proxy authentication
-     */
-    public void setProxyPassword(String proxyPassword) {
-        this.proxyPassword = proxyPassword;
-    }
-
-    // *************************************************
-    //
-    // *************************************************
-
-    public void setModels(Map<String, Class<?>> models) {
-        setRequestModels(models);
-        setResponseModels(models);
-    }
-
-    public void addModel(String name, Class<?> type) {
-        addRequestModel(name, type);
-        addResponseModel(name, type);
-    }
-
-    // *************************************************
-    // Request model
-    // *************************************************
-
-    /**
-     * Defines the request model
-     */
-    public void setRequestModels(Map<String, Class<?>> models) {
-        if (this.requestModels == null) {
-            this.requestModels = new HashMap<>();
-        }
-
-        this.requestModels.clear();
-        this.requestModels.putAll(models);
-    }
-
-    public void addRequestModel(String name, Class<?> type) {
-        if (this.requestModels == null) {
-            this.requestModels = new HashMap<>();
-        }
-
-        this.requestModels.put(name, type);
-    }
-
-    public Class<?> getRequestModel(String name) {
-        return getRequestModel(name, null);
-    }
-
-    public Class<?> getRequestModel(String name, Class<?> defaultType) {
-        Class<?> model = defaultType;
-
-        if (this.requestModels != null && this.requestModels.containsKey(name)) {
-            model = this.requestModels.get(name);
-        }
-
-        return model;
-    }
-
-    // *************************************************
-    // Response model
-    // *************************************************
-
-    /**
-     * Defines the response model
-     */
-    public void setResponseModels(Map<String, Class<?>> models) {
-        if (this.responseModels == null) {
-            this.responseModels = new HashMap<>();
-        }
-
-        this.responseModels.putAll(models);
-    }
-
-    public void addResponseModel(String name, Class<?> type) {
-        if (this.responseModels == null) {
-            this.responseModels = new HashMap<>();
-        }
-
-        this.responseModels.clear();
-        this.responseModels.put(name, type);
-    }
-
-    public Class<?> getResponseModel(String name) {
-        return getResponseModel(name, null);
-    }
-
-    public Class<?> getResponseModel(String name, Class<?> defaultType) {
-        Class<?> model = defaultType;
-
-        if (this.responseModels != null && this.responseModels.containsKey(name)) {
-            model = this.responseModels.get(name);
-        }
-
-        return model;
-    }
-
-    // *************************************************
-    //
-    // *************************************************
-
-    public ServiceNowConfiguration copy() {
-        try {
-            return (ServiceNowConfiguration)super.clone();
-        } catch (CloneNotSupportedException e) {
-            throw new RuntimeCamelException(e);
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/camel/blob/109da7c9/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowConstants.java
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowConstants.java b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowConstants.java
deleted file mode 100644
index b967bbe..0000000
--- a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowConstants.java
+++ /dev/null
@@ -1,80 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.camel.component.servicenow;
-
-public final class ServiceNowConstants {
-    public static final String CAMEL_HEADER_PREFIX = "CamelServiceNow";
-
-    public static final String RESOURCE = "CamelServiceNowResource";
-    public static final String ACTION = "CamelServiceNowAction";
-    public static final String ACTION_SUBJECT = "CamelServiceNowActionSubject";
-    public static final String MODEL = "CamelServiceNowModel";
-    public static final String REQUEST_MODEL = "CamelServiceNowRequestModel";
-    public static final String RESPONSE_MODEL = "CamelServiceNowResponseModel";
-    public static final String OFFSET_NEXT = "CamelServiceNowOffsetNext";
-    public static final String OFFSET_PREV = "CamelServiceNowOffsetPrev";
-    public static final String OFFSET_FIRST = "CamelServiceNowOffsetFirst";
-    public static final String OFFSET_LAST = "CamelServiceNowOffsetLast";
-    public static final String CONTENT_TYPE = "CamelServiceNowContentType";
-    public static final String CONTENT_ENCODING = "CamelServiceNowContentEncoding";
-    public static final String CONTENT_META = "CamelServiceNowContentMeta";
-    public static final String RESPONSE_META = "CamelServiceNowResponseMeta";
-    public static final String API_VERSION = "CamelServiceNowApiVersion";
-    public static final String RESPONSE_TYPE = "CamelServiceNowResponseType";
-    public static final String RETRIEVE_TARGET_RECORD = "CamelServiceNowRetrieveTargetRecord";
-
-    public static final String ATTACHMENT_META_HEADER = "X-Attachment-Metadata";
-
-    public static final String RESOURCE_TABLE = "table";
-    public static final String RESOURCE_AGGREGATE = "aggregate";
-    public static final String RESOURCE_IMPORT = "import";
-    public static final String RESOURCE_ATTACHMENT = "attachment";
-    public static final String RESOURCE_SCORECARDS = "scorecards";
-    public static final String RESOURCE_MISC = "misc";
-    public static final String RESOURCE_SERVICE_CATALOG = "service_catalog";
-    public static final String RESOURCE_SERVICE_CATALOG_ITEMS = "service_catalog_items";
-    public static final String RESOURCE_SERVICE_CATALOG_CARTS = "service_catalog_cart";
-    public static final String RESOURCE_SERVICE_CATALOG_CATEGORIES = "service_catalog_categories";
-
-    public static final String ACTION_RETRIEVE = "retrieve";
-    public static final String ACTION_CONTENT = "content";
-    public static final String ACTION_CREATE = "create";
-    public static final String ACTION_MODIFY = "modify";
-    public static final String ACTION_DELETE = "delete";
-    public static final String ACTION_UPDATE = "update";
-    public static final String ACTION_UPLOAD = "upload";
-
-    public static final String ACTION_SUBJECT_CATEGORIES = "categories";
-    public static final String ACTION_SUBJECT_CART = "cart";
-    public static final String ACTION_SUBJECT_PRODUCER = "producer";
-    public static final String ACTION_SUBJECT_GUIDE = "guide";
-    public static final String ACTION_SUBJECT_SUBMIT_GUIDE = "submit_guide";
-    public static final String ACTION_SUBJECT_CHECKOUT_GUIDE = "checkout_guide";
-    public static final String ACTION_SUBJECT_PERFORMANCE_ANALYTICS = "performance_analytics";
-    public static final String ACTION_SUBJECT_USER_ROLE_INHERITANCE = "user_role_inheritance";
-    public static final String ACTION_SUBJECT_IDENTIFY_RECONCILE = "identify_reconcile";
-    public static final String ACTION_SUBJECT_DELIVERY_ADDRESS = "delivery_address";
-    public static final String ACTION_SUBJECT_CHECKOUT = "checkout";
-
-    public static final String LINK_NEXT = "next";
-    public static final String LINK_PREV = "prev";
-    public static final String LINK_FIRST = "first";
-    public static final String LINK_LAST = "last";
-
-    private ServiceNowConstants() {
-    }
-}

http://git-wip-us.apache.org/repos/asf/camel/blob/109da7c9/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowDispatcher.java
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowDispatcher.java b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowDispatcher.java
deleted file mode 100644
index e3a0473..0000000
--- a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowDispatcher.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.camel.component.servicenow;
-
-import java.util.function.Predicate;
-
-import org.apache.camel.Exchange;
-import org.apache.camel.Message;
-import org.apache.camel.Processor;
-import org.apache.camel.util.ObjectHelper;
-
-public class ServiceNowDispatcher {
-    private final Predicate<Exchange> predicate;
-    private final Processor delegate;
-
-    public ServiceNowDispatcher(Predicate<Exchange> predicate, Processor delegate) {
-        this.predicate = ObjectHelper.notNull(predicate, "predicate");
-        this.delegate = ObjectHelper.notNull(delegate, "delegate");
-    }
-
-    public boolean match(Exchange exchange) {
-        return predicate.test(exchange);
-    }
-
-    public void process(Exchange exchange) throws Exception {
-        delegate.process(exchange);
-    }
-
-    // ********************
-    // Helpers
-    // ********************
-
-    public static ServiceNowDispatcher on(final String action, final String subject, final Processor delegate) {
-        return new ServiceNowDispatcher(e -> matches(e.getIn(), action, subject), delegate);
-    }
-
-    public static boolean matches(Message in, String action, final String subject) {
-        return ObjectHelper.equal(action, in.getHeader(ServiceNowConstants.ACTION, String.class), true)
-            && ObjectHelper.equal(subject, in.getHeader(ServiceNowConstants.ACTION_SUBJECT, String.class), true);
-    }
-}

http://git-wip-us.apache.org/repos/asf/camel/blob/109da7c9/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowEndpoint.java
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowEndpoint.java b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowEndpoint.java
deleted file mode 100644
index dcf3563..0000000
--- a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowEndpoint.java
+++ /dev/null
@@ -1,80 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.camel.component.servicenow;
-
-import org.apache.camel.Consumer;
-import org.apache.camel.Processor;
-import org.apache.camel.Producer;
-import org.apache.camel.impl.DefaultEndpoint;
-import org.apache.camel.spi.Metadata;
-import org.apache.camel.spi.UriEndpoint;
-import org.apache.camel.spi.UriParam;
-import org.apache.camel.spi.UriPath;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * The servicenow component is used to integrate Camel with <a href="http://www.servicenow.com/">ServiceNow</a> cloud services.
- */
-@UriEndpoint(firstVersion = "2.18.0", scheme = "servicenow", title = "ServiceNow", syntax = "servicenow:instanceName", producerOnly = true, label = "api,cloud,management")
-public class ServiceNowEndpoint extends DefaultEndpoint {
-    private static final Logger LOGGER = LoggerFactory.getLogger(ServiceNowEndpoint.class);
-
-    @UriPath(description = "The ServiceNow instance name")
-    @Metadata(required = "true")
-    private final String instanceName;
-
-    @UriParam
-    private final ServiceNowConfiguration configuration;
-
-    public ServiceNowEndpoint(String uri, ServiceNowComponent component, ServiceNowConfiguration configuration, String instanceName) throws Exception {
-        super(uri, component);
-
-        this.configuration = configuration;
-        this.instanceName = instanceName;
-    }
-
-    @Override
-    public Producer createProducer() throws Exception {
-        ServiceNowProducer producer = configuration.getRelease().get(this);
-        LOGGER.info("Producer for ServiceNow Rel. {} = {}/{}",
-            configuration.getRelease().name(),
-            producer.getRelease().name(),
-            producer.getClass().getName()
-        );
-
-        return producer;
-    }
-
-    @Override
-    public Consumer createConsumer(Processor processor) throws Exception {
-        throw new UnsupportedOperationException("Consumer is not supported");
-    }
-
-    @Override
-    public boolean isSingleton() {
-        return true;
-    }
-
-    public ServiceNowConfiguration getConfiguration() {
-        return configuration;
-    }
-
-    public String getInstanceName() {
-        return instanceName;
-    }
-}

http://git-wip-us.apache.org/repos/asf/camel/blob/109da7c9/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowException.java
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowException.java b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowException.java
deleted file mode 100644
index 6a5e0a9..0000000
--- a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowException.java
+++ /dev/null
@@ -1,69 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.camel.component.servicenow;
-
-import java.util.Collections;
-import java.util.Map;
-
-import org.apache.camel.CamelException;
-
-public class ServiceNowException extends CamelException {
-    private final Integer code;
-    private final String status;
-    private final String detail;
-    private final Map<Object, Object> attributes;
-
-    public ServiceNowException(Integer code, String status, String message, String detail) {
-        super(message);
-        this.code = code;
-        this.status = status;
-        this.detail = detail;
-        this.attributes = Collections.emptyMap();
-    }
-
-    public ServiceNowException(Integer code, Map<Object, Object> attributes) {
-        super(String.format("Status (%d)", code));
-        this.code = code;
-        this.status = null;
-        this.detail = null;
-        this.attributes = Collections.unmodifiableMap(attributes);
-    }
-
-    public Integer getCode() {
-        return code;
-    }
-
-    public String getStatus() {
-        return status;
-    }
-
-    public String getDetail() {
-        return detail;
-    }
-
-    public Map<Object, Object> getAttributes() {
-        return attributes;
-    }
-
-    @Override
-    public String toString() {
-        return getMessage() != null
-            ? "" + this.status + ": " + getMessage()
-            : super.toString();
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/camel/blob/109da7c9/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowExceptionModel.java
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowExceptionModel.java b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowExceptionModel.java
deleted file mode 100644
index a881d4a..0000000
--- a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowExceptionModel.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.camel.component.servicenow;
-
-import java.util.Map;
-
-import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
-import com.fasterxml.jackson.annotation.JsonProperty;
-
-@JsonIgnoreProperties(ignoreUnknown = true)
-public final class ServiceNowExceptionModel {
-    private final String status;
-    private final Map<String, String> error;
-
-    public ServiceNowExceptionModel(
-        @JsonProperty("status") String status,
-        @JsonProperty("error") Map<String, String> error) {
-        this.status = status;
-        this.error = error;
-    }
-
-    public String getStatus() {
-        return status;
-    }
-
-    public Map<String, String> getError() {
-        return error;
-    }
-}

http://git-wip-us.apache.org/repos/asf/camel/blob/109da7c9/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowHelper.java
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowHelper.java b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowHelper.java
deleted file mode 100644
index 2d9b70e..0000000
--- a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowHelper.java
+++ /dev/null
@@ -1,95 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.camel.component.servicenow;
-
-import java.util.List;
-import java.util.Map;
-import java.util.Optional;
-import java.util.function.BiConsumer;
-import javax.ws.rs.core.HttpHeaders;
-import javax.ws.rs.core.Response;
-
-import org.apache.camel.util.StringHelper;
-import org.apache.camel.util.URISupport;
-
-public final class ServiceNowHelper {
-    private ServiceNowHelper() {
-    }
-
-    public static void findOffsets(Response response, BiConsumer<String, Object> consumer) throws Exception {
-        List<String> links = response.getStringHeaders().get(HttpHeaders.LINK);
-        if (links != null) {
-            for (String link : links) {
-                String[] parts = link.split(";");
-                if (parts.length != 2) {
-                    continue;
-                }
-
-                // Sanitize parts
-                String uri = StringHelper.between(parts[0], "<", ">");
-                String rel = StringHelper.removeQuotes(StringHelper.after(parts[1], "="));
-
-                Map<String, Object> query = URISupport.parseQuery(uri);
-                Object offset = query.get(ServiceNowParams.SYSPARM_OFFSET.getId());
-
-                if (offset != null) {
-                    switch (rel) {
-                    case ServiceNowConstants.LINK_FIRST:
-                        consumer.accept(ServiceNowConstants.OFFSET_FIRST, offset);
-                        break;
-                    case ServiceNowConstants.LINK_LAST:
-                        consumer.accept(ServiceNowConstants.OFFSET_LAST, offset);
-                        break;
-                    case ServiceNowConstants.LINK_NEXT:
-                        consumer.accept(ServiceNowConstants.OFFSET_NEXT, offset);
-                        break;
-                    case ServiceNowConstants.LINK_PREV:
-                        consumer.accept(ServiceNowConstants.OFFSET_PREV, offset);
-                        break;
-                    default:
-                        break;
-                    }
-                }
-            }
-        }
-    }
-
-    public static Optional<String> findOffset(Response response, String type) throws Exception {
-        List<String> links = response.getStringHeaders().get(HttpHeaders.LINK);
-        if (links != null) {
-            for (String link : links) {
-                String[] parts = link.split(";");
-                if (parts.length != 2) {
-                    continue;
-                }
-
-                // Sanitize parts
-                String uri = StringHelper.between(parts[0], "<", ">");
-                String rel = StringHelper.removeQuotes(StringHelper.after(parts[1], "="));
-
-                Map<String, Object> query = URISupport.parseQuery(uri);
-                Object offset = query.get(ServiceNowParams.SYSPARM_OFFSET.getId());
-
-                if (offset != null && type.equals(rel)) {
-                    return Optional.of(offset.toString());
-                }
-            }
-        }
-
-        return Optional.empty();
-    }
-}

http://git-wip-us.apache.org/repos/asf/camel/blob/109da7c9/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowMetaDataExtension.java
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowMetaDataExtension.java b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowMetaDataExtension.java
deleted file mode 100644
index f7e2df8..0000000
--- a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowMetaDataExtension.java
+++ /dev/null
@@ -1,457 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.camel.component.servicenow;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
-import java.util.Optional;
-import java.util.Stack;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentMap;
-import java.util.function.Consumer;
-import java.util.regex.Pattern;
-import java.util.stream.Stream;
-import javax.ws.rs.HttpMethod;
-import javax.ws.rs.core.HttpHeaders;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.Response;
-
-import com.fasterxml.jackson.core.JsonProcessingException;
-import com.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.node.ArrayNode;
-import com.fasterxml.jackson.databind.node.ObjectNode;
-import org.apache.camel.RuntimeCamelException;
-import org.apache.camel.component.extension.MetaDataExtension;
-import org.apache.camel.component.extension.metadata.AbstractMetaDataExtension;
-import org.apache.camel.component.extension.metadata.MetaDataBuilder;
-import org.apache.camel.component.servicenow.model.DictionaryEntry;
-import org.apache.camel.util.IntrospectionSupport;
-import org.apache.camel.util.ObjectHelper;
-import org.apache.camel.util.StringHelper;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-final class ServiceNowMetaDataExtension extends AbstractMetaDataExtension {
-    private static final Logger LOGGER = LoggerFactory.getLogger(ServiceNowMetaDataExtension.class);
-    private final ConcurrentMap<String, String> properties;
-
-    ServiceNowMetaDataExtension() {
-        this.properties = new ConcurrentHashMap<>();
-    }
-
-    @Override
-    public Optional<MetaDataExtension.MetaData> meta(Map<String, Object> parameters) {
-        try {
-            final MetaContext context = new MetaContext(parameters);
-
-            if (!ObjectHelper.equalIgnoreCase(context.getObjectType(), "table")) {
-                throw new UnsupportedOperationException("Unsupported object type <" + context.getObjectType() + ">");
-            }
-
-            return tableMeta(context);
-
-        } catch (UnsupportedOperationException e) {
-            throw e;
-        } catch (Exception e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-    private Optional<MetaDataExtension.MetaData> tableMeta(MetaContext context) {
-        try {
-            final List<String> names = getObjectHierarchy(context);
-            final ObjectNode root = context.getConfiguration().getMapper().createObjectNode();
-
-            if (names.isEmpty()) {
-                return Optional.empty();
-            }
-
-            loadProperties(context);
-            registerDefinitions(context, root);
-
-            root.putObject("properties");
-            root.put("$schema", "http://json-schema.org/schema#");
-            root.put("id", "http://camel.apache.org/schemas/servicenow/" + context.getObjectName() + ".json");
-            root.put("type", "object");
-            root.put("additionalProperties", false);
-            root.putArray("required");
-
-            for (String name : names) {
-                context.getStack().push(name);
-
-                LOGGER.debug("Load dictionary <{}>", context.getStack());
-                loadDictionary(context, name, root);
-                context.getStack().pop();
-            }
-
-            return Optional.of(
-                MetaDataBuilder.on(getCamelContext())
-                    .withAttribute(MetaData.CONTENT_TYPE, "application/schema+json")
-                    .withAttribute(MetaData.JAVA_TYPE, JsonNode.class)
-                    .withPayload(root)
-                    .build()
-            );
-        } catch (Exception e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-    // ********************************
-    // Properties
-    // ********************************
-
-    private synchronized void loadProperties(MetaContext context) {
-        if (!properties.isEmpty()) {
-            return;
-        }
-
-        try {
-            String offset = "0";
-
-            while (true) {
-                Response response = context.getClient().reset()
-                    .types(MediaType.APPLICATION_JSON_TYPE)
-                    .path("now")
-                    .path(context.getConfiguration().getApiVersion())
-                    .path("table")
-                    .path("sys_properties")
-                    .query("sysparm_exclude_reference_link", "true")
-                    .query("sysparm_fields", "name%2Cvalue")
-                    .query("sysparm_offset", offset)
-                    .query("sysparm_query", "name=glide.sys.date_format^ORname=glide.sys.time_format")
-                    .invoke(HttpMethod.GET);
-
-                findResultNode(response).ifPresent(node -> processResult(node, n -> {
-                    if (n.hasNonNull("name") && n.hasNonNull("value")) {
-                        properties.put(
-                            n.findValue("name").asText(),
-                            n.findValue("value").asText()
-                        );
-                    }
-                }));
-
-                Optional<String> next = ServiceNowHelper.findOffset(response, ServiceNowConstants.LINK_NEXT);
-                if (next.isPresent()) {
-                    offset = next.get();
-                } else {
-                    break;
-                }
-            }
-        } catch (Exception e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-    // ********************************
-    // Definitions
-    // ********************************
-
-    private void registerDefinitions(MetaContext context, ObjectNode root) {
-        final ObjectNode definitions = root.putObject("definitions");
-
-        // Global Unique ID
-        definitions.putObject("guid")
-            .put("type", "string")
-            .put("pattern", "^[a-fA-F0-9]{32}");
-
-        // Date/Time
-        String dateFormat = properties.getOrDefault("glide.sys.date_format", "yyyy-MM-dd");
-        String timeFormat = properties.getOrDefault("glide.sys.time_format", "HH:mm:ss");
-
-        definitions.putObject("date")
-            .put("type", "string")
-            .put("format", dateFormat);
-        definitions.putObject("time")
-            .put("type", "string")
-            .put("format", timeFormat);
-        definitions.putObject("date-time")
-            .put("type", "string")
-            .put("format", dateFormat + " " + timeFormat);
-    }
-
-    // ********************************
-    // Dictionary
-    // ********************************
-
-    private void loadDictionary(MetaContext context, String name, ObjectNode root) throws Exception {
-        String offset = "0";
-
-        while (true) {
-            Response response = context.getClient().reset()
-                .types(MediaType.APPLICATION_JSON_TYPE)
-                .path("now")
-                .path(context.getConfiguration().getApiVersion())
-                .path("table")
-                .path("sys_dictionary")
-                .query("sysparm_display_value", "false")
-                .queryF("sysparm_query", "name=%s", name)
-                .query("sysparm_offset", offset)
-                .invoke(HttpMethod.GET);
-
-            findResultNode(response).ifPresent(node -> processResult(node, n -> {
-                processDictionaryNode(context, root, n);
-            }));
-
-            Optional<String> next = ServiceNowHelper.findOffset(response, ServiceNowConstants.LINK_NEXT);
-            if (next.isPresent()) {
-                offset = next.get();
-            } else {
-                break;
-            }
-        }
-    }
-
-    private void processDictionaryNode(MetaContext context, ObjectNode root, JsonNode node) {
-        if (node.hasNonNull("element")) {
-            final String id = node.get("element").asText();
-
-            if (ObjectHelper.isNotEmpty(id)) {
-                String parent = context.getStack().peek();
-                String includeKey = "object." + parent + ".fields";
-                String fields = (String)context.getParameters().get(includeKey);
-
-                boolean included = false;
-
-                if (ObjectHelper.isNotEmpty(fields)) {
-                    if (Stream.of(fields.split(",")).map(StringHelper::trimToNull).filter(Objects::nonNull).map(Pattern::compile).anyMatch(p -> p.matcher(id).matches())) {
-                        included = true;
-                    }
-                    if (Stream.of(fields.split(",")).map(StringHelper::trimToNull).filter(Objects::nonNull).anyMatch(id::equalsIgnoreCase)) {
-                        included = true;
-                    }
-                } else {
-                    included = !context.getParameters().containsKey(includeKey);
-                }
-
-                if (!included) {
-                    return;
-                }
-
-                context.getStack().push(id);
-                LOGGER.debug("Load dictionary element <{}>", context.getStack());
-
-                try {
-                    final DictionaryEntry entry = context.getConfiguration().getMapper().treeToValue(node, DictionaryEntry.class);
-                    final ObjectNode property = ((ObjectNode)root.get("properties")).putObject(id);
-
-                    // Add custom fields for code generation, json schema
-                    // validators are not supposed to use this extensions.
-                    final ObjectNode servicenow = property.putObject("servicenow");
-
-                    // the internal type
-                    servicenow.put("internal_type", entry.getInternalType().getValue());
-
-                    switch (entry.getInternalType().getValue()) {
-                    case "integer":
-                        property.put("type", "number");
-                        break;
-                    case "boolean":
-                        property.put("type", "boolean");
-                        break;
-                    case "guid":
-                    case "GUID":
-                        property.put("$ref", "#/definitions/guid");
-                        break;
-                    case "glide_date":
-                        property.put("$ref", "#/definitions/date");
-                        break;
-                    case "due_date":
-                    case "glide_date_time":
-                    case "glide_time":
-                    case "glide_duration":
-                        property.put("$ref", "#/definitions/date-time");
-                        break;
-                    case "reference":
-                        property.put("$ref", "#/definitions/guid");
-
-                        if (entry.getReference().getValue() != null) {
-                            // the referenced object type
-                            servicenow.put("sys_db_object", entry.getReference().getValue());
-                        }
-
-                        break;
-                    default:
-                        property.put("type", "string");
-
-                        if (entry.getMaxLength() != null) {
-                            property.put("maxLength", entry.getMaxLength());
-                        }
-                        break;
-                    }
-
-                    if (entry.isMandatory()) {
-                        ArrayNode required = (ArrayNode)root.get("required");
-                        if (required == null) {
-                            required = root.putArray("required");
-                        }
-
-                        required.add(id);
-                    }
-
-                } catch (JsonProcessingException e) {
-                    throw new RuntimeCamelException(e);
-                } finally {
-
-                    context.getStack().pop();
-                }
-            }
-        }
-    }
-
-    // *************************************
-    // Helpers
-    // *************************************
-
-    private List<String> getObjectHierarchy(MetaContext context) throws Exception {
-        List<String> hierarchy = new ArrayList<>();
-        String query = String.format("name=%s", context.getObjectName());
-
-        while (true) {
-            Optional<JsonNode> response = context.getClient().reset()
-                .types(MediaType.APPLICATION_JSON_TYPE)
-                .path("now")
-                .path(context.getConfiguration().getApiVersion())
-                .path("table")
-                .path("sys_db_object")
-                .query("sysparm_exclude_reference_link", "true")
-                .query("sysparm_fields", "name%2Csuper_class")
-                .query("sysparm_query", query)
-                .trasform(HttpMethod.GET, this::findResultNode);
-
-            if (response.isPresent()) {
-                JsonNode node = response.get();
-                JsonNode nameNode = node.findValue("name");
-                JsonNode classNode = node.findValue("super_class");
-
-                if (nameNode != null && classNode != null) {
-                    query = String.format("sys_id=%s", classNode.textValue());
-                    hierarchy.add(0, nameNode.textValue());
-                } else {
-                    break;
-                }
-            } else {
-                break;
-            }
-        }
-
-        return hierarchy;
-    }
-
-    private void processResult(JsonNode node, Consumer<JsonNode> consumer) {
-        if (node.isArray()) {
-            Iterator<JsonNode> it = node.elements();
-            while (it.hasNext()) {
-                consumer.accept(it.next());
-            }
-        } else {
-            consumer.accept(node);
-        }
-    }
-
-    private Optional<JsonNode> findResultNode(Response response) {
-        if (ObjectHelper.isNotEmpty(response.getHeaderString(HttpHeaders.CONTENT_TYPE))) {
-            JsonNode root = response.readEntity(JsonNode.class);
-            if (root != null) {
-                Iterator<Map.Entry<String, JsonNode>> fields = root.fields();
-                while (fields.hasNext()) {
-                    final Map.Entry<String, JsonNode> entry = fields.next();
-                    final String key = entry.getKey();
-                    final JsonNode node = entry.getValue();
-
-                    if (ObjectHelper.equal("result", key, true)) {
-                        return Optional.of(node);
-                    }
-                }
-            }
-        }
-
-        return Optional.empty();
-    }
-
-    // *********************************
-    // Context class
-    // *********************************
-
-    private final class MetaContext {
-        private final Map<String, Object> parameters;
-        private final ServiceNowConfiguration configuration;
-        private final ServiceNowClient client;
-        private final String instanceName;
-        private final String objectName;
-        private final String objectType;
-        private final Stack<String> stack;
-
-        MetaContext(Map<String, Object> parameters) throws Exception {
-            this.parameters = parameters;
-            this.configuration = getComponent(ServiceNowComponent.class).getConfiguration().copy();
-            this.stack = new Stack<>();
-
-            IntrospectionSupport.setProperties(configuration, new HashMap<>(parameters));
-
-            this.instanceName = (String)parameters.getOrDefault("instanceName", getComponent(ServiceNowComponent.class).getInstanceName());
-            this.objectType = (String)parameters.getOrDefault("objectType", "table");
-            this.objectName = (String)parameters.getOrDefault("objectName", configuration.getTable());
-
-            ObjectHelper.notNull(instanceName, "instanceName");
-            ObjectHelper.notNull(objectName, "objectName");
-            ObjectHelper.notNull(objectType, "objectType");
-
-            // 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));
-            }
-
-            this.client = new ServiceNowClient(getCamelContext(), configuration);
-        }
-
-        public Map<String, Object> getParameters() {
-            return parameters;
-        }
-
-        public ServiceNowConfiguration getConfiguration() {
-            return configuration;
-        }
-
-        public ServiceNowClient getClient() {
-            return client;
-        }
-
-        public String getInstanceName() {
-            return instanceName;
-        }
-
-        public String getObjectType() {
-            return objectType;
-        }
-
-        public String getObjectName() {
-            return objectName;
-        }
-
-        public Stack<String> getStack() {
-            return stack;
-        }
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/camel/blob/109da7c9/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowParam.java
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowParam.java b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowParam.java
deleted file mode 100644
index 5353753..0000000
--- a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowParam.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.camel.component.servicenow;
-
-import org.apache.camel.Message;
-
-public interface ServiceNowParam {
-    String getId();
-    String getHeader();
-    Class<?> getType();
-    Object getDefaultValue(ServiceNowConfiguration configuration);
-    Object getHeaderValue(Message message);
-    Object getHeaderValue(Message message, ServiceNowConfiguration configuration);
-}

http://git-wip-us.apache.org/repos/asf/camel/blob/109da7c9/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowParams.java
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowParams.java b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowParams.java
deleted file mode 100644
index 75f16f9..0000000
--- a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowParams.java
+++ /dev/null
@@ -1,123 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.camel.component.servicenow;
-
-import java.util.function.Function;
-
-import org.apache.camel.Message;
-import org.apache.camel.util.ObjectHelper;
-
-public enum ServiceNowParams implements ServiceNowParam {
-    PARAM_SYS_ID("sys_id", "CamelServiceNowSysId", String.class),
-    PARAM_USER_SYS_ID("user_sysid", "CamelServiceNowUserSysId", String.class),
-    PARAM_USER_ID("user_id", "CamelServiceNowUserId", String.class),
-    PARAM_CART_ITEM_ID("cart_item_id", "CamelServiceNowCartItemId", String.class),
-    PARAM_FILE_NAME("file_name", "CamelServiceNowFileName", String.class),
-    PARAM_TABLE_NAME("table_name", "CamelServiceNowTable", String.class),
-    PARAM_TABLE_SYS_ID("table_sys_id", "CamelServiceNowTableSysId", String.class),
-    PARAM_ENCRYPTION_CONTEXT("encryption_context", "CamelServiceNowEncryptionContext", String.class),
-    SYSPARM_CATEGORY("sysparm_category", "CamelServiceNowCategory", String.class),
-    SYSPARM_TYPE("sysparm_type", "CamelServiceNowType", String.class),
-    SYSPARM_CATALOG("sysparm_catalog", "CamelServiceNowCatalog", String.class),
-    SYSPARM_QUERY("sysparm_query", "CamelServiceNowQuery", String.class),
-    SYSPARM_DISPLAY_VALUE("sysparm_display_value", "CamelServiceNowDisplayValue", String.class, ServiceNowConfiguration::getDisplayValue),
-    SYSPARM_INPUT_DISPLAY_VALUE("sysparm_input_display_value", "CamelServiceNowInputDisplayValue", Boolean.class, ServiceNowConfiguration::getInputDisplayValue),
-    SYSPARM_EXCLUDE_REFERENCE_LINK("sysparm_exclude_reference_link", "CamelServiceNowExcludeReferenceLink", Boolean.class, ServiceNowConfiguration::getExcludeReferenceLink),
-    SYSPARM_FIELDS("sysparm_fields", "CamelServiceNowFields", String.class),
-    SYSPARM_LIMIT("sysparm_limit", "CamelServiceNowLimit", Integer.class),
-    SYSPARM_TEXT("sysparm_text", "CamelServiceNowText", String.class),
-    SYSPARM_OFFSET("sysparm_offset", "CamelServiceNowOffset", Integer.class),
-    SYSPARM_VIEW("sysparm_view", "CamelServiceNowView", String.class),
-    SYSPARM_SUPPRESS_AUTO_SYS_FIELD("sysparm_suppress_auto_sys_field", "CamelServiceNowSuppressAutoSysField", Boolean.class, ServiceNowConfiguration::getSuppressAutoSysField),
-    SYSPARM_SUPPRESS_PAGINATION_HEADER("sysparm_suppress_pagination_header", "CamelServiceNowSuppressPaginationHeader", Boolean.class, ServiceNowConfiguration::getSuppressPaginationHeader),
-    SYSPARM_MIN_FIELDS("sysparm_min_fields", "CamelServiceNowMinFields", String.class),
-    SYSPARM_MAX_FIELDS("sysparm_max_fields", "CamelServiceNowMaxFields", String.class),
-    SYSPARM_SUM_FIELDS("sysparm_sum_fields", "CamelServiceNowSumFields", String.class),
-    SYSPARM_AVG_FIELDS("sysparm_avg_fields", "CamelServiceNowAvgFields", String.class),
-    SYSPARM_COUNT("sysparm_count", "CamelServiceNowCount", Boolean.class),
-    SYSPARM_GROUP_BY("sysparm_group_by", "CamelServiceNowGroupBy", String.class),
-    SYSPARM_ORDER_BY("sysparm_order_by", "CamelServiceNowOrderBy", String.class),
-    SYSPARM_HAVING("sysparm_having", "CamelServiceNowHaving", String.class),
-    SYSPARM_UUID("sysparm_uuid", "CamelServiceNowUUID", String.class),
-    SYSPARM_BREAKDOWN("sysparm_breakdown", "CamelServiceNowBreakdown", String.class),
-    SYSPARM_INCLUDE_SCORES("sysparm_include_scores", "CamelServiceNowIncludeScores", Boolean.class, ServiceNowConfiguration::getIncludeScores),
-    SYSPARM_INCLUDE_SCORE_NOTES("sysparm_include_score_notes", "CamelServiceNowIncludeScoreNotes", Boolean.class, ServiceNowConfiguration::getIncludeScoreNotes),
-    SYSPARM_INCLUDE_AGGREGATES("sysparm_include_aggregates", "CamelServiceNowIncludeAggregates", Boolean.class, ServiceNowConfiguration::getIncludeAggregates),
-    SYSPARM_INCLUDE_AVAILABLE_BREAKDOWNS("sysparm_include_available_breakdowns", "CamelServiceNowIncludeAvailableBreakdowns", Boolean.class, ServiceNowConfiguration::getIncludeAvailableBreakdowns),
-    SYSPARM_INCLUDE_AVAILABLE_AGGREGATES("sysparm_include_available_aggregates", "CamelServiceNowIncludeAvailableAggregates", Boolean.class, ServiceNowConfiguration::getIncludeAvailableAggregates),
-    SYSPARM_FAVORITES("sysparm_favorites", "CamelServiceNowFavorites", Boolean.class, ServiceNowConfiguration::getFavorites),
-    SYSPARM_KEY("sysparm_key", "CamelServiceNowKey", Boolean.class, ServiceNowConfiguration::getKey),
-    SYSPARM_TARGET("sysparm_target", "CamelServiceNowTarget", Boolean.class, ServiceNowConfiguration::getTarget),
-    SYSPARM_DISPLAY("sysparm_display", "CamelServiceNowDisplay", String.class, ServiceNowConfiguration::getDisplay),
-    SYSPARM_PER_PAGE("sysparm_per_page", "CamelServiceNowPerPage", Integer.class, ServiceNowConfiguration::getPerPage),
-    SYSPARM_SORT_BY("sysparm_sortby", "CamelServiceNowSortBy", String.class, ServiceNowConfiguration::getSortBy),
-    SYSPARM_SORT_DIR("sysparm_sortdir", "CamelServiceNowSortDir", String.class, ServiceNowConfiguration::getSortDir),
-    SYSPARM_CONTAINS("sysparm_contains", "CamelServiceNowContains", String.class),
-    SYSPARM_TAGS("sysparm_tags", "CamelServiceNowTags", String.class),
-    SYSPARM_PAGE("sysparm_page", "CamelServiceNowPage", String.class),
-    SYSPARM_ELEMENTS_FILTER("sysparm_elements_filter", "CamelServiceNowElementsFilter", String.class),
-    SYSPARM_BREAKDOWN_RELATION("sysparm_breakdown_relation", "CamelServiceNowBreakdownRelation", String.class),
-    SYSPARM_DATA_SOURCE("sysparm_data_source", "CamelServiceNowDataSource", String.class),
-    SYSPARM_TOP_LEVEL_ONLY("sysparm_top_level_only", "CamelServiceNowTopLevelOnly", Boolean.class, ServiceNowConfiguration::getTopLevelOnly);
-
-    private final String id;
-    private final String header;
-    private final Class<?> type;
-    private final Function<ServiceNowConfiguration, ?> defaultValueSupplier;
-
-    ServiceNowParams(String id, String header, Class<?> type) {
-        this(id, header, type, null);
-    }
-
-    ServiceNowParams(String id, String header, Class<?> type, Function<ServiceNowConfiguration, ?> defaultValueSupplier) {
-        ObjectHelper.notNull(id, "ServiceNowSysParam (id)");
-        ObjectHelper.notNull(header, "ServiceNowSysParam (header)");
-        ObjectHelper.notNull(type, "ServiceNowSysParam (type)");
-
-        this.id = id;
-        this.header = header.startsWith(ServiceNowConstants.CAMEL_HEADER_PREFIX)
-            ? header
-            : ServiceNowConstants.CAMEL_HEADER_PREFIX + ObjectHelper.capitalize(header);
-
-        this.type = type;
-        this.defaultValueSupplier = defaultValueSupplier;
-    }
-
-    public String getId() {
-        return id;
-    }
-
-    public String getHeader() {
-        return header;
-    }
-
-    public Class<?> getType() {
-        return type;
-    }
-
-    public Object getDefaultValue(ServiceNowConfiguration configuration) {
-        return defaultValueSupplier != null ? defaultValueSupplier.apply(configuration) : null;
-    }
-
-    public Object getHeaderValue(Message message) {
-        return message.getHeader(header, type);
-    }
-
-    public Object getHeaderValue(Message message, ServiceNowConfiguration configuration) {
-        return message.getHeader(header, getDefaultValue(configuration), type);
-    }
-}

http://git-wip-us.apache.org/repos/asf/camel/blob/109da7c9/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowProducer.java
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowProducer.java b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowProducer.java
deleted file mode 100644
index 67e08bb..0000000
--- a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowProducer.java
+++ /dev/null
@@ -1,23 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.camel.component.servicenow;
-
-import org.apache.camel.Producer;
-
-public interface ServiceNowProducer extends Producer {
-    ServiceNowRelease getRelease();
-}

http://git-wip-us.apache.org/repos/asf/camel/blob/109da7c9/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowProducerSupplier.java
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowProducerSupplier.java b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowProducerSupplier.java
deleted file mode 100644
index d339417..0000000
--- a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowProducerSupplier.java
+++ /dev/null
@@ -1,22 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.camel.component.servicenow;
-
-public interface ServiceNowProducerSupplier {
-    ServiceNowProducer get(ServiceNowEndpoint endpoint) throws Exception;
-}

http://git-wip-us.apache.org/repos/asf/camel/blob/109da7c9/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowRelease.java
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowRelease.java b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowRelease.java
deleted file mode 100644
index d546215..0000000
--- a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowRelease.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.camel.component.servicenow;
-
-import org.apache.camel.component.servicenow.releases.fuji.FujiServiceNowProducer;
-import org.apache.camel.component.servicenow.releases.helsinki.HelsinkiServiceNowProducer;
-
-public enum ServiceNowRelease implements ServiceNowProducerSupplier {
-    FUJI {
-        @Override
-        public ServiceNowProducer get(ServiceNowEndpoint endpoint) throws Exception {
-            return new FujiServiceNowProducer(endpoint);
-        }
-    },
-    GENEVA {
-        @Override
-        public ServiceNowProducer get(ServiceNowEndpoint endpoint) throws Exception {
-            return null;
-        }
-    },
-    HELSINKI {
-        @Override
-        public ServiceNowProducer get(ServiceNowEndpoint endpoint) throws Exception {
-            return new HelsinkiServiceNowProducer(endpoint);
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/camel/blob/109da7c9/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/annotations/ServiceNowSysParm.java
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/annotations/ServiceNowSysParm.java b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/annotations/ServiceNowSysParm.java
deleted file mode 100644
index 361e741..0000000
--- a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/annotations/ServiceNowSysParm.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.camel.component.servicenow.annotations;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Repeatable;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-@Target({ElementType.TYPE})
-@Retention(RetentionPolicy.RUNTIME)
-@Repeatable(ServiceNowSysParms.class)
-public @interface ServiceNowSysParm {
-    String name();
-
-    String value();
-}

http://git-wip-us.apache.org/repos/asf/camel/blob/109da7c9/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/annotations/ServiceNowSysParms.java
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/annotations/ServiceNowSysParms.java b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/annotations/ServiceNowSysParms.java
deleted file mode 100644
index 236ba8b..0000000
--- a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/annotations/ServiceNowSysParms.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.camel.component.servicenow.annotations;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-@Target({ElementType.TYPE})
-@Retention(RetentionPolicy.RUNTIME)
-public @interface ServiceNowSysParms {
-    ServiceNowSysParm[] value();
-}

http://git-wip-us.apache.org/repos/asf/camel/blob/109da7c9/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/auth/AuthenticationRequestFilter.java
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/auth/AuthenticationRequestFilter.java b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/auth/AuthenticationRequestFilter.java
deleted file mode 100644
index 4689455..0000000
--- a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/auth/AuthenticationRequestFilter.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.camel.component.servicenow.auth;
-
-import java.io.IOException;
-import java.nio.charset.StandardCharsets;
-import java.util.Base64;
-import javax.annotation.Priority;
-import javax.ws.rs.Priorities;
-import javax.ws.rs.client.ClientRequestContext;
-import javax.ws.rs.client.ClientRequestFilter;
-import javax.ws.rs.core.HttpHeaders;
-import javax.ws.rs.ext.Provider;
-
-import org.apache.camel.component.servicenow.ServiceNowConfiguration;
-
-
-@Provider
-@Priority(Priorities.AUTHENTICATION)
-public final class AuthenticationRequestFilter implements ClientRequestFilter {
-    private final OAuthToken authToken;
-    private final String authString;
-
-    public AuthenticationRequestFilter(ServiceNowConfiguration conf) throws IOException {
-        this.authToken = conf.hasOAuthAuthentication() ? new OAuthToken(conf) : null;
-        this.authString = conf.hasBasicAuthentication() ? getBasicAuthenticationString(conf) : null;
-    }
-
-    @Override
-    public void filter(ClientRequestContext requestContext) throws IOException {
-        if (authToken != null) {
-            requestContext.getHeaders().add(HttpHeaders.AUTHORIZATION, authToken.getAuthString());
-        } else if (authString != null) {
-            requestContext.getHeaders().add(HttpHeaders.AUTHORIZATION, authString);
-        }
-    }
-
-    private static String getBasicAuthenticationString(ServiceNowConfiguration conf) {
-        String userAndPassword = conf.getUserName() + ":" + conf.getPassword();
-        return "Basic " + Base64.getEncoder().encodeToString(userAndPassword.getBytes(StandardCharsets.UTF_8));
-    }
-}

http://git-wip-us.apache.org/repos/asf/camel/blob/109da7c9/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/auth/OAuthToken.java
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/auth/OAuthToken.java b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/auth/OAuthToken.java
deleted file mode 100644
index 880cf7f..0000000
--- a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/auth/OAuthToken.java
+++ /dev/null
@@ -1,107 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.camel.component.servicenow.auth;
-
-import java.util.concurrent.TimeUnit;
-
-import org.apache.camel.component.servicenow.ServiceNowConfiguration;
-import org.apache.cxf.jaxrs.client.WebClient;
-import org.apache.cxf.rs.security.oauth2.client.Consumer;
-import org.apache.cxf.rs.security.oauth2.client.OAuthClientUtils;
-import org.apache.cxf.rs.security.oauth2.common.ClientAccessToken;
-import org.apache.cxf.rs.security.oauth2.grants.owner.ResourceOwnerGrant;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class OAuthToken {
-    private static final Logger LOGGER = LoggerFactory.getLogger(OAuthToken.class);
-
-    private final ServiceNowConfiguration configuration;
-    private ClientAccessToken token;
-    private String authString;
-    private long expireAt;
-
-    public OAuthToken(ServiceNowConfiguration configuration) {
-        this.configuration = configuration;
-        this.token = null;
-        this.authString = null;
-        this.expireAt = 0;
-    }
-
-    private synchronized void getOrRefreshAccessToken() {
-        if (token == null) {
-            LOGGER.debug("Generate OAuth token");
-
-            token = OAuthClientUtils.getAccessToken(
-                WebClient.create(configuration.getOauthTokenUrl()),
-                new Consumer(
-                    configuration.getOauthClientId(),
-                    configuration.getOauthClientSecret()),
-                new ResourceOwnerGrant(
-                    configuration.getUserName(),
-                    configuration.getPassword()),
-                true
-            );
-
-            LOGGER.debug("OAuth token expires in {}s", token.getExpiresIn());
-
-            // Set expiration time related info in milliseconds
-            token.setIssuedAt(System.currentTimeMillis());
-            token.setExpiresIn(TimeUnit.MILLISECONDS.convert(token.getExpiresIn(), TimeUnit.SECONDS));
-
-            authString = token.toString();
-
-            if (token.getExpiresIn() > 0) {
-                expireAt = token.getIssuedAt() + token.getExpiresIn();
-            }
-        } else if (expireAt > 0 && System.currentTimeMillis() >= expireAt) {
-            LOGGER.debug("OAuth token is expired, refresh it");
-
-            token = OAuthClientUtils.refreshAccessToken(
-                WebClient.create(configuration.getOauthTokenUrl()),
-                new Consumer(
-                    configuration.getOauthClientId(),
-                    configuration.getOauthClientSecret()),
-                token,
-                null,
-                false
-            );
-
-            LOGGER.debug("Refreshed OAuth token expires in {}s", token.getExpiresIn());
-
-            // Set expiration time related info in milliseconds
-            token.setIssuedAt(System.currentTimeMillis());
-            token.setExpiresIn(TimeUnit.MILLISECONDS.convert(token.getExpiresIn(), TimeUnit.SECONDS));
-
-            authString = token.toString();
-
-            if (token.getExpiresIn() > 0) {
-                expireAt = token.getIssuedAt() + token.getExpiresIn();
-            }
-        }
-    }
-
-    public ClientAccessToken getClientAccess() {
-        getOrRefreshAccessToken();
-        return token;
-    }
-
-    public String getAuthString() {
-        getOrRefreshAccessToken();
-        return authString;
-    }
-}


[05/19] camel git commit: CAMEL-11550: Component extensions

Posted by lb...@apache.org.
http://git-wip-us.apache.org/repos/asf/camel/blob/42529399/camel-core/src/main/java/org/apache/camel/impl/verifier/OptionsGroup.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/impl/verifier/OptionsGroup.java b/camel-core/src/main/java/org/apache/camel/impl/verifier/OptionsGroup.java
deleted file mode 100644
index 1df4383..0000000
--- a/camel-core/src/main/java/org/apache/camel/impl/verifier/OptionsGroup.java
+++ /dev/null
@@ -1,142 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.camel.impl.verifier;
-
-import java.io.Serializable;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.HashSet;
-import java.util.LinkedHashSet;
-import java.util.Set;
-
-/**
- * A named group of options. A group of options requires that a set of
- * component parameters is given as a whole.
- *
- * <a id="#syntax">The option syntax can be
- * {@code "propertyName"} to denote required property and
- * {@code "!propertyName"} to denote required absence of a property.
- */
-public final class OptionsGroup implements Serializable {
-    private final String name;
-    private final Set<String> options;
-
-    /**
-     * Creates new named {@link OptionsGroup}.
-     *
-     * @param name the name of the group
-     */
-    public OptionsGroup(String name) {
-        this.name = name;
-        this.options = new HashSet<>();
-    }
-
-    /**
-     * Creates new named {@link OptionsGroup} with a set of option
-     * definitions.
-     *
-     * @param name the name of the group
-     * @param options names of properties in the syntax mentioned in {@link OptionsGroup}
-     */
-    public OptionsGroup(String name, Collection<String> options) {
-        this.name = name;
-        this.options = new LinkedHashSet<>(options);
-    }
-
-    /**
-     * Adds a option definition to this group. The option syntax can be
-     * {@code "propertyName"} to denote required property and
-     * {@code "!propertyName"} to denote required absence of a property.
-     *
-     * @param option definition.
-     */
-    public void addOption(String option) {
-        this.options.add(option);
-    }
-
-    /**
-     * The name of the group.
-     */
-    public String getName() {
-        return name;
-    }
-
-    /**
-     * The option definitions in this group.
-     */
-    public Set<String> getOptions() {
-        return this.options;
-    }
-
-    /**
-     * Adds a option definition to this group. The option syntax can be
-     * {@code "propertyName"} to denote required property and
-     * {@code "!propertyName"} to denote required absence of a property.
-     *
-     * @param option definition.
-     */
-    public OptionsGroup option(String option) {
-        this.options.add(option);
-        return this;
-    }
-
-    /**
-     * Adds a number of option definitions to this group. The option
-     * syntax can be {@code "propertyName"} to denote required
-     * property and {@code "!propertyName"} to denote required absence
-     * of a property.
-     *
-     * @param options options definition
-     */
-    public OptionsGroup options(String... options) {
-        for (String option : options) {
-            addOption(option);
-        }
-
-        return this;
-    }
-
-    /**
-     * Creates new group with the specified name.
-     *
-     * @param name the name of the group
-     */
-    public static OptionsGroup withName(String name) {
-        return new OptionsGroup(name);
-    }
-
-    /**
-     * Creates new group with the specified name of the given
-     * {@link Enum} name.
-     *
-     * @param enumItem the name of the group
-     * @see Enum#name()
-     */
-    public static OptionsGroup withName(Enum<?> enumItem) {
-        return new OptionsGroup(enumItem.name());
-    }
-
-    /**
-     * Creates new group with the specified name and option definitions.
-     *
-     * @param name the name of the group
-     * @param options options definition 
-     */
-    public static OptionsGroup withNameAndOptions(String name, String... options) {
-        return new OptionsGroup(name, Arrays.asList(options));
-    }
-}

http://git-wip-us.apache.org/repos/asf/camel/blob/42529399/camel-core/src/main/java/org/apache/camel/impl/verifier/ResultBuilder.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/impl/verifier/ResultBuilder.java b/camel-core/src/main/java/org/apache/camel/impl/verifier/ResultBuilder.java
deleted file mode 100644
index 5e8ddae..0000000
--- a/camel-core/src/main/java/org/apache/camel/impl/verifier/ResultBuilder.java
+++ /dev/null
@@ -1,143 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.camel.impl.verifier;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import java.util.Optional;
-import java.util.function.Supplier;
-
-import org.apache.camel.ComponentVerifier;
-import org.apache.camel.IllegalOptionException;
-import org.apache.camel.NoSuchOptionException;
-import org.apache.camel.util.function.ThrowingBiConsumer;
-import org.apache.camel.util.function.ThrowingConsumer;
-
-public final class ResultBuilder {
-    private Optional<ComponentVerifier.Scope> scope;
-    private Optional<ComponentVerifier.Result.Status> status;
-    private List<ComponentVerifier.VerificationError> verificationErrors;
-
-    public ResultBuilder() {
-        this.scope = Optional.empty();
-        this.status = scope.empty();
-    }
-
-    // **********************************
-    // Accessors
-    // **********************************
-
-    public ResultBuilder scope(ComponentVerifier.Scope scope) {
-        this.scope = Optional.of(scope);
-        return this;
-    }
-
-    public ResultBuilder status(ComponentVerifier.Result.Status status) {
-        this.status = Optional.of(status);
-        return this;
-    }
-
-    public ResultBuilder error(ComponentVerifier.VerificationError verificationError) {
-        if (this.verificationErrors == null) {
-            this.verificationErrors = new ArrayList<>();
-        }
-
-        this.verificationErrors.add(verificationError);
-        this.status = Optional.of(ComponentVerifier.Result.Status.ERROR);
-
-        return this;
-    }
-
-    public ResultBuilder error(Optional<ComponentVerifier.VerificationError> error) {
-        error.ifPresent(e -> error(e));
-        return this;
-    }
-
-    public ResultBuilder error(Supplier<Optional<ComponentVerifier.VerificationError>> supplier) {
-        return error(supplier.get());
-    }
-
-    public ResultBuilder error(ThrowingConsumer<ResultBuilder, Exception> consumer) {
-        try {
-            consumer.accept(this);
-        } catch (NoSuchOptionException e) {
-            error(ResultErrorBuilder.withMissingOption(e.getOptionName()).build());
-        } catch (IllegalOptionException e) {
-            error(ResultErrorBuilder.withIllegalOption(e.getOptionName(), e.getOptionValue()).build());
-        } catch (Exception e) {
-            error(ResultErrorBuilder.withException(e).build());
-        }
-
-        return this;
-    }
-
-    public <T> ResultBuilder error(T data, ThrowingBiConsumer<ResultBuilder, T, Exception> consumer) {
-        try {
-            consumer.accept(this, data);
-        } catch (NoSuchOptionException e) {
-            error(ResultErrorBuilder.withMissingOption(e.getOptionName()).build());
-        } catch (IllegalOptionException e) {
-            error(ResultErrorBuilder.withIllegalOption(e.getOptionName(), e.getOptionValue()).build());
-        } catch (Exception e) {
-            error(ResultErrorBuilder.withException(e).build());
-        }
-
-        return this;
-    }
-
-    public ResultBuilder errors(List<ComponentVerifier.VerificationError> verificationErrors) {
-        verificationErrors.forEach(this::error);
-        return this;
-    }
-
-    // **********************************
-    // Build
-    // **********************************
-
-    public ComponentVerifier.Result build() {
-        return new DefaultResult(
-            scope.orElse(ComponentVerifier.Scope.PARAMETERS),
-            status.orElse(ComponentVerifier.Result.Status.UNSUPPORTED),
-            verificationErrors != null ? Collections.unmodifiableList(verificationErrors) : Collections.emptyList()
-        );
-    }
-
-    // **********************************
-    // Helpers
-    // **********************************
-
-    public static ResultBuilder withStatus(ComponentVerifier.Result.Status status) {
-        return new ResultBuilder().status(status);
-    }
-
-    public static ResultBuilder withStatusAndScope(ComponentVerifier.Result.Status status, ComponentVerifier.Scope scope) {
-        return new ResultBuilder().status(status).scope(scope);
-    }
-
-    public static ResultBuilder withScope(ComponentVerifier.Scope scope) {
-        return new ResultBuilder().scope(scope);
-    }
-
-    public static ResultBuilder unsupported() {
-        return withStatusAndScope(ComponentVerifier.Result.Status.UNSUPPORTED, ComponentVerifier.Scope.PARAMETERS);
-    }
-
-    public static ResultBuilder unsupportedScope(ComponentVerifier.Scope scope) {
-        return withStatusAndScope(ComponentVerifier.Result.Status.UNSUPPORTED, scope);
-    }
-}

http://git-wip-us.apache.org/repos/asf/camel/blob/42529399/camel-core/src/main/java/org/apache/camel/impl/verifier/ResultErrorBuilder.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/impl/verifier/ResultErrorBuilder.java b/camel-core/src/main/java/org/apache/camel/impl/verifier/ResultErrorBuilder.java
deleted file mode 100644
index daadb48..0000000
--- a/camel-core/src/main/java/org/apache/camel/impl/verifier/ResultErrorBuilder.java
+++ /dev/null
@@ -1,213 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.camel.impl.verifier;
-
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Optional;
-import java.util.Set;
-import java.util.function.Supplier;
-
-import org.apache.camel.ComponentVerifier.VerificationError;
-import org.apache.camel.util.ObjectHelper;
-
-public final class ResultErrorBuilder {
-    private VerificationError.Code code;
-    private String description;
-    private Set<String> parameters;
-    private Map<VerificationError.Attribute, Object> attributes;
-
-    public ResultErrorBuilder() {
-    }
-
-    // **********************************
-    // Accessors
-    // **********************************
-
-    public ResultErrorBuilder code(VerificationError.Code code) {
-        this.code = code;
-        return this;
-    }
-
-    public ResultErrorBuilder code(String code) {
-        code(VerificationError.asCode(code));
-        return this;
-    }
-
-    public ResultErrorBuilder description(String description) {
-        this.description = description;
-        return this;
-    }
-
-    public ResultErrorBuilder parameterKey(String parameter) {
-        if (parameter != null) {
-            if (this.parameters == null) {
-                this.parameters = new HashSet<>();
-            }
-
-            this.parameters.add(parameter);
-        }
-        return this;
-    }
-
-    public ResultErrorBuilder parameterKeys(Collection<String> parameterList) {
-        if (parameterList != null) {
-            parameterList.forEach(this::parameterKey);
-        }
-
-        return this;
-    }
-
-    public ResultErrorBuilder detail(String key, Object value) {
-        detail(VerificationError.asAttribute(key), value);
-        return this;
-    }
-
-    public ResultErrorBuilder detail(VerificationError.Attribute key, Object value) {
-        if (value != null) {
-            if (this.attributes == null) {
-                this.attributes = new HashMap<>();
-            }
-
-            this.attributes.put(key, value);
-        }
-        return this;
-    }
-
-    public <T> ResultErrorBuilder detail(String key, Supplier<Optional<T>> supplier) {
-        detail(VerificationError.asAttribute(key), supplier);
-        return this;
-    }
-
-    public <T> ResultErrorBuilder detail(VerificationError.Attribute key, Supplier<Optional<T>> supplier) {
-        supplier.get().ifPresent(value -> detail(key, value));
-        return this;
-    }
-
-    public ResultErrorBuilder details(Map<VerificationError.Attribute, Object> details) {
-        for (Map.Entry<VerificationError.Attribute, Object> entry : details.entrySet()) {
-            detail(entry.getKey(), entry.getValue());
-        }
-
-        return this;
-    }
-
-    // **********************************
-    // Build
-    // **********************************
-
-    public VerificationError build() {
-        return new DefaultResultVerificationError(
-            code,
-            description,
-            parameters != null ? Collections.unmodifiableSet(parameters) : Collections.emptySet(),
-            attributes != null ? Collections.unmodifiableMap(attributes) : Collections.emptyMap()
-        );
-    }
-
-    // **********************************
-    // Helpers
-    // **********************************
-
-    public static ResultErrorBuilder fromError(VerificationError error) {
-        return new ResultErrorBuilder()
-            .code(error.getCode())
-            .description(error.getDescription())
-            .parameterKeys(error.getParameterKeys())
-            .details(error.getDetails());
-    }
-
-    public static ResultErrorBuilder withCode(VerificationError.Code code) {
-        return new ResultErrorBuilder().code(code);
-    }
-
-    public static ResultErrorBuilder withCode(String code) {
-        return new ResultErrorBuilder().code(code);
-    }
-
-    public static ResultErrorBuilder withHttpCode(int code) {
-        return withCode(convertHttpCodeToErrorCode(code))
-            .detail(VerificationError.HttpAttribute.HTTP_CODE, code);
-    }
-
-    public static ResultErrorBuilder withHttpCodeAndText(int code, String text) {
-        return withCodeAndDescription(convertHttpCodeToErrorCode(code), text)
-            .detail(VerificationError.HttpAttribute.HTTP_CODE, code)
-            .detail(VerificationError.HttpAttribute.HTTP_TEXT, text);
-    }
-
-    private static VerificationError.StandardCode convertHttpCodeToErrorCode(int code) {
-        return code >= 400 && code < 500 ? VerificationError.StandardCode.AUTHENTICATION : VerificationError.StandardCode.GENERIC;
-    }
-
-    public static ResultErrorBuilder withCodeAndDescription(VerificationError.Code code, String description) {
-        return new ResultErrorBuilder().code(code).description(description);
-    }
-
-    public static ResultErrorBuilder withUnsupportedScope(String scope) {
-        return new ResultErrorBuilder()
-            .code(VerificationError.StandardCode.UNSUPPORTED_SCOPE)
-            .description("Unsupported scope: " + scope);
-    }
-
-    public static ResultErrorBuilder withUnsupportedComponent(String component) {
-        return new ResultErrorBuilder()
-            .code(VerificationError.StandardCode.UNSUPPORTED_COMPONENT)
-            .description("Unsupported component: " + component);
-    }
-
-    public static ResultErrorBuilder withException(Exception exception) {
-        return new ResultErrorBuilder()
-            .code(VerificationError.StandardCode.EXCEPTION)
-            .description(exception.getMessage())
-            .detail(VerificationError.ExceptionAttribute.EXCEPTION_INSTANCE, exception)
-            .detail(VerificationError.ExceptionAttribute.EXCEPTION_CLASS, exception.getClass().getName());
-    }
-
-    public static ResultErrorBuilder withMissingOption(String optionName) {
-        return new ResultErrorBuilder()
-            .code(VerificationError.StandardCode.MISSING_PARAMETER)
-            .description(optionName + " should be set")
-            .parameterKey(optionName);
-    }
-
-    public static ResultErrorBuilder withUnknownOption(String optionName) {
-        return new ResultErrorBuilder()
-            .code(VerificationError.StandardCode.UNKNOWN_PARAMETER)
-            .description("Unknown option " + optionName)
-            .parameterKey(optionName);
-    }
-
-    public static ResultErrorBuilder withIllegalOption(String optionName) {
-        return new ResultErrorBuilder()
-            .code(VerificationError.StandardCode.ILLEGAL_PARAMETER)
-            .description("Illegal option " + optionName)
-            .parameterKey(optionName);
-    }
-
-    public static ResultErrorBuilder withIllegalOption(String optionName, String optionValue) {
-        return ObjectHelper.isNotEmpty(optionValue)
-            ? new ResultErrorBuilder()
-                .code(VerificationError.StandardCode.ILLEGAL_PARAMETER_VALUE)
-                .description(optionName + " has wrong value (" + optionValue + ")")
-                .parameterKey(optionName)
-            : withIllegalOption(optionName);
-    }
-}

http://git-wip-us.apache.org/repos/asf/camel/blob/42529399/camel-core/src/main/java/org/apache/camel/impl/verifier/ResultErrorHelper.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/impl/verifier/ResultErrorHelper.java b/camel-core/src/main/java/org/apache/camel/impl/verifier/ResultErrorHelper.java
deleted file mode 100644
index fb0dfc0..0000000
--- a/camel-core/src/main/java/org/apache/camel/impl/verifier/ResultErrorHelper.java
+++ /dev/null
@@ -1,164 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.camel.impl.verifier;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Optional;
-import java.util.Set;
-import java.util.TreeSet;
-import java.util.stream.Collectors;
-
-import org.apache.camel.ComponentVerifier.VerificationError;
-import org.apache.camel.util.ObjectHelper;
-
-/**
- * Helper that validates component parameters.
- */
-public final class ResultErrorHelper {
-
-    private ResultErrorHelper() {
-    }
-
-    // **********************************
-    // Helpers
-    // **********************************
-
-    /**
-     *
-     * @param parameterName the required option
-     * @param parameters the
-     * @return
-     */
-    public static Optional<VerificationError> requiresOption(String parameterName, Map<String, Object> parameters) {
-        if (ObjectHelper.isEmpty(parameters.get(parameterName))) {
-            return Optional.of(ResultErrorBuilder.withMissingOption(parameterName).build());
-        }
-
-        return Optional.empty();
-    }
-
-    /**
-     * Validates that the given parameters satisfy any grouped options
-     * ({@link OptionsGroup}). A parameter set is valid if it is
-     * present and required by least one of the groups.
-     *
-     * <p>As an example consider that there are two option groups that
-     * can be specified:
-     * <ul>
-     * <li>optionA: requires param1 and param2
-     * <li>optionB: requires param1 and param3
-     * </ul>
-     *
-     * Valid parameters are those that include param1 and either param2
-     * and/or param3.
-     *
-     * <p>Note the special syntax of {@link OptionsGroup#getOptions()}
-     * that can require an property ({@code "propertyName"}) or can
-     * forbid the presence of a property ({@code "!propertyName"}).
-     *
-     * <p>With that if in the example above if param2 is specified
-     * specifying param3 is not allowed, and vice versa option groups
-     * should be defined with options:
-     * <ul>
-     * <li>optionA: ["param1", "param2", "!param3"]
-     * <li>optionB: ["param1", "!param2", "param3"]
-     * </ul>
-     *
-     * @param parameters given parameters of a component
-     * @param groups groups of options
-     * @see OptionsGroup
-     */
-    public static List<VerificationError> requiresAny(Map<String, Object> parameters, OptionsGroup... groups) {
-        return requiresAny(parameters, Arrays.asList(groups));
-    }
-
-    /**
-     * Validates that the given parameters satisfy any grouped options
-     * ({@link OptionsGroup}). A parameter set is valid if it is
-     * present and required by least one of the groups.
-     *
-     * @param parameters given parameters of a component
-     * @param groups groups of options
-     * @see #requiresAny(Map, OptionsGroup...)
-     * @see OptionsGroup
-     */
-    public static List<VerificationError> requiresAny(Map<String, Object> parameters, Collection<OptionsGroup> groups) {
-        final List<VerificationError> verificationErrors = new ArrayList<>();
-        final Set<String> keys = new HashSet<>(parameters.keySet());
-
-        for (OptionsGroup group : groups) {
-            final Set<String> required = required(group.getOptions());
-            final Set<String> excluded = excluded(group.getOptions());
-
-            final ResultErrorBuilder builder = new ResultErrorBuilder()
-                .code(VerificationError.StandardCode.ILLEGAL_PARAMETER_GROUP_COMBINATION)
-                .detail(VerificationError.GroupAttribute.GROUP_NAME, group.getName())
-                .detail(VerificationError.GroupAttribute.GROUP_OPTIONS, String.join(",", parameters(group.getOptions())));
-
-            if (keys.containsAll(required)) {
-                // All the options of this group are found so we are good
-                final Set<String> shouldBeExcluded = new HashSet<>(keys);
-                shouldBeExcluded.retainAll(excluded);
-
-                if (shouldBeExcluded.isEmpty()) {
-                    // None of the excluded properties is present, also good
-                    return Collections.emptyList();
-                }
-
-                shouldBeExcluded.forEach(builder::parameterKey);
-                verificationErrors.add(builder.build());
-            } else {
-
-                for (String option : required) {
-                    if (!parameters.containsKey(option)) {
-                        builder.parameterKey(option);
-                    }
-                }
-
-                for (String option : excluded) {
-                    if (parameters.containsKey(option)) {
-                        builder.parameterKey(option);
-                    }
-                }
-
-                verificationErrors.add(builder.build());
-            }
-        }
-
-        return verificationErrors;
-    }
-
-    static Set<String> required(final Set<String> options) {
-        return options.stream().filter(o -> !o.startsWith("!")).collect(Collectors.toSet());
-    }
-
-    static Set<String> excluded(final Set<String> options) {
-        return options.stream().filter(o -> o.startsWith("!")).map(o -> o.substring(1)).collect(Collectors.toSet());
-    }
-
-    static Set<String> parameters(final Set<String> options) {
-        final Set<String> withoutExclusionMark = options.stream().map(o -> o.replaceFirst("!", "")).collect(Collectors.toSet());
-
-        return new TreeSet<String>(withoutExclusionMark);
-    }
-}

http://git-wip-us.apache.org/repos/asf/camel/blob/42529399/camel-core/src/main/java/org/apache/camel/management/mbean/ManagedComponent.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/management/mbean/ManagedComponent.java b/camel-core/src/main/java/org/apache/camel/management/mbean/ManagedComponent.java
index 78af22a..931690f 100644
--- a/camel-core/src/main/java/org/apache/camel/management/mbean/ManagedComponent.java
+++ b/camel-core/src/main/java/org/apache/camel/management/mbean/ManagedComponent.java
@@ -34,8 +34,8 @@ import org.apache.camel.api.management.ManagedInstance;
 import org.apache.camel.api.management.ManagedResource;
 import org.apache.camel.api.management.mbean.CamelOpenMBeanTypes;
 import org.apache.camel.api.management.mbean.ManagedComponentMBean;
-import org.apache.camel.impl.verifier.ResultBuilder;
-import org.apache.camel.impl.verifier.ResultErrorBuilder;
+import org.apache.camel.component.extension.verifier.ResultBuilder;
+import org.apache.camel.component.extension.verifier.ResultErrorBuilder;
 import org.apache.camel.spi.ManagementStrategy;
 import org.apache.camel.util.CastUtils;
 import org.apache.camel.util.JsonSchemaHelper;
@@ -158,7 +158,6 @@ public class ManagedComponent implements ManagedInstance, ManagedComponentMBean
             return ResultBuilder.withStatus(ComponentVerifier.Result.Status.UNSUPPORTED)
                 .error(ResultErrorBuilder.withUnsupportedScope(scope).build())
                 .build();
-
         }
     }
 }

http://git-wip-us.apache.org/repos/asf/camel/blob/42529399/camel-core/src/main/java/org/apache/camel/util/CamelContextHelper.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/util/CamelContextHelper.java b/camel-core/src/main/java/org/apache/camel/util/CamelContextHelper.java
index 1ee219c..c368d03 100644
--- a/camel-core/src/main/java/org/apache/camel/util/CamelContextHelper.java
+++ b/camel-core/src/main/java/org/apache/camel/util/CamelContextHelper.java
@@ -32,6 +32,7 @@ import java.util.StringTokenizer;
 import java.util.TreeMap;
 
 import org.apache.camel.CamelContext;
+import org.apache.camel.CamelContextAware;
 import org.apache.camel.Component;
 import org.apache.camel.Endpoint;
 import org.apache.camel.Exchange;
@@ -766,5 +767,4 @@ public final class CamelContextHelper {
             }
         }
     }
-
 }

http://git-wip-us.apache.org/repos/asf/camel/blob/42529399/camel-core/src/test/java/org/apache/camel/ComponentVerifierTest.java
----------------------------------------------------------------------
diff --git a/camel-core/src/test/java/org/apache/camel/ComponentVerifierTest.java b/camel-core/src/test/java/org/apache/camel/ComponentVerifierTest.java
deleted file mode 100644
index 2eb944c..0000000
--- a/camel-core/src/test/java/org/apache/camel/ComponentVerifierTest.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.camel;
-import junit.framework.TestCase;
-import org.apache.camel.ComponentVerifier.VerificationError;
-import org.apache.camel.impl.verifier.ResultErrorBuilder;
-import org.junit.Assert;
-
-public class ComponentVerifierTest extends TestCase {
-
-    public void testGetErrorDetails() {
-        VerificationError error = ResultErrorBuilder.withCodeAndDescription(VerificationError.asCode("test_code"), "test error desc")
-            .detail(VerificationError.asAttribute("test_attr_1"), "test_detail_1")
-            .detail(VerificationError.HttpAttribute.HTTP_CODE, "test_detail_2")
-            .build();
-
-        Assert.assertEquals("test_detail_1", error.getDetail(VerificationError.asAttribute("test_attr_1")));
-        Assert.assertEquals("test_detail_1", error.getDetail("test_attr_1"));
-        Assert.assertEquals("test_detail_2", error.getDetail(VerificationError.HttpAttribute.HTTP_CODE));
-        Assert.assertNull(error.getDetail(VerificationError.HttpAttribute.HTTP_TEXT));
-
-        Assert.assertNull(error.getDetail(VerificationError.asAttribute("test_attr_non_existant")));
-    }
-
-    public void testNullCode() {
-        try {
-            VerificationError.asCode(null);
-            fail("Code must not be null");
-        } catch (IllegalArgumentException exp) {
-            Assert.assertTrue(exp.getMessage().contains("null"));
-        }
-    }
-
-    public void testNullAttribute() {
-        try {
-            VerificationError.asAttribute(null);
-            fail("Attribute must not be null");
-        } catch (IllegalArgumentException exp) {
-            Assert.assertTrue(exp.getMessage().contains("null"));
-        }
-    }
-
-    public void testScopeFromString() {
-        Assert.assertEquals(ComponentVerifier.Scope.PARAMETERS, ComponentVerifier.Scope.fromString("PaRaMeTeRS"));
-
-        try {
-            ComponentVerifier.Scope.fromString("unknown");
-            fail();
-        } catch (IllegalArgumentException exp) {
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/camel/blob/42529399/camel-core/src/test/java/org/apache/camel/component/extension/verifier/ComponentVerifierTest.java
----------------------------------------------------------------------
diff --git a/camel-core/src/test/java/org/apache/camel/component/extension/verifier/ComponentVerifierTest.java b/camel-core/src/test/java/org/apache/camel/component/extension/verifier/ComponentVerifierTest.java
new file mode 100644
index 0000000..1111e67
--- /dev/null
+++ b/camel-core/src/test/java/org/apache/camel/component/extension/verifier/ComponentVerifierTest.java
@@ -0,0 +1,66 @@
+/**
+ * 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.extension.verifier;
+import junit.framework.TestCase;
+import org.apache.camel.ComponentVerifier;
+import org.apache.camel.component.extension.ComponentVerifierExtension.VerificationError;
+import org.junit.Assert;
+
+public class ComponentVerifierTest extends TestCase {
+
+    public void testGetErrorDetails() {
+        VerificationError error = ResultErrorBuilder.withCodeAndDescription(VerificationError.asCode("test_code"), "test error desc")
+            .detail(VerificationError.asAttribute("test_attr_1"), "test_detail_1")
+            .detail(VerificationError.HttpAttribute.HTTP_CODE, "test_detail_2")
+            .build();
+
+        Assert.assertEquals("test_detail_1", error.getDetail(VerificationError.asAttribute("test_attr_1")));
+        Assert.assertEquals("test_detail_1", error.getDetail("test_attr_1"));
+        Assert.assertEquals("test_detail_2", error.getDetail(VerificationError.HttpAttribute.HTTP_CODE));
+        Assert.assertNull(error.getDetail(VerificationError.HttpAttribute.HTTP_TEXT));
+
+        Assert.assertNull(error.getDetail(VerificationError.asAttribute("test_attr_non_existant")));
+    }
+
+    public void testNullCode() {
+        try {
+            VerificationError.asCode(null);
+            fail("Code must not be null");
+        } catch (IllegalArgumentException exp) {
+            Assert.assertTrue(exp.getMessage().contains("null"));
+        }
+    }
+
+    public void testNullAttribute() {
+        try {
+            VerificationError.asAttribute(null);
+            fail("Attribute must not be null");
+        } catch (IllegalArgumentException exp) {
+            Assert.assertTrue(exp.getMessage().contains("null"));
+        }
+    }
+
+    public void testScopeFromString() {
+        Assert.assertEquals(ComponentVerifier.Scope.PARAMETERS, ComponentVerifier.Scope.fromString("PaRaMeTeRS"));
+
+        try {
+            ComponentVerifier.Scope.fromString("unknown");
+            fail();
+        } catch (IllegalArgumentException exp) {
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/42529399/camel-core/src/test/java/org/apache/camel/component/rest/RestComponentVerifierExtensionTest.java
----------------------------------------------------------------------
diff --git a/camel-core/src/test/java/org/apache/camel/component/rest/RestComponentVerifierExtensionTest.java b/camel-core/src/test/java/org/apache/camel/component/rest/RestComponentVerifierExtensionTest.java
new file mode 100644
index 0000000..a5adc8c
--- /dev/null
+++ b/camel-core/src/test/java/org/apache/camel/component/rest/RestComponentVerifierExtensionTest.java
@@ -0,0 +1,141 @@
+/**
+ * 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.rest;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.Consumer;
+import org.apache.camel.ContextTestSupport;
+import org.apache.camel.Endpoint;
+import org.apache.camel.Processor;
+import org.apache.camel.Producer;
+import org.apache.camel.component.extension.ComponentVerifierExtension;
+import org.apache.camel.component.extension.verifier.ResultBuilder;
+import org.apache.camel.component.extension.verifier.ResultErrorHelper;
+import org.apache.camel.impl.DefaultComponent;
+import org.apache.camel.impl.JndiRegistry;
+import org.apache.camel.spi.RestConfiguration;
+import org.apache.camel.spi.RestConsumerFactory;
+import org.apache.camel.spi.RestProducerFactory;
+import org.junit.Assert;
+
+public class RestComponentVerifierExtensionTest extends ContextTestSupport {
+    @Override
+    protected JndiRegistry createRegistry() throws Exception {
+        JndiRegistry registry = super.createRegistry();
+        registry.bind("rest", new RestComponent());
+        registry.bind("rest-component", new MyComponent());
+        return registry;
+    }
+
+    public void testParameters() throws Exception {
+        RestComponent component = context.getComponent("rest", RestComponent.class);
+        RestComponentVerifierExtension verifier = component.getExtension(RestComponentVerifierExtension.class).orElseThrow(() -> new IllegalStateException());
+
+        Map<String, Object> parameters = new HashMap<>();
+        parameters.put("componentName", "rest-component");
+        parameters.put("host", "http://localhost:1234");
+        parameters.put("path", "verify");
+        parameters.put("method", "get");
+
+        // This parameter does not belong to the rest component and validation
+        // is delegated to the underlying component
+        parameters.put("authProxy", "http://localhost:8080");
+
+        RestComponentVerifierExtension.Result result = verifier.verify(RestComponentVerifierExtension.Scope.PARAMETERS, parameters);
+
+        Assert.assertEquals(RestComponentVerifierExtension.Result.Status.OK, result.getStatus());
+    }
+
+    public void testMissingParameters() throws Exception {
+        RestComponent component = context.getComponent("rest", RestComponent.class);
+        RestComponentVerifierExtension verifier = component.getExtension(RestComponentVerifierExtension.class).orElseThrow(() -> new IllegalStateException());
+
+        Map<String, Object> parameters = new HashMap<>();
+        parameters.put("componentName", "rest-component");
+        parameters.put("host", "http://localhost:" + 1234);
+        parameters.put("path", "verify");
+
+        // This parameter does not belong to the rest component and validation
+        // is delegated to the underlying component
+        parameters.put("authProxy", "http://localhost:8080");
+
+        RestComponentVerifierExtension.Result result = verifier.verify(RestComponentVerifierExtension.Scope.PARAMETERS, parameters);
+
+        Assert.assertEquals(RestComponentVerifierExtension.Result.Status.ERROR, result.getStatus());
+        Assert.assertEquals(1, result.getErrors().size());
+        Assert.assertEquals(RestComponentVerifierExtension.VerificationError.StandardCode.MISSING_PARAMETER, result.getErrors().get(0).getCode());
+        Assert.assertEquals(1, result.getErrors().get(0).getParameterKeys().size());
+        Assert.assertTrue(result.getErrors().get(0).getParameterKeys().contains("method"));
+    }
+
+    // ***************************************************
+    //
+    // ***************************************************
+
+    private final class MyComponent extends DefaultComponent implements RestProducerFactory, RestConsumerFactory {
+
+        public MyComponent() {
+            registerExtension(
+                new ComponentVerifierExtension() {
+                    @Override
+                    public Result verify(Scope scope, Map<String, Object> parameters) {
+                        return ResultBuilder.withStatusAndScope(RestComponentVerifierExtension.Result.Status.OK, scope)
+                            .error(ResultErrorHelper.requiresOption("authProxy", parameters))
+                            .build();
+                    }
+                }
+            );
+        }
+        @Override
+        protected Endpoint createEndpoint(String uri, String remaining, Map<String, Object> parameters) throws Exception {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public Producer createProducer(
+                CamelContext camelContext,
+                String host,
+                String verb,
+                String basePath,
+                String uriTemplate,
+                String queryParameters,
+                String consumes,
+                String produces,
+                Map<String, Object> parameters)
+                    throws Exception {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public Consumer createConsumer(
+                CamelContext camelContext,
+                Processor processor,
+                String verb,
+                String basePath,
+                String uriTemplate,
+                String consumes,
+                String produces,
+                RestConfiguration configuration,
+                Map<String, Object> parameters)
+                    throws Exception {
+            throw new UnsupportedOperationException();
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/42529399/camel-core/src/test/java/org/apache/camel/component/rest/RestComponentVerifierTest.java
----------------------------------------------------------------------
diff --git a/camel-core/src/test/java/org/apache/camel/component/rest/RestComponentVerifierTest.java b/camel-core/src/test/java/org/apache/camel/component/rest/RestComponentVerifierTest.java
index 73fb130..ca8851e 100644
--- a/camel-core/src/test/java/org/apache/camel/component/rest/RestComponentVerifierTest.java
+++ b/camel-core/src/test/java/org/apache/camel/component/rest/RestComponentVerifierTest.java
@@ -26,11 +26,11 @@ import org.apache.camel.ContextTestSupport;
 import org.apache.camel.Endpoint;
 import org.apache.camel.Processor;
 import org.apache.camel.Producer;
-import org.apache.camel.VerifiableComponent;
+import org.apache.camel.component.extension.ComponentVerifierExtension;
+import org.apache.camel.component.extension.verifier.ResultBuilder;
+import org.apache.camel.component.extension.verifier.ResultErrorHelper;
 import org.apache.camel.impl.DefaultComponent;
 import org.apache.camel.impl.JndiRegistry;
-import org.apache.camel.impl.verifier.ResultBuilder;
-import org.apache.camel.impl.verifier.ResultErrorHelper;
 import org.apache.camel.spi.RestConfiguration;
 import org.apache.camel.spi.RestConsumerFactory;
 import org.apache.camel.spi.RestProducerFactory;
@@ -47,7 +47,7 @@ public class RestComponentVerifierTest extends ContextTestSupport {
 
     public void testParameters() throws Exception {
         RestComponent component = context.getComponent("rest", RestComponent.class);
-        RestComponentVerifier verifier = (RestComponentVerifier)component.getVerifier();
+        ComponentVerifier verifier = component.getVerifier();
 
         Map<String, Object> parameters = new HashMap<>();
         parameters.put("componentName", "rest-component");
@@ -66,7 +66,7 @@ public class RestComponentVerifierTest extends ContextTestSupport {
 
     public void testMissingParameters() throws Exception {
         RestComponent component = context.getComponent("rest", RestComponent.class);
-        RestComponentVerifier verifier = (RestComponentVerifier)component.getVerifier();
+        ComponentVerifier verifier = component.getVerifier();
 
         Map<String, Object> parameters = new HashMap<>();
         parameters.put("componentName", "rest-component");
@@ -90,7 +90,19 @@ public class RestComponentVerifierTest extends ContextTestSupport {
     //
     // ***************************************************
 
-    private final class MyComponent extends DefaultComponent implements RestProducerFactory, RestConsumerFactory, VerifiableComponent {
+    private final class MyComponent extends DefaultComponent implements RestProducerFactory, RestConsumerFactory {
+        public MyComponent() {
+            registerExtension(
+                new ComponentVerifierExtension() {
+                    @Override
+                    public Result verify(Scope scope, Map<String, Object> parameters) {
+                        return ResultBuilder.withStatusAndScope(RestComponentVerifierExtension.Result.Status.OK, scope)
+                            .error(ResultErrorHelper.requiresOption("authProxy", parameters))
+                            .build();
+                    }
+                }
+            );
+        }
         @Override
         protected Endpoint createEndpoint(String uri, String remaining, Map<String, Object> parameters) throws Exception {
             throw new UnsupportedOperationException();
@@ -125,13 +137,5 @@ public class RestComponentVerifierTest extends ContextTestSupport {
                     throws Exception {
             throw new UnsupportedOperationException();
         }
-
-        @Override
-        public ComponentVerifier getVerifier() {
-            return (scope, parameters) ->
-                ResultBuilder.withStatusAndScope(ComponentVerifier.Result.Status.OK, scope)
-                    .error(ResultErrorHelper.requiresOption("authProxy", parameters))
-                    .build();
-        }
     }
 }

http://git-wip-us.apache.org/repos/asf/camel/blob/42529399/camel-core/src/test/java/org/apache/camel/impl/verifier/DefaultComponentVerifierTest.java
----------------------------------------------------------------------
diff --git a/camel-core/src/test/java/org/apache/camel/impl/verifier/DefaultComponentVerifierTest.java b/camel-core/src/test/java/org/apache/camel/impl/verifier/DefaultComponentVerifierTest.java
index 8a903b8..9ade841 100644
--- a/camel-core/src/test/java/org/apache/camel/impl/verifier/DefaultComponentVerifierTest.java
+++ b/camel-core/src/test/java/org/apache/camel/impl/verifier/DefaultComponentVerifierTest.java
@@ -19,13 +19,16 @@ package org.apache.camel.impl.verifier;
 import java.util.HashMap;
 import java.util.Map;
 
-import org.apache.camel.ComponentVerifier;
-import org.apache.camel.ComponentVerifier.VerificationError;
 import org.apache.camel.ContextTestSupport;
+import org.apache.camel.component.extension.ComponentVerifierExtension;
+import org.apache.camel.component.extension.ComponentVerifierExtension.Result;
+import org.apache.camel.component.extension.ComponentVerifierExtension.Scope;
+import org.apache.camel.component.extension.ComponentVerifierExtension.VerificationError;
+import org.apache.camel.component.extension.verifier.DefaultComponentVerifierExtension;
 import org.junit.Assert;
 
 public class DefaultComponentVerifierTest extends ContextTestSupport {
-    private ComponentVerifier verifier;
+    private ComponentVerifierExtension verifier;
 
     @Override
     public boolean isUseRouteBuilder() {
@@ -36,7 +39,7 @@ public class DefaultComponentVerifierTest extends ContextTestSupport {
     protected void setUp() throws Exception {
         super.setUp();
 
-        this.verifier = new DefaultComponentVerifier("timer", context);
+        this.verifier = new DefaultComponentVerifierExtension("timer", context);
     }
 
     // *************************************
@@ -48,16 +51,16 @@ public class DefaultComponentVerifierTest extends ContextTestSupport {
         parameters.put("timerName", "dummy");
         parameters.put("period", "1s");
 
-        ComponentVerifier.Result result = verifier.verify(ComponentVerifier.Scope.PARAMETERS, parameters);
-        Assert.assertEquals(ComponentVerifier.Result.Status.OK, result.getStatus());
+        Result result = verifier.verify(Scope.PARAMETERS, parameters);
+        Assert.assertEquals(Result.Status.OK, result.getStatus());
     }
 
     public void testParametersWithMissingMandatoryOptions() throws Exception {
         Map<String, Object> parameters = new HashMap<>();
         parameters.put("period", "1s");
 
-        ComponentVerifier.Result result = verifier.verify(ComponentVerifier.Scope.PARAMETERS, parameters);
-        Assert.assertEquals(ComponentVerifier.Result.Status.ERROR, result.getStatus());
+        Result result = verifier.verify(Scope.PARAMETERS, parameters);
+        Assert.assertEquals(Result.Status.ERROR, result.getStatus());
 
         Assert.assertEquals(1, result.getErrors().size());
         Assert.assertEquals(VerificationError.StandardCode.MISSING_PARAMETER, result.getErrors().get(0).getCode());
@@ -70,8 +73,8 @@ public class DefaultComponentVerifierTest extends ContextTestSupport {
         parameters.put("period", "1s");
         parameters.put("fixedRate", "wrong");
 
-        ComponentVerifier.Result result = verifier.verify(ComponentVerifier.Scope.PARAMETERS, parameters);
-        Assert.assertEquals(ComponentVerifier.Result.Status.ERROR, result.getStatus());
+        Result result = verifier.verify(Scope.PARAMETERS, parameters);
+        Assert.assertEquals(Result.Status.ERROR, result.getStatus());
 
         Assert.assertEquals(1, result.getErrors().size());
         Assert.assertEquals(VerificationError.StandardCode.ILLEGAL_PARAMETER_VALUE, result.getErrors().get(0).getCode());

http://git-wip-us.apache.org/repos/asf/camel/blob/42529399/camel-core/src/test/java/org/apache/camel/impl/verifier/ResultErrorHelperTest.java
----------------------------------------------------------------------
diff --git a/camel-core/src/test/java/org/apache/camel/impl/verifier/ResultErrorHelperTest.java b/camel-core/src/test/java/org/apache/camel/impl/verifier/ResultErrorHelperTest.java
index 15b82fc..0c72829 100644
--- a/camel-core/src/test/java/org/apache/camel/impl/verifier/ResultErrorHelperTest.java
+++ b/camel-core/src/test/java/org/apache/camel/impl/verifier/ResultErrorHelperTest.java
@@ -21,8 +21,11 @@ import java.util.List;
 import java.util.Map;
 import java.util.stream.Collectors;
 
-import org.apache.camel.ComponentVerifier.VerificationError;
-import org.apache.camel.ComponentVerifier.VerificationError.StandardCode;
+import org.apache.camel.component.extension.ComponentVerifierExtension;
+import org.apache.camel.component.extension.ComponentVerifierExtension.VerificationError;
+import org.apache.camel.component.extension.ComponentVerifierExtension.VerificationError.StandardCode;
+import org.apache.camel.component.extension.verifier.OptionsGroup;
+import org.apache.camel.component.extension.verifier.ResultErrorHelper;
 import org.junit.Test;
 
 import static org.junit.Assert.assertEquals;
@@ -49,7 +52,7 @@ public class ResultErrorHelperTest {
     @Test
     public void shouldValidateParameterExclusions() {
         // combining param2 and param3 is not OK
-        final List<VerificationError> results = ResultErrorHelper.requiresAny(map("param1", "param2", "param3"),
+        final List<ComponentVerifierExtension.VerificationError> results = ResultErrorHelper.requiresAny(map("param1", "param2", "param3"),
             groups);
 
         assertEquals(3, results.size());

http://git-wip-us.apache.org/repos/asf/camel/blob/42529399/camel-core/src/test/java/org/apache/camel/management/ManagedComponentTest.java
----------------------------------------------------------------------
diff --git a/camel-core/src/test/java/org/apache/camel/management/ManagedComponentTest.java b/camel-core/src/test/java/org/apache/camel/management/ManagedComponentTest.java
index 491e766..ce1737c 100644
--- a/camel-core/src/test/java/org/apache/camel/management/ManagedComponentTest.java
+++ b/camel-core/src/test/java/org/apache/camel/management/ManagedComponentTest.java
@@ -26,9 +26,9 @@ import org.apache.camel.ComponentVerifier;
 import org.apache.camel.Endpoint;
 import org.apache.camel.VerifiableComponent;
 import org.apache.camel.component.direct.DirectComponent;
+import org.apache.camel.component.extension.verifier.DefaultComponentVerifierExtension;
+import org.apache.camel.component.extension.verifier.ResultBuilder;
 import org.apache.camel.impl.DefaultComponent;
-import org.apache.camel.impl.verifier.DefaultComponentVerifier;
-import org.apache.camel.impl.verifier.ResultBuilder;
 
 public class ManagedComponentTest extends ManagementTestSupport {
     private static final String[] VERIFY_SIGNATURE = new String[] {
@@ -100,7 +100,7 @@ public class ManagedComponentTest extends ManagementTestSupport {
     private static class MyVerifiableComponent extends DefaultComponent implements VerifiableComponent {
         @Override
         public ComponentVerifier getVerifier() {
-            return new DefaultComponentVerifier("my-verifiable-component", getCamelContext()) {
+            return new DefaultComponentVerifierExtension("my-verifiable-component", getCamelContext()) {
                 @Override
                 protected Result verifyConnectivity(Map<String, Object> parameters) {
                     return ResultBuilder.withStatusAndScope(Result.Status.OK, Scope.CONNECTIVITY).build();

http://git-wip-us.apache.org/repos/asf/camel/blob/42529399/components/camel-http/src/main/java/org/apache/camel/component/http/HttpComponent.java
----------------------------------------------------------------------
diff --git a/components/camel-http/src/main/java/org/apache/camel/component/http/HttpComponent.java b/components/camel-http/src/main/java/org/apache/camel/component/http/HttpComponent.java
index 01c1730..2e2f6ed 100644
--- a/components/camel-http/src/main/java/org/apache/camel/component/http/HttpComponent.java
+++ b/components/camel-http/src/main/java/org/apache/camel/component/http/HttpComponent.java
@@ -30,6 +30,7 @@ import org.apache.camel.Producer;
 import org.apache.camel.ResolveEndpointFailedException;
 import org.apache.camel.SSLContextParametersAware;
 import org.apache.camel.VerifiableComponent;
+import org.apache.camel.component.extension.ComponentVerifierExtension;
 import org.apache.camel.http.common.HttpBinding;
 import org.apache.camel.http.common.HttpCommonComponent;
 import org.apache.camel.http.common.HttpConfiguration;
@@ -64,11 +65,13 @@ public class HttpComponent extends HttpCommonComponent implements RestProducerFa
     private boolean useGlobalSslContextParameters;
 
     public HttpComponent() {
-        super(HttpEndpoint.class);
+        this(HttpEndpoint.class);
     }
 
     public HttpComponent(Class<? extends HttpEndpoint> endpointClass) {
         super(endpointClass);
+
+        registerExtension(HttpComponentVerifierExtension::new);
     }
 
     /**
@@ -387,10 +390,8 @@ public class HttpComponent extends HttpCommonComponent implements RestProducerFa
         this.useGlobalSslContextParameters = useGlobalSslContextParameters;
     }
 
-    /**
-     * TODO: document
-     */
+    @Override
     public ComponentVerifier getVerifier() {
-        return new HttpComponentVerifier(this);
+        return (scope, parameters) -> getExtension(ComponentVerifierExtension.class).orElseThrow(UnsupportedOperationException::new).verify(scope, parameters);
     }
 }

http://git-wip-us.apache.org/repos/asf/camel/blob/42529399/components/camel-http/src/main/java/org/apache/camel/component/http/HttpComponentVerifier.java
----------------------------------------------------------------------
diff --git a/components/camel-http/src/main/java/org/apache/camel/component/http/HttpComponentVerifier.java b/components/camel-http/src/main/java/org/apache/camel/component/http/HttpComponentVerifier.java
deleted file mode 100644
index 309ff3e..0000000
--- a/components/camel-http/src/main/java/org/apache/camel/component/http/HttpComponentVerifier.java
+++ /dev/null
@@ -1,250 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.camel.component.http;
-
-import java.net.UnknownHostException;
-import java.util.Map;
-import java.util.Optional;
-
-import org.apache.camel.ComponentVerifier;
-import org.apache.camel.http.common.HttpHelper;
-import org.apache.camel.impl.verifier.DefaultComponentVerifier;
-import org.apache.camel.impl.verifier.ResultBuilder;
-import org.apache.camel.impl.verifier.ResultErrorBuilder;
-import org.apache.camel.impl.verifier.ResultErrorHelper;
-import org.apache.commons.httpclient.HttpClient;
-import org.apache.commons.httpclient.HttpMethod;
-import org.apache.commons.httpclient.methods.GetMethod;
-import org.apache.commons.httpclient.params.HttpClientParams;
-
-final class HttpComponentVerifier extends DefaultComponentVerifier {
-    private final HttpComponent component;
-
-    HttpComponentVerifier(HttpComponent component) {
-        super("http", component.getCamelContext());
-
-        this.component = component;
-    }
-
-    // *********************************
-    // Parameters validation
-    // *********************************
-
-    @Override
-    protected Result verifyParameters(Map<String, Object> parameters) {
-        // The default is success
-        ResultBuilder builder = ResultBuilder.withStatusAndScope(Result.Status.OK, Scope.PARAMETERS);
-
-        // Validate using the catalog
-        super.verifyParametersAgainstCatalog(builder, parameters);
-
-        // Validate if the auth/proxy combination is properly set-up
-        Optional<String> authMethod = getOption(parameters, "authMethod", String.class);
-        if (authMethod.isPresent()) {
-            // If auth method is set, username and password must be provided
-            builder.error(ResultErrorHelper.requiresOption("authUsername", parameters));
-            builder.error(ResultErrorHelper.requiresOption("authPassword", parameters));
-
-            // Check if the AuthMethod is known
-            AuthMethod auth = getCamelContext().getTypeConverter().convertTo(AuthMethod.class, authMethod.get());
-            if (auth != AuthMethod.Basic && auth != AuthMethod.Digest && auth != AuthMethod.NTLM) {
-                builder.error(ResultErrorBuilder.withIllegalOption("authMethod", authMethod.get()).build());
-            }
-
-            // If auth method is NTLM, authDomain is mandatory
-            if (auth == AuthMethod.NTLM) {
-                builder.error(ResultErrorHelper.requiresOption("authDomain", parameters));
-            }
-        }
-
-        return builder.build();
-    }
-
-    // *********************************
-    // Connectivity validation
-    // *********************************
-
-    @Override
-    protected Result verifyConnectivity(Map<String, Object> parameters) {
-        // Default is success
-        ResultBuilder builder = ResultBuilder.withStatusAndScope(Result.Status.OK, Scope.CONNECTIVITY);
-
-        Optional<String> uri = getOption(parameters, "httpUri", String.class);
-        if (!uri.isPresent()) {
-            // lack of httpUri is a blocking issue
-            builder.error(ResultErrorHelper.requiresOption("httpUri", parameters));
-        } else {
-            builder.error(parameters, this::verifyHttpConnectivity);
-        }
-
-        return builder.build();
-    }
-
-    private void verifyHttpConnectivity(ResultBuilder builder, Map<String, Object> parameters) throws Exception {
-        Optional<String> uri = getOption(parameters, "httpUri", String.class);
-
-        HttpClient httpclient = createHttpClient(builder, parameters);
-        HttpMethod method = new GetMethod(uri.get());
-
-        try {
-            int code = httpclient.executeMethod(method);
-            String okCodes = getOption(parameters, "okStatusCodeRange", String.class).orElse("200-299");
-
-            if (!HttpHelper.isStatusCodeOk(code, okCodes)) {
-                if (code == 401) {
-                    // Unauthorized, add authUsername and authPassword to the list
-                    // of parameters in error
-                    builder.error(
-                        ResultErrorBuilder.withHttpCode(code)
-                            .description(method.getStatusText())
-                            .parameterKey("authUsername")
-                            .parameterKey("authPassword")
-                            .build()
-                    );
-                } else if (code >= 300 && code < 400) {
-                    // redirect
-                    builder.error(
-                        ResultErrorBuilder.withHttpCode(code)
-                            .description(method.getStatusText())
-                            .parameterKey("httpUri")
-                            .detail(VerificationError.HttpAttribute.HTTP_REDIRECT, () -> HttpUtil.responseHeaderValue(method, "location"))
-                            .build()
-                    );
-                } else if (code >= 400) {
-                    // generic http error
-                    builder.error(
-                        ResultErrorBuilder.withHttpCode(code)
-                            .description(method.getStatusText())
-                            .build()
-                    );
-                }
-            }
-        } catch (UnknownHostException e) {
-            builder.error(
-                ResultErrorBuilder.withException(e)
-                    .parameterKey("httpUri")
-                    .build()
-            );
-        }
-    }
-
-    // *********************************
-    // Helpers
-    // *********************************
-
-    private Optional<HttpClientConfigurer> configureAuthentication(ResultBuilder builder, Map<String, Object> parameters) {
-        Optional<String> authMethod = getOption(parameters, "authMethod", String.class);
-
-        if (authMethod.isPresent()) {
-            Optional<String> authUsername = getOption(parameters, "authUsername", String.class);
-            Optional<String> authPassword = getOption(parameters, "authPassword", String.class);
-
-            if (authUsername.isPresent() && authUsername.isPresent()) {
-                AuthMethod auth = getCamelContext().getTypeConverter().convertTo(AuthMethod.class, authMethod.get());
-                if (auth == AuthMethod.Basic || auth == AuthMethod.Digest) {
-                    return Optional.of(
-                        new BasicAuthenticationHttpClientConfigurer(false, authUsername.get(), authPassword.get())
-                    );
-                } else if (auth == AuthMethod.NTLM) {
-                    Optional<String> authDomain = getOption(parameters, "authDomain", String.class);
-                    Optional<String> authHost = getOption(parameters, "authHost", String.class);
-
-                    if (!authDomain.isPresent()) {
-                        builder.error(ResultErrorBuilder.withMissingOption("authDomain").build());
-                    } else {
-                        return Optional.of(
-                            new NTLMAuthenticationHttpClientConfigurer(false, authUsername.get(), authPassword.get(), authDomain.get(), authHost.orElse(null))
-                        );
-                    }
-                } else {
-                    builder.error(ResultErrorBuilder.withIllegalOption("authMethod", authMethod.get()).build());
-                }
-            } else {
-                builder.error(ResultErrorHelper.requiresOption("authUsername", parameters));
-                builder.error(ResultErrorHelper.requiresOption("authPassword", parameters));
-            }
-        }
-        return Optional.empty();
-    }
-
-    private Optional<HttpClientConfigurer> configureProxy(ResultBuilder builder, Map<String, Object> parameters) {
-        CompositeHttpConfigurer configurer = new CompositeHttpConfigurer();
-
-        // Add a Proxy
-        Optional<String> proxyHost = getOption(parameters, "proxyAuthHost", String.class);
-        if (!proxyHost.isPresent()) {
-            proxyHost = getOption(parameters, "proxyHost", String.class);
-        }
-
-        Optional<Integer> proxyPort = getOption(parameters, "proxyAuthPort", Integer.class);
-        if (!proxyPort.isPresent()) {
-            proxyPort = getOption(parameters, "proxyPort", Integer.class);
-        }
-
-        if (proxyHost.isPresent() || proxyPort.isPresent()) {
-            configurer.addConfigurer(new HttpProxyConfigurer(proxyHost, proxyPort));
-        }
-
-
-        // Configure proxy auth
-        Optional<String> authMethod = getOption(parameters, "proxyAuthMethod", String.class);
-        if (authMethod.isPresent()) {
-            Optional<String> authUsername = getOption(parameters, "proxyAuthUsername", String.class);
-            Optional<String> authPassword = getOption(parameters, "proxyAuthPassword", String.class);
-
-            if (authUsername.isPresent() && authUsername.isPresent()) {
-                AuthMethod auth = getCamelContext().getTypeConverter().convertTo(AuthMethod.class, authMethod);
-                if (auth == AuthMethod.Basic || auth == AuthMethod.Digest) {
-                    configurer.addConfigurer(
-                        new BasicAuthenticationHttpClientConfigurer(false, authUsername.get(), authPassword.get())
-                    );
-                } else if (auth == AuthMethod.NTLM) {
-                    Optional<String> authDomain = getOption(parameters, "proxyAuthDomain", String.class);
-                    Optional<String> authHost = getOption(parameters, "proxyAuthHost", String.class);
-
-                    if (!authDomain.isPresent()) {
-                        builder.error(ResultErrorBuilder.withMissingOption("authDomain").build());
-                    } else {
-                        return Optional.of(
-                            new NTLMAuthenticationHttpClientConfigurer(false, authUsername.get(), authPassword.get(), authDomain.get(), authHost.orElse(null))
-                        );
-                    }
-                } else {
-                    builder.error(ResultErrorBuilder.withIllegalOption("authMethod", authMethod.get()).build());
-                }
-            } else {
-                builder.error(ResultErrorHelper.requiresOption("authUsername", parameters));
-                builder.error(ResultErrorHelper.requiresOption("authPassword", parameters));
-            }
-        }
-
-        return Optional.of(configurer);
-    }
-
-    private HttpClient createHttpClient(ResultBuilder builder, Map<String, Object> parameters) throws Exception {
-        HttpClientParams clientParams = setProperties(new HttpClientParams(), "httpClient.", parameters);
-        HttpClient client = new HttpClient(clientParams);
-
-        CompositeHttpConfigurer configurer = new CompositeHttpConfigurer();
-        configureProxy(builder, parameters).ifPresent(configurer::addConfigurer);
-        configureAuthentication(builder, parameters).ifPresent(configurer::addConfigurer);
-
-        configurer.configureHttpClient(client);
-
-        return client;
-    }
-}

http://git-wip-us.apache.org/repos/asf/camel/blob/42529399/components/camel-http/src/main/java/org/apache/camel/component/http/HttpComponentVerifierExtension.java
----------------------------------------------------------------------
diff --git a/components/camel-http/src/main/java/org/apache/camel/component/http/HttpComponentVerifierExtension.java b/components/camel-http/src/main/java/org/apache/camel/component/http/HttpComponentVerifierExtension.java
new file mode 100644
index 0000000..620c688
--- /dev/null
+++ b/components/camel-http/src/main/java/org/apache/camel/component/http/HttpComponentVerifierExtension.java
@@ -0,0 +1,246 @@
+/**
+ * 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.http;
+
+import java.net.UnknownHostException;
+import java.util.Map;
+import java.util.Optional;
+
+import org.apache.camel.component.extension.verifier.DefaultComponentVerifierExtension;
+import org.apache.camel.component.extension.verifier.ResultBuilder;
+import org.apache.camel.component.extension.verifier.ResultErrorBuilder;
+import org.apache.camel.component.extension.verifier.ResultErrorHelper;
+import org.apache.camel.http.common.HttpHelper;
+import org.apache.commons.httpclient.HttpClient;
+import org.apache.commons.httpclient.HttpMethod;
+import org.apache.commons.httpclient.methods.GetMethod;
+import org.apache.commons.httpclient.params.HttpClientParams;
+
+final class HttpComponentVerifierExtension extends DefaultComponentVerifierExtension {
+
+    HttpComponentVerifierExtension() {
+        super("http");
+    }
+
+    // *********************************
+    // Parameters validation
+    // *********************************
+
+    @Override
+    protected Result verifyParameters(Map<String, Object> parameters) {
+        // The default is success
+        ResultBuilder builder = ResultBuilder.withStatusAndScope(Result.Status.OK, Scope.PARAMETERS);
+
+        // Validate using the catalog
+        super.verifyParametersAgainstCatalog(builder, parameters);
+
+        // Validate if the auth/proxy combination is properly set-up
+        Optional<String> authMethod = getOption(parameters, "authMethod", String.class);
+        if (authMethod.isPresent()) {
+            // If auth method is set, username and password must be provided
+            builder.error(ResultErrorHelper.requiresOption("authUsername", parameters));
+            builder.error(ResultErrorHelper.requiresOption("authPassword", parameters));
+
+            // Check if the AuthMethod is known
+            AuthMethod auth = getCamelContext().getTypeConverter().convertTo(AuthMethod.class, authMethod.get());
+            if (auth != AuthMethod.Basic && auth != AuthMethod.Digest && auth != AuthMethod.NTLM) {
+                builder.error(ResultErrorBuilder.withIllegalOption("authMethod", authMethod.get()).build());
+            }
+
+            // If auth method is NTLM, authDomain is mandatory
+            if (auth == AuthMethod.NTLM) {
+                builder.error(ResultErrorHelper.requiresOption("authDomain", parameters));
+            }
+        }
+
+        return builder.build();
+    }
+
+    // *********************************
+    // Connectivity validation
+    // *********************************
+
+    @Override
+    protected Result verifyConnectivity(Map<String, Object> parameters) {
+        // Default is success
+        ResultBuilder builder = ResultBuilder.withStatusAndScope(Result.Status.OK, Scope.CONNECTIVITY);
+
+        Optional<String> uri = getOption(parameters, "httpUri", String.class);
+        if (!uri.isPresent()) {
+            // lack of httpUri is a blocking issue
+            builder.error(ResultErrorHelper.requiresOption("httpUri", parameters));
+        } else {
+            builder.error(parameters, this::verifyHttpConnectivity);
+        }
+
+        return builder.build();
+    }
+
+    private void verifyHttpConnectivity(ResultBuilder builder, Map<String, Object> parameters) throws Exception {
+        Optional<String> uri = getOption(parameters, "httpUri", String.class);
+
+        HttpClient httpclient = createHttpClient(builder, parameters);
+        HttpMethod method = new GetMethod(uri.get());
+
+        try {
+            int code = httpclient.executeMethod(method);
+            String okCodes = getOption(parameters, "okStatusCodeRange", String.class).orElse("200-299");
+
+            if (!HttpHelper.isStatusCodeOk(code, okCodes)) {
+                if (code == 401) {
+                    // Unauthorized, add authUsername and authPassword to the list
+                    // of parameters in error
+                    builder.error(
+                        ResultErrorBuilder.withHttpCode(code)
+                            .description(method.getStatusText())
+                            .parameterKey("authUsername")
+                            .parameterKey("authPassword")
+                            .build()
+                    );
+                } else if (code >= 300 && code < 400) {
+                    // redirect
+                    builder.error(
+                        ResultErrorBuilder.withHttpCode(code)
+                            .description(method.getStatusText())
+                            .parameterKey("httpUri")
+                            .detail(VerificationError.HttpAttribute.HTTP_REDIRECT, () -> HttpUtil.responseHeaderValue(method, "location"))
+                            .build()
+                    );
+                } else if (code >= 400) {
+                    // generic http error
+                    builder.error(
+                        ResultErrorBuilder.withHttpCode(code)
+                            .description(method.getStatusText())
+                            .build()
+                    );
+                }
+            }
+        } catch (UnknownHostException e) {
+            builder.error(
+                ResultErrorBuilder.withException(e)
+                    .parameterKey("httpUri")
+                    .build()
+            );
+        }
+    }
+
+    // *********************************
+    // Helpers
+    // *********************************
+
+    private Optional<HttpClientConfigurer> configureAuthentication(ResultBuilder builder, Map<String, Object> parameters) {
+        Optional<String> authMethod = getOption(parameters, "authMethod", String.class);
+
+        if (authMethod.isPresent()) {
+            Optional<String> authUsername = getOption(parameters, "authUsername", String.class);
+            Optional<String> authPassword = getOption(parameters, "authPassword", String.class);
+
+            if (authUsername.isPresent() && authUsername.isPresent()) {
+                AuthMethod auth = getCamelContext().getTypeConverter().convertTo(AuthMethod.class, authMethod.get());
+                if (auth == AuthMethod.Basic || auth == AuthMethod.Digest) {
+                    return Optional.of(
+                        new BasicAuthenticationHttpClientConfigurer(false, authUsername.get(), authPassword.get())
+                    );
+                } else if (auth == AuthMethod.NTLM) {
+                    Optional<String> authDomain = getOption(parameters, "authDomain", String.class);
+                    Optional<String> authHost = getOption(parameters, "authHost", String.class);
+
+                    if (!authDomain.isPresent()) {
+                        builder.error(ResultErrorBuilder.withMissingOption("authDomain").build());
+                    } else {
+                        return Optional.of(
+                            new NTLMAuthenticationHttpClientConfigurer(false, authUsername.get(), authPassword.get(), authDomain.get(), authHost.orElse(null))
+                        );
+                    }
+                } else {
+                    builder.error(ResultErrorBuilder.withIllegalOption("authMethod", authMethod.get()).build());
+                }
+            } else {
+                builder.error(ResultErrorHelper.requiresOption("authUsername", parameters));
+                builder.error(ResultErrorHelper.requiresOption("authPassword", parameters));
+            }
+        }
+        return Optional.empty();
+    }
+
+    private Optional<HttpClientConfigurer> configureProxy(ResultBuilder builder, Map<String, Object> parameters) {
+        CompositeHttpConfigurer configurer = new CompositeHttpConfigurer();
+
+        // Add a Proxy
+        Optional<String> proxyHost = getOption(parameters, "proxyAuthHost", String.class);
+        if (!proxyHost.isPresent()) {
+            proxyHost = getOption(parameters, "proxyHost", String.class);
+        }
+
+        Optional<Integer> proxyPort = getOption(parameters, "proxyAuthPort", Integer.class);
+        if (!proxyPort.isPresent()) {
+            proxyPort = getOption(parameters, "proxyPort", Integer.class);
+        }
+
+        if (proxyHost.isPresent() || proxyPort.isPresent()) {
+            configurer.addConfigurer(new HttpProxyConfigurer(proxyHost, proxyPort));
+        }
+
+
+        // Configure proxy auth
+        Optional<String> authMethod = getOption(parameters, "proxyAuthMethod", String.class);
+        if (authMethod.isPresent()) {
+            Optional<String> authUsername = getOption(parameters, "proxyAuthUsername", String.class);
+            Optional<String> authPassword = getOption(parameters, "proxyAuthPassword", String.class);
+
+            if (authUsername.isPresent() && authUsername.isPresent()) {
+                AuthMethod auth = getCamelContext().getTypeConverter().convertTo(AuthMethod.class, authMethod);
+                if (auth == AuthMethod.Basic || auth == AuthMethod.Digest) {
+                    configurer.addConfigurer(
+                        new BasicAuthenticationHttpClientConfigurer(false, authUsername.get(), authPassword.get())
+                    );
+                } else if (auth == AuthMethod.NTLM) {
+                    Optional<String> authDomain = getOption(parameters, "proxyAuthDomain", String.class);
+                    Optional<String> authHost = getOption(parameters, "proxyAuthHost", String.class);
+
+                    if (!authDomain.isPresent()) {
+                        builder.error(ResultErrorBuilder.withMissingOption("authDomain").build());
+                    } else {
+                        return Optional.of(
+                            new NTLMAuthenticationHttpClientConfigurer(false, authUsername.get(), authPassword.get(), authDomain.get(), authHost.orElse(null))
+                        );
+                    }
+                } else {
+                    builder.error(ResultErrorBuilder.withIllegalOption("authMethod", authMethod.get()).build());
+                }
+            } else {
+                builder.error(ResultErrorHelper.requiresOption("authUsername", parameters));
+                builder.error(ResultErrorHelper.requiresOption("authPassword", parameters));
+            }
+        }
+
+        return Optional.of(configurer);
+    }
+
+    private HttpClient createHttpClient(ResultBuilder builder, Map<String, Object> parameters) throws Exception {
+        HttpClientParams clientParams = setProperties(new HttpClientParams(), "httpClient.", parameters);
+        HttpClient client = new HttpClient(clientParams);
+
+        CompositeHttpConfigurer configurer = new CompositeHttpConfigurer();
+        configureProxy(builder, parameters).ifPresent(configurer::addConfigurer);
+        configureAuthentication(builder, parameters).ifPresent(configurer::addConfigurer);
+
+        configurer.configureHttpClient(client);
+
+        return client;
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/42529399/components/camel-http/src/test/java/org/apache/camel/component/http/CamelComponentVerifierTest.java
----------------------------------------------------------------------
diff --git a/components/camel-http/src/test/java/org/apache/camel/component/http/CamelComponentVerifierTest.java b/components/camel-http/src/test/java/org/apache/camel/component/http/CamelComponentVerifierTest.java
deleted file mode 100644
index 76d918e..0000000
--- a/components/camel-http/src/test/java/org/apache/camel/component/http/CamelComponentVerifierTest.java
+++ /dev/null
@@ -1,192 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.camel.component.http;
-
-import java.util.HashMap;
-import java.util.Map;
-
-import org.apache.camel.ComponentVerifier;
-import org.apache.camel.ComponentVerifier.VerificationError;
-import org.apache.camel.component.http.handler.BasicValidationHandler;
-import org.apache.camel.test.AvailablePortFinder;
-import org.eclipse.jetty.server.Server;
-import org.junit.After;
-import org.junit.Assert;
-import org.junit.Before;
-import org.junit.Ignore;
-import org.junit.Test;
-
-public class CamelComponentVerifierTest extends BaseHttpTest {
-    private static final String AUTH_USERNAME = "camel";
-    private static final String AUTH_PASSWORD = "password";
-    private static final int PORT = AvailablePortFinder.getNextAvailable();
-
-    private Server localServer;
-
-    @Before
-    @Override
-    public void setUp() throws Exception {
-        localServer = new Server(PORT);
-        localServer.setHandler(handlers(
-            contextHandler("/basic", new BasicValidationHandler("GET", null, null, getExpectedContent()))
-        ));
-
-        localServer.start();
-
-        super.setUp();
-    }
-
-    @After
-    @Override
-    public void tearDown() throws Exception {
-        super.tearDown();
-
-        if (localServer != null) {
-            localServer.stop();
-        }
-    }
-
-    @Override
-    public boolean isUseRouteBuilder() {
-        return false;
-    }
-
-    // *************************************************
-    // Helpers
-    // *************************************************
-
-    protected String getLocalServerUri(String contextPath) throws Exception {
-        return new StringBuilder()
-            .append("http://")
-            .append("localhost")
-            .append(":")
-            .append(PORT)
-            .append(contextPath != null ? contextPath : "")
-            .toString();
-    }
-
-    // *************************************************
-    // Tests
-    // *************************************************
-
-    @Test
-    public void testParameters() throws Exception {
-        HttpComponent component = context().getComponent("http", HttpComponent.class);
-        HttpComponentVerifier verifier = (HttpComponentVerifier)component.getVerifier();
-
-        Map<String, Object> parameters = new HashMap<>();
-        parameters.put("httpUri", getLocalServerUri("/basic"));
-
-        ComponentVerifier.Result result = verifier.verify(ComponentVerifier.Scope.PARAMETERS, parameters);
-
-        Assert.assertEquals(ComponentVerifier.Result.Status.OK, result.getStatus());
-    }
-
-    @Test
-    public void testMissingMandatoryParameters() throws Exception {
-        HttpComponent component = context().getComponent("http", HttpComponent.class);
-        HttpComponentVerifier verifier = (HttpComponentVerifier)component.getVerifier();
-
-        Map<String, Object> parameters = new HashMap<>();
-
-        ComponentVerifier.Result result = verifier.verify(ComponentVerifier.Scope.PARAMETERS, parameters);
-
-        Assert.assertEquals(ComponentVerifier.Result.Status.ERROR, result.getStatus());
-        Assert.assertEquals(1, result.getErrors().size());
-
-        VerificationError error = result.getErrors().get(0);
-
-        Assert.assertEquals(VerificationError.StandardCode.MISSING_PARAMETER, error.getCode());
-        Assert.assertTrue(error.getParameterKeys().contains("httpUri"));
-    }
-
-    // *************************************************
-    // Tests
-    // *************************************************
-
-    @Test
-    public void testConnectivity() throws Exception {
-        HttpComponent component = context().getComponent("http", HttpComponent.class);
-        HttpComponentVerifier verifier = (HttpComponentVerifier)component.getVerifier();
-
-        Map<String, Object> parameters = new HashMap<>();
-        parameters.put("httpUri", getLocalServerUri("/basic"));
-
-        ComponentVerifier.Result result = verifier.verify(ComponentVerifier.Scope.CONNECTIVITY, parameters);
-
-        Assert.assertEquals(ComponentVerifier.Result.Status.OK, result.getStatus());
-    }
-
-    @Test
-    public void testConnectivityWithWrongUri() throws Exception {
-        HttpComponent component = context().getComponent("http", HttpComponent.class);
-        HttpComponentVerifier verifier = (HttpComponentVerifier)component.getVerifier();
-
-        Map<String, Object> parameters = new HashMap<>();
-        parameters.put("httpUri", "http://www.not-existing-uri.unknown");
-
-        ComponentVerifier.Result result = verifier.verify(ComponentVerifier.Scope.CONNECTIVITY, parameters);
-
-        Assert.assertEquals(ComponentVerifier.Result.Status.ERROR, result.getStatus());
-        Assert.assertEquals(1, result.getErrors().size());
-
-        VerificationError error = result.getErrors().get(0);
-
-        Assert.assertEquals(VerificationError.StandardCode.EXCEPTION, error.getCode());
-        Assert.assertTrue(error.getParameterKeys().contains("httpUri"));
-    }
-
-    @Ignore
-    @Test
-    public void testConnectivityWithAuthentication() throws Exception {
-        HttpComponent component = context().getComponent("http", HttpComponent.class);
-        HttpComponentVerifier verifier = (HttpComponentVerifier)component.getVerifier();
-
-        Map<String, Object> parameters = new HashMap<>();
-        parameters.put("httpUri", getLocalServerUri("/auth"));
-        parameters.put("authUsername", AUTH_USERNAME);
-        parameters.put("authPassword", AUTH_PASSWORD);
-
-        ComponentVerifier.Result result = verifier.verify(ComponentVerifier.Scope.CONNECTIVITY, parameters);
-
-        Assert.assertEquals(ComponentVerifier.Result.Status.OK, result.getStatus());
-    }
-
-    @Ignore
-    @Test
-    public void testConnectivityWithWrongAuthenticationData() throws Exception {
-        HttpComponent component = context().getComponent("http", HttpComponent.class);
-        HttpComponentVerifier verifier = (HttpComponentVerifier)component.getVerifier();
-
-        Map<String, Object> parameters = new HashMap<>();
-        parameters.put("httpUri", getLocalServerUri("/auth"));
-        parameters.put("authUsername", "unknown");
-        parameters.put("authPassword", AUTH_PASSWORD);
-
-        ComponentVerifier.Result result = verifier.verify(ComponentVerifier.Scope.CONNECTIVITY, parameters);
-
-        Assert.assertEquals(ComponentVerifier.Result.Status.ERROR, result.getStatus());
-        Assert.assertEquals(1, result.getErrors().size());
-
-        VerificationError error = result.getErrors().get(0);
-
-        Assert.assertEquals(VerificationError.StandardCode.AUTHENTICATION, error.getCode());
-        Assert.assertEquals(401, error.getDetails().get(VerificationError.HttpAttribute.HTTP_CODE));
-        Assert.assertTrue(error.getParameterKeys().contains("authUsername"));
-        Assert.assertTrue(error.getParameterKeys().contains("authPassword"));
-    }
-}
\ No newline at end of file


[12/19] camel git commit: CAMEL-11555: ServiceNow : create a maven plugin to generate models based on table layout

Posted by lb...@apache.org.
http://git-wip-us.apache.org/repos/asf/camel/blob/109da7c9/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/model/DictionaryEntry.java
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/model/DictionaryEntry.java b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/model/DictionaryEntry.java
deleted file mode 100644
index af7aa5b..0000000
--- a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/model/DictionaryEntry.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.camel.component.servicenow.model;
-
-import com.fasterxml.jackson.annotation.JsonCreator;
-import com.fasterxml.jackson.annotation.JsonProperty;
-
-public class DictionaryEntry {
-    private final Reference internalType;
-    private final Reference reference;
-    private final Integer maxLength;
-    private final boolean mandatory;
-
-    @JsonCreator
-    public DictionaryEntry(
-        @JsonProperty(value = "internal_type") Reference internalType,
-        @JsonProperty(value = "reference") Reference reference,
-        @JsonProperty(value = "max_length") Integer maxLength,
-        @JsonProperty(value = "mandatory", defaultValue = "false") boolean mandatory) {
-
-        this.internalType = internalType;
-        this.reference = reference;
-        this.maxLength = maxLength;
-        this.mandatory = mandatory;
-    }
-
-    public Reference getInternalType() {
-        return internalType;
-    }
-
-    public Reference getReference() {
-        return reference;
-    }
-
-    public Integer getMaxLength() {
-        return maxLength;
-    }
-
-    public boolean isMandatory() {
-        return mandatory;
-    }
-}

http://git-wip-us.apache.org/repos/asf/camel/blob/109da7c9/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/model/ImportSetResponse.java
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/model/ImportSetResponse.java b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/model/ImportSetResponse.java
deleted file mode 100644
index 348dd8d..0000000
--- a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/model/ImportSetResponse.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.camel.component.servicenow.model;
-
-import java.util.Collections;
-import java.util.List;
-
-import com.fasterxml.jackson.annotation.JsonCreator;
-import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
-import com.fasterxml.jackson.annotation.JsonInclude;
-import com.fasterxml.jackson.annotation.JsonProperty;
-import org.apache.camel.component.servicenow.annotations.ServiceNowSysParm;
-
-@ServiceNowSysParm(name = "sysparm_exclude_reference_link", value = "true")
-@JsonIgnoreProperties(ignoreUnknown = true)
-@JsonInclude(JsonInclude.Include.NON_NULL)
-public class ImportSetResponse {
-    private final String importSet;
-    private final String stagingTable;
-    private final List<ImportSetResult> results;
-
-    @JsonCreator
-    public ImportSetResponse(
-        @JsonProperty("import_set") String importSet,
-        @JsonProperty("staging_table") String stagingTable,
-        @JsonProperty("result") List<ImportSetResult> results) {
-        this.importSet = importSet;
-        this.stagingTable = stagingTable;
-        this.results = results == null ? Collections.emptyList() : results;
-    }
-
-    public String getImportSet() {
-        return importSet;
-    }
-
-    public String getStagingTable() {
-        return stagingTable;
-    }
-
-    public List<ImportSetResult> getResults() {
-        return results;
-    }
-}

http://git-wip-us.apache.org/repos/asf/camel/blob/109da7c9/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/model/ImportSetResult.java
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/model/ImportSetResult.java b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/model/ImportSetResult.java
deleted file mode 100644
index e5962e0..0000000
--- a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/model/ImportSetResult.java
+++ /dev/null
@@ -1,83 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.camel.component.servicenow.model;
-
-import com.fasterxml.jackson.annotation.JsonCreator;
-import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
-import com.fasterxml.jackson.annotation.JsonInclude;
-import com.fasterxml.jackson.annotation.JsonProperty;
-import org.apache.camel.component.servicenow.annotations.ServiceNowSysParm;
-
-@ServiceNowSysParm(name = "sysparm_exclude_reference_link", value = "true")
-@JsonIgnoreProperties(ignoreUnknown = true)
-@JsonInclude(JsonInclude.Include.NON_NULL)
-public class ImportSetResult {
-    private final String transformMap;
-    private final String table;
-    private final String displayName;
-    private final String displayValue;
-    private final String recordLink;
-    private final String status;
-    private final String sysId;
-
-    @JsonCreator
-    public ImportSetResult(
-        @JsonProperty(value = "transform_map") String transformMap,
-        @JsonProperty(value = "table", required = true) String table,
-        @JsonProperty(value = "display_name") String displayName,
-        @JsonProperty(value = "display_value") String displayValue,
-        @JsonProperty(value = "record_link") String recordLink,
-        @JsonProperty(value = "status", required = true) String status,
-        @JsonProperty(value = "sys_id", required = true) String sysId) {
-
-        this.transformMap = transformMap;
-        this.table = table;
-        this.displayName = displayName;
-        this.displayValue = displayValue;
-        this.recordLink = recordLink;
-        this.status = status;
-        this.sysId = sysId;
-    }
-
-    public String getTransformMap() {
-        return transformMap;
-    }
-
-    public String getTable() {
-        return table;
-    }
-
-    public String getDisplayName() {
-        return displayName;
-    }
-
-    public String getDisplayValue() {
-        return displayValue;
-    }
-
-    public String getRecordLink() {
-        return recordLink;
-    }
-
-    public String getStatus() {
-        return status;
-    }
-
-    public String getSysId() {
-        return sysId;
-    }
-}

http://git-wip-us.apache.org/repos/asf/camel/blob/109da7c9/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/model/Reference.java
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/model/Reference.java b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/model/Reference.java
deleted file mode 100644
index 1bcb2a7..0000000
--- a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/model/Reference.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.camel.component.servicenow.model;
-
-import com.fasterxml.jackson.annotation.JsonCreator;
-import com.fasterxml.jackson.annotation.JsonProperty;
-
-public class Reference {
-    private final String link;
-    private final String value;
-    private final String displayValue;
-
-    @JsonCreator
-    public Reference(String value) {
-        this.link = null;
-        this.value = value;
-        this.displayValue = null;
-    }
-
-    @JsonCreator
-    public Reference(
-        @JsonProperty(value = "link", required = false) String link,
-        @JsonProperty(value = "value", required = true) String value,
-        @JsonProperty(value = "display_value", required = false) String displayValue) {
-
-        this.link = link;
-        this.value = value;
-        this.displayValue = displayValue;
-    }
-
-    public String getLink() {
-        return link;
-    }
-
-    public String getValue() {
-        return value;
-    }
-
-    public String getDisplayValue() {
-        return displayValue;
-    }
-}

http://git-wip-us.apache.org/repos/asf/camel/blob/109da7c9/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/releases/fuji/FujiServiceNowAggregateProcessor.java
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/releases/fuji/FujiServiceNowAggregateProcessor.java b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/releases/fuji/FujiServiceNowAggregateProcessor.java
deleted file mode 100644
index 7fe9352..0000000
--- a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/releases/fuji/FujiServiceNowAggregateProcessor.java
+++ /dev/null
@@ -1,72 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.camel.component.servicenow.releases.fuji;
-
-import javax.ws.rs.HttpMethod;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.Response;
-
-import org.apache.camel.Exchange;
-import org.apache.camel.Message;
-import org.apache.camel.component.servicenow.ServiceNowConstants;
-import org.apache.camel.component.servicenow.ServiceNowEndpoint;
-import org.apache.camel.component.servicenow.ServiceNowParams;
-import org.apache.camel.util.ObjectHelper;
-
-class FujiServiceNowAggregateProcessor extends FujiServiceNowProcessor {
-
-    FujiServiceNowAggregateProcessor(ServiceNowEndpoint endpoint) throws Exception {
-        super(endpoint);
-    }
-
-    @Override
-    protected void doProcess(Exchange exchange, Class<?> requestModel, Class<?> responseModel, String action, String apiVersion, String tableName, String sysId) throws Exception {
-        Response response;
-        if (ObjectHelper.equal(ServiceNowConstants.ACTION_RETRIEVE, action, true)) {
-            response = retrieveStats(exchange.getIn(), requestModel, responseModel, tableName);
-        } else {
-            throw new IllegalArgumentException("Unknown action " + action);
-        }
-
-        setBodyAndHeaders(exchange.getIn(), responseModel, response);
-    }
-
-    private Response retrieveStats(Message in, Class<?> requestModel, Class<?> responseModel, String tableName) throws Exception {
-        final String apiVersion = getApiVersion(in);
-
-        return client.reset()
-            .types(MediaType.APPLICATION_JSON_TYPE)
-            .path("now")
-            .path(apiVersion)
-            .path("stats")
-            .path(tableName)
-            .query(ServiceNowParams.SYSPARM_QUERY, in)
-            .query(ServiceNowParams.SYSPARM_AVG_FIELDS, in)
-            .query(ServiceNowParams.SYSPARM_COUNT, in)
-            .query(ServiceNowParams.SYSPARM_MIN_FIELDS, in)
-            .query(ServiceNowParams.SYSPARM_QUERY, in)
-            .query(ServiceNowParams.SYSPARM_MAX_FIELDS, in)
-            .query(ServiceNowParams.SYSPARM_SUM_FIELDS, in)
-            .query(ServiceNowParams.SYSPARM_GROUP_BY, in)
-            .query(ServiceNowParams.SYSPARM_ORDER_BY, in)
-            .query(ServiceNowParams.SYSPARM_HAVING, in)
-            .query(ServiceNowParams.SYSPARM_DISPLAY_VALUE, in)
-            .query(responseModel)
-            .invoke(HttpMethod.GET);
-    }
-}

http://git-wip-us.apache.org/repos/asf/camel/blob/109da7c9/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/releases/fuji/FujiServiceNowImportSetProcessor.java
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/releases/fuji/FujiServiceNowImportSetProcessor.java b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/releases/fuji/FujiServiceNowImportSetProcessor.java
deleted file mode 100644
index 2080045..0000000
--- a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/releases/fuji/FujiServiceNowImportSetProcessor.java
+++ /dev/null
@@ -1,86 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.camel.component.servicenow.releases.fuji;
-
-import javax.ws.rs.HttpMethod;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.Response;
-
-import org.apache.camel.Exchange;
-import org.apache.camel.Message;
-import org.apache.camel.component.servicenow.ServiceNowConstants;
-import org.apache.camel.component.servicenow.ServiceNowEndpoint;
-import org.apache.camel.util.ObjectHelper;
-
-class FujiServiceNowImportSetProcessor extends FujiServiceNowProcessor {
-
-    FujiServiceNowImportSetProcessor(ServiceNowEndpoint endpoint) throws Exception {
-        super(endpoint);
-    }
-
-    @Override
-    protected void doProcess(Exchange exchange, Class<?> requestModel, Class<?> responseModel, String action, String apiVersion, String tableName, String sysId) throws Exception {
-        Response response;
-        if (ObjectHelper.equal(ServiceNowConstants.ACTION_RETRIEVE, action, true)) {
-            response = retrieveRecord(exchange.getIn(), requestModel, responseModel, apiVersion, tableName, sysId);
-        } else if (ObjectHelper.equal(ServiceNowConstants.ACTION_CREATE, action, true)) {
-            response = createRecord(exchange.getIn(), requestModel, responseModel, apiVersion, tableName);
-        } else {
-            throw new IllegalArgumentException("Unknown action " + action);
-        }
-
-        setBodyAndHeaders(exchange.getIn(), responseModel, response);
-    }
-
-    /*
-     * GET
-     * https://instance.service-now.com/api/now/import/{tableName}/{sys_id}
-     */
-    private Response retrieveRecord(Message in, Class<?> requestModel, Class<?> responseModel, String apiVersion, String tableName, String sysId) throws Exception {
-        return client.reset()
-            .types(MediaType.APPLICATION_JSON_TYPE)
-            .path("now")
-            .path(apiVersion)
-            .path("import")
-            .path(tableName)
-            .path(ObjectHelper.notNull(sysId, "sysId"))
-            .query(responseModel)
-            .invoke(HttpMethod.GET);
-    }
-
-    /*
-     * POST
-     * https://instance.service-now.com/api/now/import/{tableName}
-     */
-    private Response createRecord(Message in, Class<?> requestModel, Class<?> responseModel, String apiVersion, String tableName) throws Exception {
-        if (in.getHeader(ServiceNowConstants.RETRIEVE_TARGET_RECORD, config::getRetrieveTargetRecordOnImport, Boolean.class)) {
-            throw new UnsupportedOperationException("RetrieveTargetRecordOnImport is supported from Helsinky");
-        }
-
-        validateBody(in, requestModel);
-
-        return client.reset()
-            .types(MediaType.APPLICATION_JSON_TYPE)
-            .path("now")
-            .path(apiVersion)
-            .path("import")
-            .path(tableName)
-            .query(responseModel)
-            .invoke(HttpMethod.POST, in.getMandatoryBody());
-    }
-}

http://git-wip-us.apache.org/repos/asf/camel/blob/109da7c9/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/releases/fuji/FujiServiceNowProcessor.java
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/releases/fuji/FujiServiceNowProcessor.java b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/releases/fuji/FujiServiceNowProcessor.java
deleted file mode 100644
index 52b81bb..0000000
--- a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/releases/fuji/FujiServiceNowProcessor.java
+++ /dev/null
@@ -1,60 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.camel.component.servicenow.releases.fuji;
-
-import org.apache.camel.Exchange;
-import org.apache.camel.Message;
-import org.apache.camel.component.servicenow.AbstractServiceNowProcessor;
-import org.apache.camel.component.servicenow.ServiceNowConstants;
-import org.apache.camel.component.servicenow.ServiceNowEndpoint;
-import org.apache.camel.util.ObjectHelper;
-
-public abstract class FujiServiceNowProcessor extends AbstractServiceNowProcessor {
-    protected FujiServiceNowProcessor(ServiceNowEndpoint endpoint) throws Exception {
-        super(endpoint);
-    }
-
-    @Override
-    public void process(Exchange exchange) throws Exception {
-        final Message in = exchange.getIn();
-        final String tableName = getTableName(in);
-        final Class<?> requestModel = getRequestModel(in, tableName);
-        final Class<?> responseModel = getResponseModel(in, tableName);
-        final String apiVersion = getApiVersion(in);
-        final String action = in.getHeader(ServiceNowConstants.ACTION, String.class);
-        final String sysId = getSysID(in);
-
-        doProcess(
-            exchange,
-            ObjectHelper.notNull(requestModel, "requestModel"),
-            ObjectHelper.notNull(responseModel, "responseModel"),
-            apiVersion,
-            ObjectHelper.notNull(action, "action"),
-            ObjectHelper.notNull(tableName, "tableName"),
-            sysId);
-    }
-
-    protected abstract void doProcess(
-        Exchange exchange,
-        Class<?> requestModel,
-        Class<?> responseModel,
-        String apiVersion,
-        String action,
-        String tableName,
-        String sysId) throws Exception;
-}

http://git-wip-us.apache.org/repos/asf/camel/blob/109da7c9/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/releases/fuji/FujiServiceNowProducer.java
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/releases/fuji/FujiServiceNowProducer.java b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/releases/fuji/FujiServiceNowProducer.java
deleted file mode 100644
index 3d2f6cc..0000000
--- a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/releases/fuji/FujiServiceNowProducer.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.camel.component.servicenow.releases.fuji;
-
-import org.apache.camel.component.servicenow.AbstractServiceNowProducer;
-import org.apache.camel.component.servicenow.ServiceNowConstants;
-import org.apache.camel.component.servicenow.ServiceNowEndpoint;
-import org.apache.camel.component.servicenow.ServiceNowRelease;
-
-/**
- * The Fuji ServiceNow producer.
- */
-public class FujiServiceNowProducer extends AbstractServiceNowProducer {
-    public FujiServiceNowProducer(ServiceNowEndpoint endpoint) throws Exception {
-        super(endpoint, ServiceNowRelease.FUJI);
-
-        bind(ServiceNowConstants.RESOURCE_TABLE, new FujiServiceNowTableProcessor(endpoint));
-        bind(ServiceNowConstants.RESOURCE_AGGREGATE, new FujiServiceNowAggregateProcessor(endpoint));
-        bind(ServiceNowConstants.RESOURCE_IMPORT, new FujiServiceNowImportSetProcessor(endpoint));
-    }
-}

http://git-wip-us.apache.org/repos/asf/camel/blob/109da7c9/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/releases/fuji/FujiServiceNowTableProcessor.java
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/releases/fuji/FujiServiceNowTableProcessor.java b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/releases/fuji/FujiServiceNowTableProcessor.java
deleted file mode 100644
index 0781811..0000000
--- a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/releases/fuji/FujiServiceNowTableProcessor.java
+++ /dev/null
@@ -1,175 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.camel.component.servicenow.releases.fuji;
-
-import javax.ws.rs.HttpMethod;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.Response;
-
-import org.apache.camel.Exchange;
-import org.apache.camel.Message;
-import org.apache.camel.component.servicenow.ServiceNowConstants;
-import org.apache.camel.component.servicenow.ServiceNowEndpoint;
-import org.apache.camel.component.servicenow.ServiceNowParams;
-import org.apache.camel.util.ObjectHelper;
-
-class FujiServiceNowTableProcessor extends FujiServiceNowProcessor {
-    FujiServiceNowTableProcessor(ServiceNowEndpoint endpoint) throws Exception {
-        super(endpoint);
-    }
-
-    @Override
-    protected void doProcess(Exchange exchange, Class<?> requestModel, Class<?> responseModel, String apiVersion, String action, String tableName, String sysId) throws Exception {
-        Response response;
-        if (ObjectHelper.equal(ServiceNowConstants.ACTION_RETRIEVE, action, true)) {
-            response = retrieveRecord(exchange.getIn(), requestModel, responseModel, apiVersion, tableName, sysId);
-        } else if (ObjectHelper.equal(ServiceNowConstants.ACTION_CREATE, action, true)) {
-            response = createRecord(exchange.getIn(), requestModel, responseModel, apiVersion, tableName);
-        } else if (ObjectHelper.equal(ServiceNowConstants.ACTION_MODIFY, action, true)) {
-            response = modifyRecord(exchange.getIn(), requestModel, responseModel, apiVersion, tableName, sysId);
-        } else if (ObjectHelper.equal(ServiceNowConstants.ACTION_DELETE, action, true)) {
-            response = deleteRecord(exchange.getIn(), requestModel, responseModel, apiVersion, tableName, sysId);
-        } else if (ObjectHelper.equal(ServiceNowConstants.ACTION_UPDATE, action, true)) {
-            response = updateRecord(exchange.getIn(), requestModel, responseModel, apiVersion, tableName, sysId);
-        } else {
-            throw new IllegalArgumentException("Unknown action " + action);
-        }
-
-        setBodyAndHeaders(exchange.getIn(), responseModel, response);
-    }
-
-    /*
-     * GET
-     * https://instance.service-now.com/api/now/table/{tableName}
-     * https://instance.service-now.com/api/now/table/{tableName}/{sys_id}
-     */
-    private Response retrieveRecord(Message in, Class<?> requestModel, Class<?> responseModel, String apiVersion, String tableName, String sysId) throws Exception {
-        return ObjectHelper.isEmpty(sysId)
-            ? client.reset()
-                .types(MediaType.APPLICATION_JSON_TYPE)
-                .path("now")
-                .path(apiVersion)
-                .path("table")
-                .path(tableName)
-                .query(ServiceNowParams.SYSPARM_QUERY, in)
-                .query(ServiceNowParams.SYSPARM_DISPLAY_VALUE, in)
-                .query(ServiceNowParams.SYSPARM_EXCLUDE_REFERENCE_LINK, in)
-                .query(ServiceNowParams.SYSPARM_FIELDS, in)
-                .query(ServiceNowParams.SYSPARM_LIMIT, in)
-                .query(ServiceNowParams.SYSPARM_VIEW, in)
-                .query(responseModel)
-                .invoke(HttpMethod.GET)
-            : client.reset()
-                .types(MediaType.APPLICATION_JSON_TYPE)
-                .path("now")
-                .path(apiVersion)
-                .path("table")
-                .path(tableName)
-                .path(sysId)
-                .query(ServiceNowParams.SYSPARM_DISPLAY_VALUE, in)
-                .query(ServiceNowParams.SYSPARM_EXCLUDE_REFERENCE_LINK, in)
-                .query(ServiceNowParams.SYSPARM_FIELDS, in)
-                .query(ServiceNowParams.SYSPARM_VIEW, in)
-                .query(responseModel)
-                .invoke(HttpMethod.GET);
-    }
-
-    /*
-     * POST
-     * https://instance.service-now.com/api/now/table/{tableName}
-     */
-    private Response createRecord(Message in, Class<?> requestModel, Class<?> responseModel, String apiVersion, String tableName) throws Exception {
-        validateBody(in, requestModel);
-        return client.reset()
-            .types(MediaType.APPLICATION_JSON_TYPE)
-            .path("now")
-            .path(apiVersion)
-            .path("table")
-            .path(tableName)
-            .query(ServiceNowParams.SYSPARM_DISPLAY_VALUE, in)
-            .query(ServiceNowParams.SYSPARM_EXCLUDE_REFERENCE_LINK, in)
-            .query(ServiceNowParams.SYSPARM_FIELDS, in)
-            .query(ServiceNowParams.SYSPARM_INPUT_DISPLAY_VALUE, in)
-            .query(ServiceNowParams.SYSPARM_SUPPRESS_AUTO_SYS_FIELD, in)
-            .query(ServiceNowParams.SYSPARM_VIEW, in)
-            .query(responseModel)
-            .invoke(HttpMethod.POST, in.getMandatoryBody());
-    }
-
-    /*
-     * PUT
-     * https://instance.service-now.com/api/now/table/{tableName}/{sys_id}
-     */
-    private Response modifyRecord(Message in, Class<?> requestModel, Class<?> responseModel, String apiVersion, String tableName, String sysId) throws Exception {
-        validateBody(in, requestModel);
-        return client.reset()
-            .types(MediaType.APPLICATION_JSON_TYPE)
-            .path("now")
-            .path(apiVersion)
-            .path("table")
-            .path(tableName)
-            .path(ObjectHelper.notNull(sysId, "sysId"))
-            .query(ServiceNowParams.SYSPARM_DISPLAY_VALUE, in)
-            .query(ServiceNowParams.SYSPARM_EXCLUDE_REFERENCE_LINK, in)
-            .query(ServiceNowParams.SYSPARM_FIELDS, in)
-            .query(ServiceNowParams.SYSPARM_INPUT_DISPLAY_VALUE, in)
-            .query(ServiceNowParams.SYSPARM_SUPPRESS_AUTO_SYS_FIELD, in)
-            .query(ServiceNowParams.SYSPARM_VIEW, in)
-            .query(responseModel)
-            .invoke(HttpMethod.PUT, in.getMandatoryBody());
-    }
-
-    /*
-     * DELETE
-     * https://instance.service-now.com/api/now/table/{tableName}/{sys_id}
-     */
-    private Response deleteRecord(Message in, Class<?> requestModel, Class<?> responseModel, String apiVersion, String tableName, String sysId) throws Exception {
-        return client.reset()
-            .types(MediaType.APPLICATION_JSON_TYPE)
-            .path("now")
-            .path(apiVersion)
-            .path("table")
-            .path(tableName)
-            .path(ObjectHelper.notNull(sysId, "sysId"))
-            .query(responseModel)
-            .invoke(HttpMethod.DELETE);
-    }
-
-    /*
-     * PATCH
-     * http://instance.service-now.com/api/now/table/{tableName}/{sys_id}
-     */
-    private Response updateRecord(Message in, Class<?> requestModel, Class<?> responseModel, String apiVersion, String tableName, String sysId) throws Exception {
-        validateBody(in, requestModel);
-        return client.reset()
-            .types(MediaType.APPLICATION_JSON_TYPE)
-            .path("now")
-            .path(apiVersion)
-            .path("table")
-            .path(tableName)
-            .path(ObjectHelper.notNull(sysId, "sysId"))
-            .query(ServiceNowParams.SYSPARM_DISPLAY_VALUE, in)
-            .query(ServiceNowParams.SYSPARM_EXCLUDE_REFERENCE_LINK, in)
-            .query(ServiceNowParams.SYSPARM_FIELDS, in)
-            .query(ServiceNowParams.SYSPARM_INPUT_DISPLAY_VALUE, in)
-            .query(ServiceNowParams.SYSPARM_SUPPRESS_AUTO_SYS_FIELD, in)
-            .query(ServiceNowParams.SYSPARM_VIEW, in)
-            .query(responseModel)
-            .invoke("PATCH", in.getMandatoryBody());
-    }
-}

http://git-wip-us.apache.org/repos/asf/camel/blob/109da7c9/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/releases/helsinki/HelsinkiServiceNowAggregateProcessor.java
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/releases/helsinki/HelsinkiServiceNowAggregateProcessor.java b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/releases/helsinki/HelsinkiServiceNowAggregateProcessor.java
deleted file mode 100644
index d895718..0000000
--- a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/releases/helsinki/HelsinkiServiceNowAggregateProcessor.java
+++ /dev/null
@@ -1,77 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.camel.component.servicenow.releases.helsinki;
-
-import javax.ws.rs.HttpMethod;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.Response;
-
-import org.apache.camel.Exchange;
-import org.apache.camel.Message;
-import org.apache.camel.component.servicenow.AbstractServiceNowProcessor;
-import org.apache.camel.component.servicenow.ServiceNowEndpoint;
-import org.apache.camel.component.servicenow.ServiceNowParams;
-
-import static org.apache.camel.component.servicenow.ServiceNowConstants.ACTION_RETRIEVE;
-
-class HelsinkiServiceNowAggregateProcessor extends AbstractServiceNowProcessor {
-
-    HelsinkiServiceNowAggregateProcessor(ServiceNowEndpoint endpoint) throws Exception {
-        super(endpoint);
-
-        addDispatcher(ACTION_RETRIEVE, this::retrieveStats);
-    }
-
-    /*
-     * This method retrieves records for the specified table and performs aggregate
-     * functions on the returned values.
-     *
-     * Method:
-     * - GET
-     *
-     * URL Format:
-     * - /api/now/api/stats/{tableName}
-     */
-    private void retrieveStats(Exchange exchange) throws Exception {
-        final Message in = exchange.getIn();
-        final String tableName = getTableName(in);
-        final String apiVersion = getApiVersion(in);
-        final Class<?> responseModel = getResponseModel(in, tableName);
-
-        Response response = client.reset()
-            .types(MediaType.APPLICATION_JSON_TYPE)
-            .path("now")
-            .path(apiVersion)
-            .path("stats")
-            .path(tableName)
-            .query(ServiceNowParams.SYSPARM_QUERY, in)
-            .query(ServiceNowParams.SYSPARM_AVG_FIELDS, in)
-            .query(ServiceNowParams.SYSPARM_COUNT, in)
-            .query(ServiceNowParams.SYSPARM_MIN_FIELDS, in)
-            .query(ServiceNowParams.SYSPARM_QUERY, in)
-            .query(ServiceNowParams.SYSPARM_MAX_FIELDS, in)
-            .query(ServiceNowParams.SYSPARM_SUM_FIELDS, in)
-            .query(ServiceNowParams.SYSPARM_GROUP_BY, in)
-            .query(ServiceNowParams.SYSPARM_ORDER_BY, in)
-            .query(ServiceNowParams.SYSPARM_HAVING, in)
-            .query(ServiceNowParams.SYSPARM_DISPLAY_VALUE, in)
-            .query(responseModel)
-            .invoke(HttpMethod.GET);
-
-        setBodyAndHeaders(in, responseModel, response);
-    }
-}

http://git-wip-us.apache.org/repos/asf/camel/blob/109da7c9/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/releases/helsinki/HelsinkiServiceNowAttachmentProcessor.java
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/releases/helsinki/HelsinkiServiceNowAttachmentProcessor.java b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/releases/helsinki/HelsinkiServiceNowAttachmentProcessor.java
deleted file mode 100644
index b25bcc0..0000000
--- a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/releases/helsinki/HelsinkiServiceNowAttachmentProcessor.java
+++ /dev/null
@@ -1,179 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.camel.component.servicenow.releases.helsinki;
-
-import java.io.InputStream;
-import javax.ws.rs.HttpMethod;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.Response;
-
-import org.apache.camel.Exchange;
-import org.apache.camel.Message;
-import org.apache.camel.component.servicenow.AbstractServiceNowProcessor;
-import org.apache.camel.component.servicenow.ServiceNowConstants;
-import org.apache.camel.component.servicenow.ServiceNowEndpoint;
-import org.apache.camel.component.servicenow.ServiceNowParams;
-import org.apache.camel.util.ObjectHelper;
-
-import static org.apache.camel.component.servicenow.ServiceNowConstants.ACTION_CONTENT;
-import static org.apache.camel.component.servicenow.ServiceNowConstants.ACTION_DELETE;
-import static org.apache.camel.component.servicenow.ServiceNowConstants.ACTION_RETRIEVE;
-import static org.apache.camel.component.servicenow.ServiceNowConstants.ACTION_UPLOAD;
-
-public class HelsinkiServiceNowAttachmentProcessor extends AbstractServiceNowProcessor {
-    protected HelsinkiServiceNowAttachmentProcessor(ServiceNowEndpoint endpoint) throws Exception {
-        super(endpoint);
-
-        addDispatcher(ACTION_RETRIEVE, this::retrieveMeta);
-        addDispatcher(ACTION_CONTENT, this::retrieveContent);
-        addDispatcher(ACTION_UPLOAD, this::uploadContent);
-        addDispatcher(ACTION_DELETE, this::deleteContent);
-    }
-
-    /*
-     * This method gets the metadata for multiple attachments or for a specific
-     * attachment with a specific sys_id value
-     *
-     * Method:
-     * - GET
-     *
-     * URL Format:
-     * - /api/now/api/now/attachment
-     * - /api/now/api/now/attachment/{sys_id}
-     */
-    private void retrieveMeta(Exchange exchange) throws Exception {
-        final Message in = exchange.getIn();
-        final String tableName = getTableName(in);
-        final String apiVersion = getApiVersion(in);
-        final Class<?> responseModel = getResponseModel(in, tableName);
-        final String sysId = getSysID(in);
-
-        Response response = ObjectHelper.isEmpty(sysId)
-            ? client.reset()
-                .types(MediaType.APPLICATION_JSON_TYPE)
-                .path("now")
-                .path(apiVersion)
-                .path("attachment")
-                .query(ServiceNowParams.SYSPARM_QUERY, in)
-                .query(ServiceNowParams.SYSPARM_LIMIT, in)
-                .query(ServiceNowParams.SYSPARM_OFFSET, in)
-                .query(ServiceNowParams.SYSPARM_SUPPRESS_PAGINATION_HEADER, in)
-                .invoke(HttpMethod.GET)
-            : client.reset()
-                .types(MediaType.APPLICATION_JSON_TYPE)
-                .path("now")
-                .path(apiVersion)
-                .path("attachment")
-                .path(ObjectHelper.notNull(sysId, "sysId"))
-                .invoke(HttpMethod.GET);
-
-        setBodyAndHeaders(in, responseModel, response);
-    }
-
-    /*
-     * This method gets the binary file attachment with a specific sys_id value.
-     *
-     * Method:
-     * - GET
-     *
-     * URL Format:
-     * - /api/now/attachment/{sys_id}/file
-     */
-    private void retrieveContent(Exchange exchange) throws Exception {
-        final Message in = exchange.getIn();
-        final String apiVersion = getApiVersion(in);
-        final String sysId = getSysID(in);
-
-        Response response = client.reset()
-            .type(MediaType.APPLICATION_JSON_TYPE)
-            .accept("*/*")
-            .path("now")
-            .path(apiVersion)
-            .path("attachment")
-            .path(ObjectHelper.notNull(sysId, "sysId"))
-            .path("file")
-            .invoke(HttpMethod.GET);
-
-        // Header
-        setHeaders(in, null, response);
-
-        in.setBody(response.readEntity(InputStream.class));
-    }
-
-    /*
-     * This method uploads a binary file specified in the request body as an attachment.
-     *
-     * Method:
-     * - POST
-     *
-     * URL Format:
-     * - /api/now/api/now/attachment/file
-     */
-    private void uploadContent(Exchange exchange) throws Exception {
-        final Message in = exchange.getIn();
-        final String tableName = getTableName(in);
-        final String apiVersion = getApiVersion(in);
-        final Class<?> responseModel = getResponseModel(in, tableName);
-
-        Response response = client.reset()
-            .type(ObjectHelper.notNull(
-                in.getHeader(ServiceNowConstants.CONTENT_TYPE, String.class),
-                ServiceNowConstants.CONTENT_TYPE))
-            .accept(MediaType.APPLICATION_JSON_TYPE)
-            .path("now")
-            .path(apiVersion)
-            .path("attachment")
-            .path("file")
-            .query(ServiceNowParams.PARAM_FILE_NAME, in)
-            .query(ServiceNowParams.PARAM_TABLE_NAME, in)
-            .query(ServiceNowParams.PARAM_TABLE_SYS_ID, in)
-            .query(ServiceNowParams.PARAM_ENCRYPTION_CONTEXT, in)
-            .query(responseModel)
-            .invoke(HttpMethod.POST, in.getMandatoryBody(InputStream.class));
-
-        setBodyAndHeaders(in, responseModel, response);
-    }
-
-    /*
-     * This method deletes the attachment with a specific sys_id value.
-     *
-     * Method:
-     * - DELETE
-     *
-     * URL Format:
-     * - /api/now/attachment/{sys_id}
-     */
-    private void deleteContent(Exchange exchange) throws Exception {
-        final Message in = exchange.getIn();
-        final String tableName = getTableName(in);
-        final String apiVersion = getApiVersion(in);
-        final Class<?> responseModel = getResponseModel(in, tableName);
-        final String sysId = getSysID(in);
-
-        Response response = client.reset()
-            .types(MediaType.APPLICATION_JSON_TYPE)
-            .path("now")
-            .path(apiVersion)
-            .path("attachment")
-            .path(ObjectHelper.notNull(sysId, "sysId"))
-            .query(responseModel)
-            .invoke(HttpMethod.DELETE);
-
-        setBodyAndHeaders(in, responseModel, response);
-    }
-}

http://git-wip-us.apache.org/repos/asf/camel/blob/109da7c9/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/releases/helsinki/HelsinkiServiceNowImportSetProcessor.java
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/releases/helsinki/HelsinkiServiceNowImportSetProcessor.java b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/releases/helsinki/HelsinkiServiceNowImportSetProcessor.java
deleted file mode 100644
index feb5d47..0000000
--- a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/releases/helsinki/HelsinkiServiceNowImportSetProcessor.java
+++ /dev/null
@@ -1,143 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.camel.component.servicenow.releases.helsinki;
-
-import javax.ws.rs.HttpMethod;
-import javax.ws.rs.core.HttpHeaders;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.Response;
-
-import org.apache.camel.Exchange;
-import org.apache.camel.Message;
-import org.apache.camel.component.servicenow.AbstractServiceNowProcessor;
-import org.apache.camel.component.servicenow.ServiceNowConstants;
-import org.apache.camel.component.servicenow.ServiceNowEndpoint;
-import org.apache.camel.component.servicenow.ServiceNowParams;
-import org.apache.camel.component.servicenow.model.ImportSetResponse;
-import org.apache.camel.component.servicenow.model.ImportSetResult;
-import org.apache.camel.util.ObjectHelper;
-
-import static org.apache.camel.component.servicenow.ServiceNowConstants.ACTION_CREATE;
-import static org.apache.camel.component.servicenow.ServiceNowConstants.ACTION_RETRIEVE;
-
-class HelsinkiServiceNowImportSetProcessor extends AbstractServiceNowProcessor {
-
-    HelsinkiServiceNowImportSetProcessor(ServiceNowEndpoint endpoint) throws Exception {
-        super(endpoint);
-
-        addDispatcher(ACTION_RETRIEVE, this::retrieveRecord);
-        addDispatcher(ACTION_CREATE, this::createRecord);
-    }
-
-    /*
-     * GET
-     * https://instance.service-now.com/api/now/import/{tableName}/{sys_id}
-     */
-    private void retrieveRecord(Exchange exchange) throws Exception {
-        final Message in = exchange.getIn();
-        final String tableName = getTableName(in);
-        final String apiVersion = getApiVersion(in);
-        final Class<?> responseModel = getResponseModel(in, tableName);
-        final String sysId = getSysID(in);
-
-        Response response = client.reset()
-            .types(MediaType.APPLICATION_JSON_TYPE)
-            .path("now")
-            .path(apiVersion)
-            .path("import")
-            .path(ObjectHelper.notNull(tableName, "tableName"))
-            .path(ObjectHelper.notNull(sysId, "sysId"))
-            .query(responseModel)
-            .invoke(HttpMethod.GET);
-
-        setBodyAndHeaders(in, responseModel, response);
-    }
-
-    /*
-     * POST
-     * https://instance.service-now.com/api/now/import/{tableName}
-     */
-    private void createRecord(Exchange exchange) throws Exception {
-        final Message in = exchange.getIn();
-        final String tableName = getTableName(in);
-        final String apiVersion = getApiVersion(in);
-        final Class<?> requestModel = getRequestModel(in, tableName);
-        final boolean retrieve = in.getHeader(ServiceNowConstants.RETRIEVE_TARGET_RECORD, config::getRetrieveTargetRecordOnImport, Boolean.class);
-
-        Class<?> responseModel = getResponseModel(in, tableName);
-        Response response;
-
-        validateBody(in, requestModel);
-
-        if (retrieve) {
-            // If the endpoint is configured to retrieve the target record, the
-            // import response model is ignored and the response is ImportSetResponse
-
-            response = client.reset()
-                .types(MediaType.APPLICATION_JSON_TYPE)
-                .path("now")
-                .path(apiVersion)
-                .path("import")
-                .path(tableName)
-                .invoke(HttpMethod.POST, in.getMandatoryBody());
-
-            if (ObjectHelper.isNotEmpty(response.getHeaderString(HttpHeaders.CONTENT_TYPE))) {
-                for (ImportSetResult result : response.readEntity(ImportSetResponse.class).getResults()) {
-                    final String status = result.getStatus();
-                    final String table = result.getTable();
-                    final String sysId = result.getSysId();
-
-                    if (ObjectHelper.equalIgnoreCase("inserted", status)) {
-
-                        // If the endpoint is configured to retrieve the target
-                        // record, the response model is related to the target
-                        // table
-                        responseModel = getResponseModel(in, table);
-
-                        // Do get the record
-                        response = client.reset()
-                            .types(MediaType.APPLICATION_JSON_TYPE)
-                            .path("now")
-                            .path(apiVersion)
-                            .path("table")
-                            .path(ObjectHelper.notNull(table, "table"))
-                            .path(ObjectHelper.notNull(sysId, "sys_id"))
-                            .query(ServiceNowParams.SYSPARM_DISPLAY_VALUE, in)
-                            .query(ServiceNowParams.SYSPARM_EXCLUDE_REFERENCE_LINK, in)
-                            .query(ServiceNowParams.SYSPARM_FIELDS, in)
-                            .query(ServiceNowParams.SYSPARM_VIEW, in)
-                            .query(responseModel)
-                            .invoke(HttpMethod.GET);
-
-                        break;
-                    }
-                }
-            }
-        } else {
-            response = client.reset()
-                .types(MediaType.APPLICATION_JSON_TYPE)
-                .path("now")
-                .path(apiVersion)
-                .path("import")
-                .path(tableName)
-                .query(responseModel)
-                .invoke(HttpMethod.POST, in.getMandatoryBody());
-        }
-
-        setBodyAndHeaders(in, responseModel, response);
-    }
-}

http://git-wip-us.apache.org/repos/asf/camel/blob/109da7c9/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/releases/helsinki/HelsinkiServiceNowMiscProcessor.java
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/releases/helsinki/HelsinkiServiceNowMiscProcessor.java b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/releases/helsinki/HelsinkiServiceNowMiscProcessor.java
deleted file mode 100644
index c4e9d1b..0000000
--- a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/releases/helsinki/HelsinkiServiceNowMiscProcessor.java
+++ /dev/null
@@ -1,94 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.camel.component.servicenow.releases.helsinki;
-
-import javax.ws.rs.HttpMethod;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.Response;
-
-import org.apache.camel.Exchange;
-import org.apache.camel.Message;
-import org.apache.camel.component.servicenow.AbstractServiceNowProcessor;
-import org.apache.camel.component.servicenow.ServiceNowEndpoint;
-import org.apache.camel.component.servicenow.ServiceNowParams;
-
-import static org.apache.camel.component.servicenow.ServiceNowConstants.ACTION_CREATE;
-import static org.apache.camel.component.servicenow.ServiceNowConstants.ACTION_RETRIEVE;
-import static org.apache.camel.component.servicenow.ServiceNowConstants.ACTION_SUBJECT_IDENTIFY_RECONCILE;
-import static org.apache.camel.component.servicenow.ServiceNowConstants.ACTION_SUBJECT_USER_ROLE_INHERITANCE;
-
-class HelsinkiServiceNowMiscProcessor extends AbstractServiceNowProcessor {
-
-    HelsinkiServiceNowMiscProcessor(ServiceNowEndpoint endpoint) throws Exception {
-        super(endpoint);
-
-        addDispatcher(ACTION_RETRIEVE, ACTION_SUBJECT_USER_ROLE_INHERITANCE, this::retrieveUserRoleInheritance);
-        addDispatcher(ACTION_CREATE, ACTION_SUBJECT_IDENTIFY_RECONCILE, this::uploadIdentifyReconcile);
-    }
-
-    /*
-     * This method retrieves the roles the user has an determine what was inherited.
-     *
-     * Method:
-     * - GET
-     *
-     * URL Format:
-     * - /api/global/user_role_inheritance
-     */
-    private void retrieveUserRoleInheritance(Exchange exchange) throws Exception {
-        final Message in = exchange.getIn();
-        final Class<?> responseModel = getResponseModel(in);
-        final String apiVersion = getApiVersion(in);
-
-        Response response = client.reset()
-            .types(MediaType.APPLICATION_JSON_TYPE)
-            .path("global")
-            .path("user_role_inheritance")
-            .query(ServiceNowParams.PARAM_USER_SYS_ID, in)
-            .query(responseModel)
-            .invoke(HttpMethod.GET);
-
-        setBodyAndHeaders(in, responseModel, response);
-    }
-
-    /*
-     * This method retrieves the roles the user has an determine what was inherited.
-     *
-     * Method:
-     * - POST
-     *
-     * URL Format:
-     * - /api/now/identifyreconcile
-     */
-    private void uploadIdentifyReconcile(Exchange exchange) throws Exception {
-        final Message in = exchange.getIn();
-        final Class<?> responseModel = getResponseModel(in);
-        final String apiVersion = getApiVersion(in);
-
-        Response response = client.reset()
-            .types(MediaType.APPLICATION_JSON_TYPE)
-            .path("now")
-            .path(apiVersion)
-            .path("identifyreconcile")
-            .query(ServiceNowParams.SYSPARM_DATA_SOURCE, in)
-            .query(responseModel)
-            .invoke(HttpMethod.POST, in.getMandatoryBody());
-
-        setBodyAndHeaders(in, responseModel, response);
-    }
-}

http://git-wip-us.apache.org/repos/asf/camel/blob/109da7c9/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/releases/helsinki/HelsinkiServiceNowProducer.java
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/releases/helsinki/HelsinkiServiceNowProducer.java b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/releases/helsinki/HelsinkiServiceNowProducer.java
deleted file mode 100644
index 69a86af..0000000
--- a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/releases/helsinki/HelsinkiServiceNowProducer.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.camel.component.servicenow.releases.helsinki;
-
-import org.apache.camel.component.servicenow.AbstractServiceNowProducer;
-import org.apache.camel.component.servicenow.ServiceNowConstants;
-import org.apache.camel.component.servicenow.ServiceNowEndpoint;
-import org.apache.camel.component.servicenow.ServiceNowRelease;
-
-/**
- * The Helsinki ServiceNow producer.
- */
-public class HelsinkiServiceNowProducer extends AbstractServiceNowProducer {
-    public HelsinkiServiceNowProducer(ServiceNowEndpoint endpoint) throws Exception {
-        super(endpoint, ServiceNowRelease.HELSINKI);
-
-        bind(ServiceNowConstants.RESOURCE_TABLE, new HelsinkiServiceNowTableProcessor(endpoint));
-        bind(ServiceNowConstants.RESOURCE_AGGREGATE, new HelsinkiServiceNowAggregateProcessor(endpoint));
-        bind(ServiceNowConstants.RESOURCE_IMPORT, new HelsinkiServiceNowImportSetProcessor(endpoint));
-        bind(ServiceNowConstants.RESOURCE_ATTACHMENT, new HelsinkiServiceNowAttachmentProcessor(endpoint));
-        bind(ServiceNowConstants.RESOURCE_SCORECARDS, new HelsinkiServiceNowScorecardProcessor(endpoint));
-        bind(ServiceNowConstants.RESOURCE_MISC, new HelsinkiServiceNowMiscProcessor(endpoint));
-        bind(ServiceNowConstants.RESOURCE_SERVICE_CATALOG, new HelsinkiServiceNowServiceCatalogProcessor(endpoint));
-        bind(ServiceNowConstants.RESOURCE_SERVICE_CATALOG_ITEMS, new HelsinkiServiceNowServiceCatalogItemsProcessor(endpoint));
-        bind(ServiceNowConstants.RESOURCE_SERVICE_CATALOG_CARTS, new HelsinkiServiceNowServiceCatalogCartsProcessor(endpoint));
-        bind(ServiceNowConstants.RESOURCE_SERVICE_CATALOG_CATEGORIES, new HelsinkiServiceNowServiceCatalogCategoriesProcessor(endpoint));
-    }
-}

http://git-wip-us.apache.org/repos/asf/camel/blob/109da7c9/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/releases/helsinki/HelsinkiServiceNowScorecardProcessor.java
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/releases/helsinki/HelsinkiServiceNowScorecardProcessor.java b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/releases/helsinki/HelsinkiServiceNowScorecardProcessor.java
deleted file mode 100644
index 78cace8..0000000
--- a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/releases/helsinki/HelsinkiServiceNowScorecardProcessor.java
+++ /dev/null
@@ -1,87 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.camel.component.servicenow.releases.helsinki;
-
-import javax.ws.rs.HttpMethod;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.Response;
-
-import org.apache.camel.Exchange;
-import org.apache.camel.Message;
-import org.apache.camel.component.servicenow.AbstractServiceNowProcessor;
-import org.apache.camel.component.servicenow.ServiceNowEndpoint;
-import org.apache.camel.component.servicenow.ServiceNowParams;
-
-import static org.apache.camel.component.servicenow.ServiceNowConstants.ACTION_RETRIEVE;
-import static org.apache.camel.component.servicenow.ServiceNowConstants.ACTION_SUBJECT_PERFORMANCE_ANALYTICS;
-
-class HelsinkiServiceNowScorecardProcessor extends AbstractServiceNowProcessor {
-
-    HelsinkiServiceNowScorecardProcessor(ServiceNowEndpoint endpoint) throws Exception {
-        super(endpoint);
-
-        addDispatcher(ACTION_RETRIEVE, ACTION_SUBJECT_PERFORMANCE_ANALYTICS, this::retrievePerformanceAnalytics);
-    }
-
-    /*
-     * This method retrieves Performance Analytics scorecard details.
-     *
-     * Method:
-     * - GET
-     *
-     * URL Format:
-     * - /api/now/pa/scorecards
-     */
-    private void retrievePerformanceAnalytics(Exchange exchange) throws Exception {
-        final Message in = exchange.getIn();
-        final Class<?> responseModel = getResponseModel(in);
-        final String apiVersion = getApiVersion(in);
-
-        Response response = client.reset()
-            .types(MediaType.APPLICATION_JSON_TYPE)
-            .path("now")
-            .path(apiVersion)
-            .path("pa")
-            .path("scorecards")
-            .query(ServiceNowParams.SYSPARM_UUID, in)
-            .query(ServiceNowParams.SYSPARM_BREAKDOWN, in)
-            .query(ServiceNowParams.SYSPARM_INCLUDE_SCORES, in)
-            .query(ServiceNowParams.SYSPARM_INCLUDE_AGGREGATES, in)
-            .query(ServiceNowParams.SYSPARM_INCLUDE_AVAILABLE_BREAKDOWNS, in)
-            .query(ServiceNowParams.SYSPARM_INCLUDE_AVAILABLE_AGGREGATES, in)
-            .query(ServiceNowParams.SYSPARM_DISPLAY_VALUE, in)
-            .query(ServiceNowParams.SYSPARM_EXCLUDE_REFERENCE_LINK, in)
-            .query(ServiceNowParams.SYSPARM_FAVORITES, in)
-            .query(ServiceNowParams.SYSPARM_KEY, in)
-            .query(ServiceNowParams.SYSPARM_TARGET, in)
-            .query(ServiceNowParams.SYSPARM_DISPLAY, in)
-            .query(ServiceNowParams.SYSPARM_CONTAINS, in)
-            .query(ServiceNowParams.SYSPARM_TAGS, in)
-            .query(ServiceNowParams.SYSPARM_PER_PAGE, in)
-            .query(ServiceNowParams.SYSPARM_PAGE, in)
-            .query(ServiceNowParams.SYSPARM_SORT_BY, in)
-            .query(ServiceNowParams.SYSPARM_SORT_DIR, in)
-            .query(ServiceNowParams.SYSPARM_ELEMENTS_FILTER, in)
-            .query(ServiceNowParams.SYSPARM_BREAKDOWN_RELATION, in)
-            .query(ServiceNowParams.SYSPARM_INCLUDE_SCORE_NOTES, in)
-            .query(responseModel)
-            .invoke(HttpMethod.GET);
-
-        setBodyAndHeaders(in, responseModel, response);
-    }
-}

http://git-wip-us.apache.org/repos/asf/camel/blob/109da7c9/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/releases/helsinki/HelsinkiServiceNowServiceCatalogCartsProcessor.java
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/releases/helsinki/HelsinkiServiceNowServiceCatalogCartsProcessor.java b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/releases/helsinki/HelsinkiServiceNowServiceCatalogCartsProcessor.java
deleted file mode 100644
index d890172..0000000
--- a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/releases/helsinki/HelsinkiServiceNowServiceCatalogCartsProcessor.java
+++ /dev/null
@@ -1,218 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.camel.component.servicenow.releases.helsinki;
-
-import javax.ws.rs.HttpMethod;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.Response;
-
-import org.apache.camel.Exchange;
-import org.apache.camel.Message;
-import org.apache.camel.component.servicenow.AbstractServiceNowProcessor;
-import org.apache.camel.component.servicenow.ServiceNowEndpoint;
-import org.apache.camel.component.servicenow.ServiceNowParams;
-
-import static org.apache.camel.component.servicenow.ServiceNowConstants.ACTION_DELETE;
-import static org.apache.camel.component.servicenow.ServiceNowConstants.ACTION_RETRIEVE;
-import static org.apache.camel.component.servicenow.ServiceNowConstants.ACTION_SUBJECT_CHECKOUT;
-import static org.apache.camel.component.servicenow.ServiceNowConstants.ACTION_SUBJECT_DELIVERY_ADDRESS;
-import static org.apache.camel.component.servicenow.ServiceNowConstants.ACTION_UPDATE;
-    
-class HelsinkiServiceNowServiceCatalogCartsProcessor extends AbstractServiceNowProcessor {
-
-    HelsinkiServiceNowServiceCatalogCartsProcessor(ServiceNowEndpoint endpoint) throws Exception {
-        super(endpoint);
-
-        addDispatcher(ACTION_RETRIEVE, ACTION_SUBJECT_DELIVERY_ADDRESS, this::retrieveDeliveryAddress);
-        addDispatcher(ACTION_RETRIEVE, ACTION_SUBJECT_CHECKOUT, this::retrieveCheckoutCart);
-        addDispatcher(ACTION_RETRIEVE, ACTION_SUBJECT_CHECKOUT, this::retrieveCarts);
-        addDispatcher(ACTION_UPDATE, ACTION_SUBJECT_CHECKOUT, this::checkoutCart);
-        addDispatcher(ACTION_UPDATE, this::updateCart);
-        addDispatcher(ACTION_DELETE, this::deleteCart);
-    }
-
-    /*
-     * This method retrieves the default list of cart contents, cart details,
-     * and price shown on the two-step checkout page.
-     *
-     * Method:
-     * - GET
-     *
-     * URL Format:
-     * - /sn_sc/servicecatalog/cart
-     */
-    private void retrieveCarts(Exchange exchange) throws Exception {
-        final Message in = exchange.getIn();
-        final Class<?> responseModel = getResponseModel(in);
-        final String apiVersion = getApiVersion(in);
-
-        Response response = client.reset()
-            .types(MediaType.APPLICATION_JSON_TYPE)
-            .path("sn_sc")
-            .path(apiVersion)
-            .path("servicecatalog")
-            .path("cart")
-            .query(responseModel)
-            .invoke(HttpMethod.GET);
-
-        setBodyAndHeaders(in, responseModel, response);
-    }
-
-    /*
-     * This method retrieves the shipping address of the requested user.
-     *
-     * Method:
-     * - GET
-     *
-     * URL Format:
-     * - /sn_sc/servicecatalog/cart/delivery_address/{user_id}
-     */
-    private void retrieveDeliveryAddress(Exchange exchange) throws Exception {
-        final Message in = exchange.getIn();
-        final Class<?> responseModel = getResponseModel(in);
-        final String apiVersion = getApiVersion(in);
-
-        Response response = client.reset()
-            .types(MediaType.APPLICATION_JSON_TYPE)
-            .path("sn_sc")
-            .path(apiVersion)
-            .path("servicecatalog")
-            .path("cart")
-            .path("delivery_address")
-            .path(getMandatoryRequestParamFromHeader(ServiceNowParams.PARAM_USER_ID, in))
-            .query(responseModel)
-            .invoke(HttpMethod.GET);
-
-        setBodyAndHeaders(in, responseModel, response);
-    }
-
-    /*
-     * This method edits and updates any item in the cart.
-     *
-     * Method:
-     * - POST
-     *
-     * URL Format:
-     * - /sn_sc/servicecatalog/cart/{cart_item_id}
-     */
-    private void updateCart(Exchange exchange) throws Exception {
-        final Message in = exchange.getIn();
-        final Class<?> responseModel = getResponseModel(in);
-        final String apiVersion = getApiVersion(in);
-
-        Response response = client.reset()
-            .types(MediaType.APPLICATION_JSON_TYPE)
-            .path("sn_sc")
-            .path(apiVersion)
-            .path("servicecatalog")
-            .path("cart")
-            .path(getMandatoryRequestParamFromHeader(ServiceNowParams.PARAM_CART_ITEM_ID, in))
-            .query(responseModel)
-            .invoke(HttpMethod.POST, in.getMandatoryBody());
-
-        setBodyAndHeaders(in, responseModel, response);
-    }
-
-    /*
-     * This method deletes the cart and contents of the cart for a given user
-     * role and sys_id.
-     *
-     * Method:
-     * - DELETE
-     *
-     * URL Format:
-     * - /sn_sc/servicecatalog/cart/{sys_id}/empty
-     */
-    private void deleteCart(Exchange exchange) throws Exception {
-        final Message in = exchange.getIn();
-        final Class<?> responseModel = getResponseModel(in);
-        final String apiVersion = getApiVersion(in);
-
-        Response response = client.reset()
-            .types(MediaType.APPLICATION_JSON_TYPE)
-            .path("sn_sc")
-            .path(apiVersion)
-            .path("servicecatalog")
-            .path("cart")
-            .path(getMandatoryRequestParamFromHeader(ServiceNowParams.PARAM_SYS_ID, in))
-            .path("empty")
-            .query(responseModel)
-            .invoke(HttpMethod.DELETE);
-
-        setBodyAndHeaders(in, responseModel, response);
-    }
-
-    /*
-     * This method retrieves the checkout cart details based on the two-step
-     * checkout process enabled or disabled. If the user enables two-step checkout,
-     * the method returns cart order status and all the information required for
-     * two-step checkout. If the user disables two-step checkout, the method
-     * checks out the cart and returns the request number and request order ID.
-     *
-     * Method:
-     * - POST
-     *
-     * URL Format:
-     * - /sn_sc/servicecatalog/cart/checkout
-     */
-    private void retrieveCheckoutCart(Exchange exchange) throws Exception {
-        final Message in = exchange.getIn();
-        final Class<?> responseModel = getResponseModel(in);
-        final String apiVersion = getApiVersion(in);
-
-        Response response = client.reset()
-            .types(MediaType.APPLICATION_JSON_TYPE)
-            .path("sn_sc")
-            .path(apiVersion)
-            .path("servicecatalog")
-            .path("cart")
-            .path("checkout")
-            .query(responseModel)
-            .invoke(HttpMethod.POST);
-
-        setBodyAndHeaders(in, responseModel, response);
-    }
-
-    /*
-     * This method checks out the user cart, whether two-step parameter is
-     * enabled or disabled.
-     *
-     * Method:
-     * - POST
-     *
-     * URL Format:
-     * - /sn_sc/servicecatalog/cart/submit_order
-     */
-    private void checkoutCart(Exchange exchange) throws Exception {
-        final Message in = exchange.getIn();
-        final Class<?> responseModel = getResponseModel(in);
-        final String apiVersion = getApiVersion(in);
-
-        Response response = client.reset()
-            .types(MediaType.APPLICATION_JSON_TYPE)
-            .path("sn_sc")
-            .path(apiVersion)
-            .path("servicecatalog")
-            .path("cart")
-            .path("submit_order")
-            .query(responseModel)
-            .invoke(HttpMethod.POST);
-
-        setBodyAndHeaders(in, responseModel, response);
-    }
-}

http://git-wip-us.apache.org/repos/asf/camel/blob/109da7c9/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/releases/helsinki/HelsinkiServiceNowServiceCatalogCategoriesProcessor.java
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/releases/helsinki/HelsinkiServiceNowServiceCatalogCategoriesProcessor.java b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/releases/helsinki/HelsinkiServiceNowServiceCatalogCategoriesProcessor.java
deleted file mode 100644
index bd5e905..0000000
--- a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/releases/helsinki/HelsinkiServiceNowServiceCatalogCategoriesProcessor.java
+++ /dev/null
@@ -1,69 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.camel.component.servicenow.releases.helsinki;
-
-import javax.ws.rs.HttpMethod;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.Response;
-
-import org.apache.camel.Exchange;
-import org.apache.camel.Message;
-import org.apache.camel.component.servicenow.AbstractServiceNowProcessor;
-import org.apache.camel.component.servicenow.ServiceNowEndpoint;
-import org.apache.camel.component.servicenow.ServiceNowParams;
-import org.apache.camel.util.ObjectHelper;
-
-import static org.apache.camel.component.servicenow.ServiceNowConstants.ACTION_RETRIEVE;
-
-class HelsinkiServiceNowServiceCatalogCategoriesProcessor extends AbstractServiceNowProcessor {
-
-    HelsinkiServiceNowServiceCatalogCategoriesProcessor(ServiceNowEndpoint endpoint) throws Exception {
-        super(endpoint);
-
-        addDispatcher(ACTION_RETRIEVE, this::retrieveCategory);
-    }
-
-    /*
-     * This method retrieves all the information about a requested category.
-     *
-     * Method:
-     * - GET
-     *
-     * URL Format:
-     * - /sn_sc/servicecatalog/categories/{sys_id}
-     */
-    private void retrieveCategory(Exchange exchange) throws Exception {
-        final Message in = exchange.getIn();
-        final Class<?> responseModel = getResponseModel(in);
-        final String sysId = getSysID(in);
-        final String apiVersion = getApiVersion(in);
-
-        Response response = client.reset()
-            .types(MediaType.APPLICATION_JSON_TYPE)
-            .path("sn_sc")
-            .path(apiVersion)
-            .path("servicecatalog")
-            .path("categories")
-            .path(ObjectHelper.notNull(sysId, "sysId"))
-            .query(ServiceNowParams.SYSPARM_VIEW, in)
-            .query(responseModel)
-            .invoke(HttpMethod.GET);
-
-        setBodyAndHeaders(in, responseModel, response);
-    }
-}

http://git-wip-us.apache.org/repos/asf/camel/blob/109da7c9/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/releases/helsinki/HelsinkiServiceNowServiceCatalogItemsProcessor.java
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/releases/helsinki/HelsinkiServiceNowServiceCatalogItemsProcessor.java b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/releases/helsinki/HelsinkiServiceNowServiceCatalogItemsProcessor.java
deleted file mode 100644
index c0520c1..0000000
--- a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/releases/helsinki/HelsinkiServiceNowServiceCatalogItemsProcessor.java
+++ /dev/null
@@ -1,216 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.camel.component.servicenow.releases.helsinki;
-
-import javax.ws.rs.HttpMethod;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.Response;
-
-import org.apache.camel.Exchange;
-import org.apache.camel.Message;
-import org.apache.camel.component.servicenow.AbstractServiceNowProcessor;
-import org.apache.camel.component.servicenow.ServiceNowEndpoint;
-import org.apache.camel.component.servicenow.ServiceNowParams;
-import org.apache.camel.util.ObjectHelper;
-
-import static org.apache.camel.component.servicenow.ServiceNowConstants.ACTION_CREATE;
-import static org.apache.camel.component.servicenow.ServiceNowConstants.ACTION_RETRIEVE;
-import static org.apache.camel.component.servicenow.ServiceNowConstants.ACTION_SUBJECT_CART;
-import static org.apache.camel.component.servicenow.ServiceNowConstants.ACTION_SUBJECT_CHECKOUT_GUIDE;
-import static org.apache.camel.component.servicenow.ServiceNowConstants.ACTION_SUBJECT_PRODUCER;
-import static org.apache.camel.component.servicenow.ServiceNowConstants.ACTION_SUBJECT_SUBMIT_GUIDE;
-
-class HelsinkiServiceNowServiceCatalogItemsProcessor extends AbstractServiceNowProcessor {
-
-    HelsinkiServiceNowServiceCatalogItemsProcessor(ServiceNowEndpoint endpoint) throws Exception {
-        super(endpoint);
-
-        addDispatcher(ACTION_RETRIEVE, ACTION_SUBJECT_SUBMIT_GUIDE, this::submitItemGuide);
-        addDispatcher(ACTION_RETRIEVE, ACTION_SUBJECT_CHECKOUT_GUIDE, this::checkoutItemGuide);
-        addDispatcher(ACTION_RETRIEVE, this::retrieveItems);
-        addDispatcher(ACTION_CREATE, ACTION_SUBJECT_CART, this::addItemToCart);
-        addDispatcher(ACTION_CREATE, ACTION_SUBJECT_PRODUCER, this::submitItemProducer);
-    }
-
-    /*
-     * This method retrieves a list of catalogs to which the user has access or
-     * a single one if sys_id is defined.
-     *
-     * Method:
-     * - GET
-     *
-     * URL Format:
-     * - /sn_sc/servicecatalog/items
-     * - /sn_sc/servicecatalog/items/{sys_id}
-     */
-    private void retrieveItems(Exchange exchange) throws Exception {
-        final Message in = exchange.getIn();
-        final Class<?> responseModel = getResponseModel(in);
-        final String sysId = getSysID(in);
-        final String apiVersion = getApiVersion(in);
-
-        Response response = ObjectHelper.isEmpty(sysId)
-            ? client.reset()
-                .types(MediaType.APPLICATION_JSON_TYPE)
-                .path("sn_sc")
-                .path(apiVersion)
-                .path("servicecatalog")
-                .path("items")
-                .query(ServiceNowParams.SYSPARM_CATEGORY, in)
-                .query(ServiceNowParams.SYSPARM_TYPE, in)
-                .query(ServiceNowParams.SYSPARM_LIMIT, in)
-                .query(ServiceNowParams.SYSPARM_TEXT, in)
-                .query(ServiceNowParams.SYSPARM_OFFSET, in)
-                .query(ServiceNowParams.SYSPARM_CATALOG, in)
-                .query(ServiceNowParams.SYSPARM_VIEW, in)
-                .query(responseModel)
-                .invoke(HttpMethod.GET)
-            : client.reset()
-                .types(MediaType.APPLICATION_JSON_TYPE)
-                .path("sn_sc")
-                .path(apiVersion)
-                .path("items")
-                .path("items")
-                .path(sysId)
-                .query(ServiceNowParams.SYSPARM_VIEW, in)
-                .query(responseModel)
-                .invoke(HttpMethod.GET);
-
-        setBodyAndHeaders(in, responseModel, response);
-    }
-
-    /*
-     * This method retrieves a list of items based on the needs described for an
-     * order guide.
-     *
-     * Method:
-     * - POST
-     *
-     * URL Format:
-     * - /sn_sc/servicecatalog/items/{sys_id}/submit_guide
-     */
-    private void submitItemGuide(Exchange exchange) throws Exception {
-        final Message in = exchange.getIn();
-        final Class<?> responseModel = getResponseModel(in);
-        final String sysId = getSysID(in);
-        final String apiVersion = getApiVersion(in);
-
-        Response response =  client.reset()
-            .types(MediaType.APPLICATION_JSON_TYPE)
-            .path("sn_sc")
-            .path(apiVersion)
-            .path("servicecatalog")
-            .path("items")
-            .path(ObjectHelper.notNull(sysId, "sysId"))
-            .path("submit_guide")
-            .query(ServiceNowParams.SYSPARM_VIEW, in)
-            .query(responseModel)
-            .invoke(HttpMethod.POST, in.getMandatoryBody());
-
-        setBodyAndHeaders(in, responseModel, response);
-    }
-
-    /*
-     * This method retrieves an array of contents requested for checkout.
-     *
-     * Method:
-     * - POST
-     *
-     * URL Format:
-     * - /sn_sc/servicecatalog/items/{sys_id}/checkout_guide
-     */
-    private void checkoutItemGuide(Exchange exchange) throws Exception {
-        final Message in = exchange.getIn();
-        final Class<?> responseModel = getResponseModel(in);
-        final String sysId = getSysID(in);
-        final String apiVersion = getApiVersion(in);
-
-        Response response = client.reset()
-            .types(MediaType.APPLICATION_JSON_TYPE)
-            .path("sn_sc")
-            .path(apiVersion)
-            .path("servicecatalog")
-            .path("items")
-            .path(ObjectHelper.notNull(sysId, "sysId"))
-            .path("submit_guide")
-            .query(responseModel)
-            .invoke(HttpMethod.POST, in.getMandatoryBody());
-
-        setBodyAndHeaders(in, responseModel, response);
-    }
-
-    /*
-     * This method adds an item to the cart of the current user.
-     *
-     * Method:
-     * - POST
-     *
-     * URL Format:
-     * - /sn_sc/servicecatalog/items/{sys_id}/add_to_cart
-     */
-    private void addItemToCart(Exchange exchange) throws Exception {
-        final Message in = exchange.getIn();
-        final Class<?> responseModel = getResponseModel(in);
-        final String sysId = getSysID(in);
-        final String apiVersion = getApiVersion(in);
-
-        Response response = client.reset()
-            .types(MediaType.APPLICATION_JSON_TYPE)
-            .path("sn_sc")
-            .path(apiVersion)
-            .path("servicecatalog")
-            .path("items")
-            .path(ObjectHelper.notNull(sysId, "sysId"))
-            .path("add_to_cart")
-            .query(responseModel)
-            .invoke(HttpMethod.POST);
-
-        setBodyAndHeaders(in, responseModel, response);
-    }
-
-    /*
-     * This method creates a record and returns the Table API relative path and
-     * redirect url to access the created record.
-     *
-     * Method:
-     * - POST
-     *
-     * URL Format:
-     * - /sn_sc/servicecatalog/items/{sys_id}/submit_producer
-     */
-    private void submitItemProducer(Exchange exchange) throws Exception {
-        final Message in = exchange.getIn();
-        final Class<?> responseModel = getResponseModel(in);
-        final String sysId = getSysID(in);
-        final String apiVersion = getApiVersion(in);
-
-        Response response = client.reset()
-            .types(MediaType.APPLICATION_JSON_TYPE)
-            .path("sn_sc")
-            .path(apiVersion)
-            .path("servicecatalog")
-            .path("items")
-            .path(ObjectHelper.notNull(sysId, "sysId"))
-            .path("submit_producer")
-            .query(ServiceNowParams.SYSPARM_VIEW, in)
-            .query(responseModel)
-            .invoke(HttpMethod.POST, in.getMandatoryBody());
-
-        setBodyAndHeaders(in, responseModel, response);
-    }
-}


[08/19] camel git commit: CAMEL-11556: ServiceNow : add annotations on the model to customize sysparms

Posted by lb...@apache.org.
CAMEL-11556: ServiceNow : add annotations on the model to customize sysparms


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

Branch: refs/heads/master
Commit: 05aa433ec8b59cdee7cfb929689b6455a9fc30ae
Parents: 79172c3
Author: lburgazzoli <lb...@gmail.com>
Authored: Tue Aug 1 19:50:17 2017 +0200
Committer: lburgazzoli <lb...@gmail.com>
Committed: Fri Aug 4 18:09:05 2017 +0200

----------------------------------------------------------------------
 .../component/servicenow/ServiceNowClient.java  | 29 ++++++++-
 .../annotations/ServiceNowSysParm.java          | 32 ++++++++++
 .../annotations/ServiceNowSysParms.java         | 28 +++++++++
 .../fuji/FujiServiceNowAggregateProcessor.java  |  5 +-
 .../fuji/FujiServiceNowImportSetProcessor.java  |  8 ++-
 .../fuji/FujiServiceNowTableProcessor.java      |  6 ++
 .../HelsinkiServiceNowAggregateProcessor.java   |  1 +
 .../HelsinkiServiceNowAttachmentProcessor.java  |  2 +
 .../HelsinkiServiceNowImportSetProcessor.java   |  2 +
 .../HelsinkiServiceNowMiscProcessor.java        |  2 +
 .../HelsinkiServiceNowScorecardProcessor.java   |  1 +
 ...iServiceNowServiceCatalogCartsProcessor.java |  6 ++
 ...iceNowServiceCatalogCategoriesProcessor.java |  1 +
 ...iServiceNowServiceCatalogItemsProcessor.java |  6 ++
 ...lsinkiServiceNowServiceCatalogProcessor.java |  3 +
 .../HelsinkiServiceNowTableProcessor.java       |  9 +++
 .../servicenow/ServiceNowTableTest.java         | 33 ++++++++++
 .../servicenow/model/IncidentWithParms.java     | 64 ++++++++++++++++++++
 18 files changed, 232 insertions(+), 6 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/camel/blob/05aa433e/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowClient.java
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowClient.java b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowClient.java
index 6157ecf..5128797 100644
--- a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowClient.java
+++ b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowClient.java
@@ -26,15 +26,21 @@ import javax.ws.rs.core.Response;
 import com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider;
 import org.apache.camel.CamelContext;
 import org.apache.camel.Message;
+import org.apache.camel.component.servicenow.annotations.ServiceNowSysParm;
 import org.apache.camel.component.servicenow.auth.AuthenticationRequestFilter;
+import org.apache.camel.util.ObjectHelper;
 import org.apache.camel.util.jsse.SSLContextParameters;
 import org.apache.cxf.configuration.jsse.TLSClientParameters;
 import org.apache.cxf.configuration.security.ProxyAuthorizationPolicy;
 import org.apache.cxf.jaxrs.client.WebClient;
 import org.apache.cxf.transport.http.HTTPConduit;
 import org.apache.cxf.transports.http.configuration.HTTPClientPolicy;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 public final class ServiceNowClient {
+    private static final Logger LOGGER = LoggerFactory.getLogger(ServiceNowClient.class);
+
     private final CamelContext camelContext;
     private final ServiceNowConfiguration configuration;
     private final WebClient client;
@@ -68,7 +74,7 @@ public final class ServiceNowClient {
     }
 
     public ServiceNowClient path(Object path) {
-        if (path != null) {
+        if (ObjectHelper.isNotEmpty(path)) {
             client.path(path);
         }
 
@@ -114,6 +120,27 @@ public final class ServiceNowClient {
         return this;
     }
 
+    public ServiceNowClient query(Class<?> model) {
+        if (model != null) {
+            String name;
+            String value;
+
+            for (ServiceNowSysParm parm : model.getAnnotationsByType(ServiceNowSysParm.class)) {
+                name = parm.name();
+                value = parm.value();
+
+                // SysParms defined on model have precedence and replace query param
+                // with same name set via Message headers.
+                if (ObjectHelper.isNotEmpty(name) && ObjectHelper.isNotEmpty(value)) {
+                    LOGGER.debug("Replace query param {} with value {}", name, value);
+                    client.replaceQueryParam(name, value);
+                }
+            }
+        }
+
+        return this;
+    }
+
     public Response invoke(String httpMethod) throws Exception {
         return invoke(client, httpMethod, null);
     }

http://git-wip-us.apache.org/repos/asf/camel/blob/05aa433e/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/annotations/ServiceNowSysParm.java
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/annotations/ServiceNowSysParm.java b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/annotations/ServiceNowSysParm.java
new file mode 100644
index 0000000..361e741
--- /dev/null
+++ b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/annotations/ServiceNowSysParm.java
@@ -0,0 +1,32 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.servicenow.annotations;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Repeatable;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Target({ElementType.TYPE})
+@Retention(RetentionPolicy.RUNTIME)
+@Repeatable(ServiceNowSysParms.class)
+public @interface ServiceNowSysParm {
+    String name();
+
+    String value();
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/05aa433e/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/annotations/ServiceNowSysParms.java
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/annotations/ServiceNowSysParms.java b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/annotations/ServiceNowSysParms.java
new file mode 100644
index 0000000..236ba8b
--- /dev/null
+++ b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/annotations/ServiceNowSysParms.java
@@ -0,0 +1,28 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.servicenow.annotations;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Target({ElementType.TYPE})
+@Retention(RetentionPolicy.RUNTIME)
+public @interface ServiceNowSysParms {
+    ServiceNowSysParm[] value();
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/05aa433e/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/releases/fuji/FujiServiceNowAggregateProcessor.java
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/releases/fuji/FujiServiceNowAggregateProcessor.java b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/releases/fuji/FujiServiceNowAggregateProcessor.java
index 0b4f32a..7fe9352 100644
--- a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/releases/fuji/FujiServiceNowAggregateProcessor.java
+++ b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/releases/fuji/FujiServiceNowAggregateProcessor.java
@@ -38,7 +38,7 @@ class FujiServiceNowAggregateProcessor extends FujiServiceNowProcessor {
     protected void doProcess(Exchange exchange, Class<?> requestModel, Class<?> responseModel, String action, String apiVersion, String tableName, String sysId) throws Exception {
         Response response;
         if (ObjectHelper.equal(ServiceNowConstants.ACTION_RETRIEVE, action, true)) {
-            response = retrieveStats(exchange.getIn(), tableName);
+            response = retrieveStats(exchange.getIn(), requestModel, responseModel, tableName);
         } else {
             throw new IllegalArgumentException("Unknown action " + action);
         }
@@ -46,7 +46,7 @@ class FujiServiceNowAggregateProcessor extends FujiServiceNowProcessor {
         setBodyAndHeaders(exchange.getIn(), responseModel, response);
     }
 
-    private Response retrieveStats(Message in, String tableName) throws Exception {
+    private Response retrieveStats(Message in, Class<?> requestModel, Class<?> responseModel, String tableName) throws Exception {
         final String apiVersion = getApiVersion(in);
 
         return client.reset()
@@ -66,6 +66,7 @@ class FujiServiceNowAggregateProcessor extends FujiServiceNowProcessor {
             .query(ServiceNowParams.SYSPARM_ORDER_BY, in)
             .query(ServiceNowParams.SYSPARM_HAVING, in)
             .query(ServiceNowParams.SYSPARM_DISPLAY_VALUE, in)
+            .query(responseModel)
             .invoke(HttpMethod.GET);
     }
 }

http://git-wip-us.apache.org/repos/asf/camel/blob/05aa433e/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/releases/fuji/FujiServiceNowImportSetProcessor.java
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/releases/fuji/FujiServiceNowImportSetProcessor.java b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/releases/fuji/FujiServiceNowImportSetProcessor.java
index 2f09d3e..4bace68 100644
--- a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/releases/fuji/FujiServiceNowImportSetProcessor.java
+++ b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/releases/fuji/FujiServiceNowImportSetProcessor.java
@@ -37,7 +37,7 @@ class FujiServiceNowImportSetProcessor extends FujiServiceNowProcessor {
     protected void doProcess(Exchange exchange, Class<?> requestModel, Class<?> responseModel, String action, String apiVersion, String tableName, String sysId) throws Exception {
         Response response;
         if (ObjectHelper.equal(ServiceNowConstants.ACTION_RETRIEVE, action, true)) {
-            response = retrieveRecord(exchange.getIn(), apiVersion, tableName, sysId);
+            response = retrieveRecord(exchange.getIn(), requestModel, responseModel, apiVersion, tableName, sysId);
         } else if (ObjectHelper.equal(ServiceNowConstants.ACTION_CREATE, action, true)) {
             response = createRecord(exchange.getIn(), requestModel, responseModel, apiVersion, tableName);
         } else {
@@ -51,7 +51,7 @@ class FujiServiceNowImportSetProcessor extends FujiServiceNowProcessor {
      * GET
      * https://instance.service-now.com/api/now/import/{tableName}/{sys_id}
      */
-    private Response retrieveRecord(Message in, String apiVersion, String tableName, String sysId) throws Exception {
+    private Response retrieveRecord(Message in, Class<?> requestModel, Class<?> responseModel, String apiVersion, String tableName, String sysId) throws Exception {
         return client.reset()
             .types(MediaType.APPLICATION_JSON_TYPE)
             .path("now")
@@ -59,6 +59,7 @@ class FujiServiceNowImportSetProcessor extends FujiServiceNowProcessor {
             .path("import")
             .path(tableName)
             .path(ObjectHelper.notNull(sysId, "sysId"))
+            .query(responseModel)
             .invoke(HttpMethod.GET);
     }
 
@@ -66,7 +67,7 @@ class FujiServiceNowImportSetProcessor extends FujiServiceNowProcessor {
      * POST
      * https://instance.service-now.com/api/now/import/{tableName}
      */
-    private Response createRecord(Message in, Class<?> requestModel, Class<?> responseModell, String apiVersion, String tableName) throws Exception {
+    private Response createRecord(Message in, Class<?> requestModel, Class<?> responseModel, String apiVersion, String tableName) throws Exception {
         validateBody(in, requestModel);
         return client.reset()
             .types(MediaType.APPLICATION_JSON_TYPE)
@@ -74,6 +75,7 @@ class FujiServiceNowImportSetProcessor extends FujiServiceNowProcessor {
             .path(apiVersion)
             .path("import")
             .path(tableName)
+            .query(responseModel)
             .invoke(HttpMethod.POST, in.getMandatoryBody());
     }
 }

http://git-wip-us.apache.org/repos/asf/camel/blob/05aa433e/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/releases/fuji/FujiServiceNowTableProcessor.java
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/releases/fuji/FujiServiceNowTableProcessor.java b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/releases/fuji/FujiServiceNowTableProcessor.java
index 7fb7c2a..0781811 100644
--- a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/releases/fuji/FujiServiceNowTableProcessor.java
+++ b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/releases/fuji/FujiServiceNowTableProcessor.java
@@ -72,6 +72,7 @@ class FujiServiceNowTableProcessor extends FujiServiceNowProcessor {
                 .query(ServiceNowParams.SYSPARM_FIELDS, in)
                 .query(ServiceNowParams.SYSPARM_LIMIT, in)
                 .query(ServiceNowParams.SYSPARM_VIEW, in)
+                .query(responseModel)
                 .invoke(HttpMethod.GET)
             : client.reset()
                 .types(MediaType.APPLICATION_JSON_TYPE)
@@ -84,6 +85,7 @@ class FujiServiceNowTableProcessor extends FujiServiceNowProcessor {
                 .query(ServiceNowParams.SYSPARM_EXCLUDE_REFERENCE_LINK, in)
                 .query(ServiceNowParams.SYSPARM_FIELDS, in)
                 .query(ServiceNowParams.SYSPARM_VIEW, in)
+                .query(responseModel)
                 .invoke(HttpMethod.GET);
     }
 
@@ -105,6 +107,7 @@ class FujiServiceNowTableProcessor extends FujiServiceNowProcessor {
             .query(ServiceNowParams.SYSPARM_INPUT_DISPLAY_VALUE, in)
             .query(ServiceNowParams.SYSPARM_SUPPRESS_AUTO_SYS_FIELD, in)
             .query(ServiceNowParams.SYSPARM_VIEW, in)
+            .query(responseModel)
             .invoke(HttpMethod.POST, in.getMandatoryBody());
     }
 
@@ -127,6 +130,7 @@ class FujiServiceNowTableProcessor extends FujiServiceNowProcessor {
             .query(ServiceNowParams.SYSPARM_INPUT_DISPLAY_VALUE, in)
             .query(ServiceNowParams.SYSPARM_SUPPRESS_AUTO_SYS_FIELD, in)
             .query(ServiceNowParams.SYSPARM_VIEW, in)
+            .query(responseModel)
             .invoke(HttpMethod.PUT, in.getMandatoryBody());
     }
 
@@ -142,6 +146,7 @@ class FujiServiceNowTableProcessor extends FujiServiceNowProcessor {
             .path("table")
             .path(tableName)
             .path(ObjectHelper.notNull(sysId, "sysId"))
+            .query(responseModel)
             .invoke(HttpMethod.DELETE);
     }
 
@@ -164,6 +169,7 @@ class FujiServiceNowTableProcessor extends FujiServiceNowProcessor {
             .query(ServiceNowParams.SYSPARM_INPUT_DISPLAY_VALUE, in)
             .query(ServiceNowParams.SYSPARM_SUPPRESS_AUTO_SYS_FIELD, in)
             .query(ServiceNowParams.SYSPARM_VIEW, in)
+            .query(responseModel)
             .invoke("PATCH", in.getMandatoryBody());
     }
 }

http://git-wip-us.apache.org/repos/asf/camel/blob/05aa433e/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/releases/helsinki/HelsinkiServiceNowAggregateProcessor.java
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/releases/helsinki/HelsinkiServiceNowAggregateProcessor.java b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/releases/helsinki/HelsinkiServiceNowAggregateProcessor.java
index be47129..d895718 100644
--- a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/releases/helsinki/HelsinkiServiceNowAggregateProcessor.java
+++ b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/releases/helsinki/HelsinkiServiceNowAggregateProcessor.java
@@ -69,6 +69,7 @@ class HelsinkiServiceNowAggregateProcessor extends AbstractServiceNowProcessor {
             .query(ServiceNowParams.SYSPARM_ORDER_BY, in)
             .query(ServiceNowParams.SYSPARM_HAVING, in)
             .query(ServiceNowParams.SYSPARM_DISPLAY_VALUE, in)
+            .query(responseModel)
             .invoke(HttpMethod.GET);
 
         setBodyAndHeaders(in, responseModel, response);

http://git-wip-us.apache.org/repos/asf/camel/blob/05aa433e/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/releases/helsinki/HelsinkiServiceNowAttachmentProcessor.java
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/releases/helsinki/HelsinkiServiceNowAttachmentProcessor.java b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/releases/helsinki/HelsinkiServiceNowAttachmentProcessor.java
index b57fe4a..b25bcc0 100644
--- a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/releases/helsinki/HelsinkiServiceNowAttachmentProcessor.java
+++ b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/releases/helsinki/HelsinkiServiceNowAttachmentProcessor.java
@@ -143,6 +143,7 @@ public class HelsinkiServiceNowAttachmentProcessor extends AbstractServiceNowPro
             .query(ServiceNowParams.PARAM_TABLE_NAME, in)
             .query(ServiceNowParams.PARAM_TABLE_SYS_ID, in)
             .query(ServiceNowParams.PARAM_ENCRYPTION_CONTEXT, in)
+            .query(responseModel)
             .invoke(HttpMethod.POST, in.getMandatoryBody(InputStream.class));
 
         setBodyAndHeaders(in, responseModel, response);
@@ -170,6 +171,7 @@ public class HelsinkiServiceNowAttachmentProcessor extends AbstractServiceNowPro
             .path(apiVersion)
             .path("attachment")
             .path(ObjectHelper.notNull(sysId, "sysId"))
+            .query(responseModel)
             .invoke(HttpMethod.DELETE);
 
         setBodyAndHeaders(in, responseModel, response);

http://git-wip-us.apache.org/repos/asf/camel/blob/05aa433e/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/releases/helsinki/HelsinkiServiceNowImportSetProcessor.java
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/releases/helsinki/HelsinkiServiceNowImportSetProcessor.java b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/releases/helsinki/HelsinkiServiceNowImportSetProcessor.java
index 61dcf92..c49f228 100644
--- a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/releases/helsinki/HelsinkiServiceNowImportSetProcessor.java
+++ b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/releases/helsinki/HelsinkiServiceNowImportSetProcessor.java
@@ -56,6 +56,7 @@ class HelsinkiServiceNowImportSetProcessor extends AbstractServiceNowProcessor {
             .path("import")
             .path(ObjectHelper.notNull(tableName, "tableName"))
             .path(ObjectHelper.notNull(sysId, "sysId"))
+            .query(responseModel)
             .invoke(HttpMethod.GET);
 
         setBodyAndHeaders(in, responseModel, response);
@@ -79,6 +80,7 @@ class HelsinkiServiceNowImportSetProcessor extends AbstractServiceNowProcessor {
             .path(apiVersion)
             .path("import")
             .path(tableName)
+            .query(responseModel)
             .invoke(HttpMethod.POST, in.getMandatoryBody());
 
         setBodyAndHeaders(in, responseModel, response);

http://git-wip-us.apache.org/repos/asf/camel/blob/05aa433e/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/releases/helsinki/HelsinkiServiceNowMiscProcessor.java
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/releases/helsinki/HelsinkiServiceNowMiscProcessor.java b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/releases/helsinki/HelsinkiServiceNowMiscProcessor.java
index 5947532..c4e9d1b 100644
--- a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/releases/helsinki/HelsinkiServiceNowMiscProcessor.java
+++ b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/releases/helsinki/HelsinkiServiceNowMiscProcessor.java
@@ -60,6 +60,7 @@ class HelsinkiServiceNowMiscProcessor extends AbstractServiceNowProcessor {
             .path("global")
             .path("user_role_inheritance")
             .query(ServiceNowParams.PARAM_USER_SYS_ID, in)
+            .query(responseModel)
             .invoke(HttpMethod.GET);
 
         setBodyAndHeaders(in, responseModel, response);
@@ -85,6 +86,7 @@ class HelsinkiServiceNowMiscProcessor extends AbstractServiceNowProcessor {
             .path(apiVersion)
             .path("identifyreconcile")
             .query(ServiceNowParams.SYSPARM_DATA_SOURCE, in)
+            .query(responseModel)
             .invoke(HttpMethod.POST, in.getMandatoryBody());
 
         setBodyAndHeaders(in, responseModel, response);

http://git-wip-us.apache.org/repos/asf/camel/blob/05aa433e/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/releases/helsinki/HelsinkiServiceNowScorecardProcessor.java
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/releases/helsinki/HelsinkiServiceNowScorecardProcessor.java b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/releases/helsinki/HelsinkiServiceNowScorecardProcessor.java
index cae4cd0..78cace8 100644
--- a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/releases/helsinki/HelsinkiServiceNowScorecardProcessor.java
+++ b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/releases/helsinki/HelsinkiServiceNowScorecardProcessor.java
@@ -79,6 +79,7 @@ class HelsinkiServiceNowScorecardProcessor extends AbstractServiceNowProcessor {
             .query(ServiceNowParams.SYSPARM_ELEMENTS_FILTER, in)
             .query(ServiceNowParams.SYSPARM_BREAKDOWN_RELATION, in)
             .query(ServiceNowParams.SYSPARM_INCLUDE_SCORE_NOTES, in)
+            .query(responseModel)
             .invoke(HttpMethod.GET);
 
         setBodyAndHeaders(in, responseModel, response);

http://git-wip-us.apache.org/repos/asf/camel/blob/05aa433e/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/releases/helsinki/HelsinkiServiceNowServiceCatalogCartsProcessor.java
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/releases/helsinki/HelsinkiServiceNowServiceCatalogCartsProcessor.java b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/releases/helsinki/HelsinkiServiceNowServiceCatalogCartsProcessor.java
index 99b1d52..d890172 100644
--- a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/releases/helsinki/HelsinkiServiceNowServiceCatalogCartsProcessor.java
+++ b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/releases/helsinki/HelsinkiServiceNowServiceCatalogCartsProcessor.java
@@ -67,6 +67,7 @@ class HelsinkiServiceNowServiceCatalogCartsProcessor extends AbstractServiceNowP
             .path(apiVersion)
             .path("servicecatalog")
             .path("cart")
+            .query(responseModel)
             .invoke(HttpMethod.GET);
 
         setBodyAndHeaders(in, responseModel, response);
@@ -94,6 +95,7 @@ class HelsinkiServiceNowServiceCatalogCartsProcessor extends AbstractServiceNowP
             .path("cart")
             .path("delivery_address")
             .path(getMandatoryRequestParamFromHeader(ServiceNowParams.PARAM_USER_ID, in))
+            .query(responseModel)
             .invoke(HttpMethod.GET);
 
         setBodyAndHeaders(in, responseModel, response);
@@ -120,6 +122,7 @@ class HelsinkiServiceNowServiceCatalogCartsProcessor extends AbstractServiceNowP
             .path("servicecatalog")
             .path("cart")
             .path(getMandatoryRequestParamFromHeader(ServiceNowParams.PARAM_CART_ITEM_ID, in))
+            .query(responseModel)
             .invoke(HttpMethod.POST, in.getMandatoryBody());
 
         setBodyAndHeaders(in, responseModel, response);
@@ -148,6 +151,7 @@ class HelsinkiServiceNowServiceCatalogCartsProcessor extends AbstractServiceNowP
             .path("cart")
             .path(getMandatoryRequestParamFromHeader(ServiceNowParams.PARAM_SYS_ID, in))
             .path("empty")
+            .query(responseModel)
             .invoke(HttpMethod.DELETE);
 
         setBodyAndHeaders(in, responseModel, response);
@@ -178,6 +182,7 @@ class HelsinkiServiceNowServiceCatalogCartsProcessor extends AbstractServiceNowP
             .path("servicecatalog")
             .path("cart")
             .path("checkout")
+            .query(responseModel)
             .invoke(HttpMethod.POST);
 
         setBodyAndHeaders(in, responseModel, response);
@@ -205,6 +210,7 @@ class HelsinkiServiceNowServiceCatalogCartsProcessor extends AbstractServiceNowP
             .path("servicecatalog")
             .path("cart")
             .path("submit_order")
+            .query(responseModel)
             .invoke(HttpMethod.POST);
 
         setBodyAndHeaders(in, responseModel, response);

http://git-wip-us.apache.org/repos/asf/camel/blob/05aa433e/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/releases/helsinki/HelsinkiServiceNowServiceCatalogCategoriesProcessor.java
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/releases/helsinki/HelsinkiServiceNowServiceCatalogCategoriesProcessor.java b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/releases/helsinki/HelsinkiServiceNowServiceCatalogCategoriesProcessor.java
index e81ef73..bd5e905 100644
--- a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/releases/helsinki/HelsinkiServiceNowServiceCatalogCategoriesProcessor.java
+++ b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/releases/helsinki/HelsinkiServiceNowServiceCatalogCategoriesProcessor.java
@@ -61,6 +61,7 @@ class HelsinkiServiceNowServiceCatalogCategoriesProcessor extends AbstractServic
             .path("categories")
             .path(ObjectHelper.notNull(sysId, "sysId"))
             .query(ServiceNowParams.SYSPARM_VIEW, in)
+            .query(responseModel)
             .invoke(HttpMethod.GET);
 
         setBodyAndHeaders(in, responseModel, response);

http://git-wip-us.apache.org/repos/asf/camel/blob/05aa433e/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/releases/helsinki/HelsinkiServiceNowServiceCatalogItemsProcessor.java
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/releases/helsinki/HelsinkiServiceNowServiceCatalogItemsProcessor.java b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/releases/helsinki/HelsinkiServiceNowServiceCatalogItemsProcessor.java
index f8824ed..c0520c1 100644
--- a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/releases/helsinki/HelsinkiServiceNowServiceCatalogItemsProcessor.java
+++ b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/releases/helsinki/HelsinkiServiceNowServiceCatalogItemsProcessor.java
@@ -78,6 +78,7 @@ class HelsinkiServiceNowServiceCatalogItemsProcessor extends AbstractServiceNowP
                 .query(ServiceNowParams.SYSPARM_OFFSET, in)
                 .query(ServiceNowParams.SYSPARM_CATALOG, in)
                 .query(ServiceNowParams.SYSPARM_VIEW, in)
+                .query(responseModel)
                 .invoke(HttpMethod.GET)
             : client.reset()
                 .types(MediaType.APPLICATION_JSON_TYPE)
@@ -87,6 +88,7 @@ class HelsinkiServiceNowServiceCatalogItemsProcessor extends AbstractServiceNowP
                 .path("items")
                 .path(sysId)
                 .query(ServiceNowParams.SYSPARM_VIEW, in)
+                .query(responseModel)
                 .invoke(HttpMethod.GET);
 
         setBodyAndHeaders(in, responseModel, response);
@@ -117,6 +119,7 @@ class HelsinkiServiceNowServiceCatalogItemsProcessor extends AbstractServiceNowP
             .path(ObjectHelper.notNull(sysId, "sysId"))
             .path("submit_guide")
             .query(ServiceNowParams.SYSPARM_VIEW, in)
+            .query(responseModel)
             .invoke(HttpMethod.POST, in.getMandatoryBody());
 
         setBodyAndHeaders(in, responseModel, response);
@@ -145,6 +148,7 @@ class HelsinkiServiceNowServiceCatalogItemsProcessor extends AbstractServiceNowP
             .path("items")
             .path(ObjectHelper.notNull(sysId, "sysId"))
             .path("submit_guide")
+            .query(responseModel)
             .invoke(HttpMethod.POST, in.getMandatoryBody());
 
         setBodyAndHeaders(in, responseModel, response);
@@ -173,6 +177,7 @@ class HelsinkiServiceNowServiceCatalogItemsProcessor extends AbstractServiceNowP
             .path("items")
             .path(ObjectHelper.notNull(sysId, "sysId"))
             .path("add_to_cart")
+            .query(responseModel)
             .invoke(HttpMethod.POST);
 
         setBodyAndHeaders(in, responseModel, response);
@@ -203,6 +208,7 @@ class HelsinkiServiceNowServiceCatalogItemsProcessor extends AbstractServiceNowP
             .path(ObjectHelper.notNull(sysId, "sysId"))
             .path("submit_producer")
             .query(ServiceNowParams.SYSPARM_VIEW, in)
+            .query(responseModel)
             .invoke(HttpMethod.POST, in.getMandatoryBody());
 
         setBodyAndHeaders(in, responseModel, response);

http://git-wip-us.apache.org/repos/asf/camel/blob/05aa433e/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/releases/helsinki/HelsinkiServiceNowServiceCatalogProcessor.java
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/releases/helsinki/HelsinkiServiceNowServiceCatalogProcessor.java b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/releases/helsinki/HelsinkiServiceNowServiceCatalogProcessor.java
index 47d52b1..42b5da3 100644
--- a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/releases/helsinki/HelsinkiServiceNowServiceCatalogProcessor.java
+++ b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/releases/helsinki/HelsinkiServiceNowServiceCatalogProcessor.java
@@ -67,6 +67,7 @@ class HelsinkiServiceNowServiceCatalogProcessor extends AbstractServiceNowProces
                 .query(ServiceNowParams.SYSPARM_LIMIT, in)
                 .query(ServiceNowParams.SYSPARM_QUERY, in)
                 .query(ServiceNowParams.SYSPARM_VIEW, in)
+                .query(responseModel)
                 .invoke(HttpMethod.GET)
             : client.reset()
                 .types(MediaType.APPLICATION_JSON_TYPE)
@@ -76,6 +77,7 @@ class HelsinkiServiceNowServiceCatalogProcessor extends AbstractServiceNowProces
                 .path("catalogs")
                 .path(sysId)
                 .query(ServiceNowParams.SYSPARM_VIEW, in)
+                .query(responseModel)
                 .invoke(HttpMethod.GET);
 
         setBodyAndHeaders(in, responseModel, response);
@@ -108,6 +110,7 @@ class HelsinkiServiceNowServiceCatalogProcessor extends AbstractServiceNowProces
             .query(ServiceNowParams.SYSPARM_LIMIT, in)
             .query(ServiceNowParams.SYSPARM_VIEW, in)
             .query(ServiceNowParams.SYSPARM_OFFSET, in)
+            .query(responseModel)
             .invoke(HttpMethod.GET);
 
         setBodyAndHeaders(in, responseModel, response);

http://git-wip-us.apache.org/repos/asf/camel/blob/05aa433e/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/releases/helsinki/HelsinkiServiceNowTableProcessor.java
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/releases/helsinki/HelsinkiServiceNowTableProcessor.java b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/releases/helsinki/HelsinkiServiceNowTableProcessor.java
index 05be850..8e62408 100644
--- a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/releases/helsinki/HelsinkiServiceNowTableProcessor.java
+++ b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/releases/helsinki/HelsinkiServiceNowTableProcessor.java
@@ -71,6 +71,7 @@ class HelsinkiServiceNowTableProcessor extends AbstractServiceNowProcessor {
                 .query(ServiceNowParams.SYSPARM_LIMIT, in)
                 .query(ServiceNowParams.SYSPARM_OFFSET, in)
                 .query(ServiceNowParams.SYSPARM_VIEW, in)
+                .query(responseModel)
                 .invoke(HttpMethod.GET)
             : client.reset()
                 .types(MediaType.APPLICATION_JSON_TYPE)
@@ -83,6 +84,7 @@ class HelsinkiServiceNowTableProcessor extends AbstractServiceNowProcessor {
                 .query(ServiceNowParams.SYSPARM_EXCLUDE_REFERENCE_LINK, in)
                 .query(ServiceNowParams.SYSPARM_FIELDS, in)
                 .query(ServiceNowParams.SYSPARM_VIEW, in)
+                .query(responseModel)
                 .invoke(HttpMethod.GET);
 
         setBodyAndHeaders(exchange.getIn(), responseModel, response);
@@ -101,6 +103,7 @@ class HelsinkiServiceNowTableProcessor extends AbstractServiceNowProcessor {
         final String sysId = getSysID(in);
 
         validateBody(in, requestModel);
+
         Response response = client.reset()
             .types(MediaType.APPLICATION_JSON_TYPE)
             .path("now")
@@ -113,6 +116,7 @@ class HelsinkiServiceNowTableProcessor extends AbstractServiceNowProcessor {
             .query(ServiceNowParams.SYSPARM_INPUT_DISPLAY_VALUE, in)
             .query(ServiceNowParams.SYSPARM_SUPPRESS_AUTO_SYS_FIELD, in)
             .query(ServiceNowParams.SYSPARM_VIEW, in)
+            .query(responseModel)
             .invoke(HttpMethod.POST, in.getMandatoryBody());
 
         setBodyAndHeaders(exchange.getIn(), responseModel, response);
@@ -131,6 +135,7 @@ class HelsinkiServiceNowTableProcessor extends AbstractServiceNowProcessor {
         final String sysId = getSysID(in);
 
         validateBody(in, requestModel);
+
         Response response = client.reset()
             .types(MediaType.APPLICATION_JSON_TYPE)
             .path("now")
@@ -144,6 +149,7 @@ class HelsinkiServiceNowTableProcessor extends AbstractServiceNowProcessor {
             .query(ServiceNowParams.SYSPARM_INPUT_DISPLAY_VALUE, in)
             .query(ServiceNowParams.SYSPARM_SUPPRESS_AUTO_SYS_FIELD, in)
             .query(ServiceNowParams.SYSPARM_VIEW, in)
+            .query(responseModel)
             .invoke(HttpMethod.PUT, in.getMandatoryBody());
 
         setBodyAndHeaders(exchange.getIn(), responseModel, response);
@@ -167,6 +173,7 @@ class HelsinkiServiceNowTableProcessor extends AbstractServiceNowProcessor {
             .path("table")
             .path(tableName)
             .path(ObjectHelper.notNull(sysId, "sysId"))
+            .query(responseModel)
             .invoke(HttpMethod.DELETE, null);
 
         setBodyAndHeaders(exchange.getIn(), responseModel, response);
@@ -185,6 +192,7 @@ class HelsinkiServiceNowTableProcessor extends AbstractServiceNowProcessor {
         final String sysId = getSysID(in);
 
         validateBody(in, requestModel);
+
         Response response = client.reset()
             .types(MediaType.APPLICATION_JSON_TYPE)
             .path("now")
@@ -198,6 +206,7 @@ class HelsinkiServiceNowTableProcessor extends AbstractServiceNowProcessor {
             .query(ServiceNowParams.SYSPARM_INPUT_DISPLAY_VALUE, in)
             .query(ServiceNowParams.SYSPARM_SUPPRESS_AUTO_SYS_FIELD, in)
             .query(ServiceNowParams.SYSPARM_VIEW, in)
+            .query(responseModel)
             .invoke("PATCH", in.getMandatoryBody());
 
         setBodyAndHeaders(exchange.getIn(), responseModel, response);

http://git-wip-us.apache.org/repos/asf/camel/blob/05aa433e/components/camel-servicenow/src/test/java/org/apache/camel/component/servicenow/ServiceNowTableTest.java
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/src/test/java/org/apache/camel/component/servicenow/ServiceNowTableTest.java b/components/camel-servicenow/src/test/java/org/apache/camel/component/servicenow/ServiceNowTableTest.java
index 62ba190..e775e85 100644
--- a/components/camel-servicenow/src/test/java/org/apache/camel/component/servicenow/ServiceNowTableTest.java
+++ b/components/camel-servicenow/src/test/java/org/apache/camel/component/servicenow/ServiceNowTableTest.java
@@ -23,6 +23,7 @@ import org.apache.camel.Exchange;
 import org.apache.camel.builder.RouteBuilder;
 import org.apache.camel.component.mock.MockEndpoint;
 import org.apache.camel.component.servicenow.model.Incident;
+import org.apache.camel.component.servicenow.model.IncidentWithParms;
 import org.junit.Test;
 
 public class ServiceNowTableTest extends ServiceNowTestSupport {
@@ -57,6 +58,38 @@ public class ServiceNowTableTest extends ServiceNowTestSupport {
     }
 
     @Test
+    public void testRetrieveSomeWithParams() throws Exception {
+        MockEndpoint mock = getMockEndpoint("mock:servicenow");
+        mock.expectedMessageCount(1);
+
+        template().sendBodyAndHeaders(
+            "direct:servicenow",
+            null,
+            kvBuilder()
+                .put(ServiceNowConstants.RESOURCE, "table")
+                .put(ServiceNowConstants.ACTION, ServiceNowConstants.ACTION_RETRIEVE)
+                .put(ServiceNowParams.SYSPARM_LIMIT, 10)
+                .put(ServiceNowParams.SYSPARM_EXCLUDE_REFERENCE_LINK, false)
+                .put(ServiceNowParams.PARAM_TABLE_NAME, "incident")
+                .put(ServiceNowConstants.MODEL, IncidentWithParms.class)
+                .build()
+        );
+
+        mock.assertIsSatisfied();
+
+        Exchange exchange = mock.getExchanges().get(0);
+        List<Incident> items = exchange.getIn().getBody(List.class);
+
+        assertNotNull(items);
+        assertFalse(items.isEmpty());
+        assertTrue(items.size() <= 10);
+        assertNotNull(exchange.getIn().getHeader(ServiceNowConstants.RESPONSE_TYPE));
+        assertNotNull(exchange.getIn().getHeader(ServiceNowConstants.OFFSET_FIRST));
+        assertNotNull(exchange.getIn().getHeader(ServiceNowConstants.OFFSET_NEXT));
+        assertNotNull(exchange.getIn().getHeader(ServiceNowConstants.OFFSET_LAST));
+    }
+
+    @Test
     public void testRetrieveSomeWithDefaults() throws Exception {
         MockEndpoint mock = getMockEndpoint("mock:servicenow-defaults");
         mock.expectedMessageCount(1);

http://git-wip-us.apache.org/repos/asf/camel/blob/05aa433e/components/camel-servicenow/src/test/java/org/apache/camel/component/servicenow/model/IncidentWithParms.java
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/src/test/java/org/apache/camel/component/servicenow/model/IncidentWithParms.java b/components/camel-servicenow/src/test/java/org/apache/camel/component/servicenow/model/IncidentWithParms.java
new file mode 100644
index 0000000..03ff9ff
--- /dev/null
+++ b/components/camel-servicenow/src/test/java/org/apache/camel/component/servicenow/model/IncidentWithParms.java
@@ -0,0 +1,64 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.camel.component.servicenow.model;
+
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import org.apache.camel.component.servicenow.annotations.ServiceNowSysParm;
+
+@ServiceNowSysParm(name = "sysparm_exclude_reference_link", value = "true")
+@ServiceNowSysParm(name = "sysparm_fields", value = "id%2Cnumber%2Ccaller_id")
+@JsonIgnoreProperties(ignoreUnknown = true)
+@JsonInclude(JsonInclude.Include.NON_NULL)
+public class IncidentWithParms {
+    @JsonProperty("sys_id")
+    private String id;
+    @JsonProperty("number")
+    private String number;
+    @JsonProperty("caller_id")
+    private String callerId;
+
+    public IncidentWithParms() {
+    }
+
+
+    public String getId() {
+        return id;
+    }
+
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    public String getNumber() {
+        return number;
+    }
+
+    public void setNumber(String number) {
+        this.number = number;
+    }
+
+    public String getCallerId() {
+        return callerId;
+    }
+
+    public void setCallerId(String callerId) {
+        this.callerId = callerId;
+    }
+}


[14/19] camel git commit: CAMEL-11555: ServiceNow : create a maven plugin to generate models based on table layout

Posted by lb...@apache.org.
http://git-wip-us.apache.org/repos/asf/camel/blob/109da7c9/components/camel-servicenow/camel-servicenow-maven-plugin/src/test/java/org/apache/camel/maven/CamelServiceNowMojoTestSupport.java
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/camel-servicenow-maven-plugin/src/test/java/org/apache/camel/maven/CamelServiceNowMojoTestSupport.java b/components/camel-servicenow/camel-servicenow-maven-plugin/src/test/java/org/apache/camel/maven/CamelServiceNowMojoTestSupport.java
new file mode 100644
index 0000000..1fbb041
--- /dev/null
+++ b/components/camel-servicenow/camel-servicenow-maven-plugin/src/test/java/org/apache/camel/maven/CamelServiceNowMojoTestSupport.java
@@ -0,0 +1,56 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.maven;
+
+import java.io.File;
+import java.io.IOException;
+
+import org.apache.camel.util.ObjectHelper;
+import org.apache.commons.io.FileUtils;
+import org.apache.maven.plugin.logging.SystemStreamLog;
+
+class CamelServiceNowMojoTestSupport  {
+
+    protected CamelServiceNowGenerateMojo createMojo() throws IOException {
+        CamelServiceNowGenerateMojo mojo = new CamelServiceNowGenerateMojo();
+
+        mojo.setLog(new SystemStreamLog());
+
+        // set defaults
+        mojo.instanceName = getSystemPropertyOrEnvVar("servicenow.instance");
+        mojo.userName = getSystemPropertyOrEnvVar("servicenow.username");
+        mojo.userPassword = getSystemPropertyOrEnvVar("servicenow.password");
+        mojo.oauthClientId = getSystemPropertyOrEnvVar("servicenow.oauth2.client.id");
+        mojo.oauthClientSecret = getSystemPropertyOrEnvVar("servicenow.oauth2.client.secret");
+        mojo.outputDirectory = new File("target/generated-sources/camel-servicenow");
+        mojo.packageName = "org.apache.camel.servicenow.dto";
+
+        FileUtils.deleteDirectory(mojo.outputDirectory);
+
+        return mojo;
+    }
+
+    public static String getSystemPropertyOrEnvVar(String systemProperty) {
+        String answer = System.getProperty(systemProperty);
+        if (ObjectHelper.isEmpty(answer)) {
+            String envProperty = systemProperty.toUpperCase().replaceAll("[.-]", "_");
+            answer = System.getenv(envProperty);
+        }
+
+        return answer;
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/109da7c9/components/camel-servicenow/camel-servicenow-maven-plugin/src/test/resources/log4j2.properties
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/camel-servicenow-maven-plugin/src/test/resources/log4j2.properties b/components/camel-servicenow/camel-servicenow-maven-plugin/src/test/resources/log4j2.properties
new file mode 100644
index 0000000..495dd7f
--- /dev/null
+++ b/components/camel-servicenow/camel-servicenow-maven-plugin/src/test/resources/log4j2.properties
@@ -0,0 +1,43 @@
+## ---------------------------------------------------------------------------
+## Licensed to the Apache Software Foundation (ASF) under one or more
+## contributor license agreements.  See the NOTICE file distributed with
+## this work for additional information regarding copyright ownership.
+## The ASF licenses this file to You under the Apache License, Version 2.0
+## (the "License"); you may not use this file except in compliance with
+## the License.  You may obtain a copy of the License at
+##
+##      http://www.apache.org/licenses/LICENSE-2.0
+##
+## Unless required by applicable law or agreed to in writing, software
+## distributed under the License is distributed on an "AS IS" BASIS,
+## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+## See the License for the specific language governing permissions and
+## limitations under the License.
+## ---------------------------------------------------------------------------
+
+appender.file.type = File
+appender.file.name = file
+appender.file.fileName = target/camel-servicenow-maven-plugin-test.log
+appender.file.layout.type = PatternLayout
+appender.file.layout.pattern = %d %-5p %c{1} - %m %n
+
+appender.out.type = Console
+appender.out.name = out
+appender.out.layout.type = PatternLayout
+appender.out.layout.pattern = %d{HH:mm:ss.SSS} [%-15.15t] %-30.30c{1} %-5p %m%n
+
+logger.servicenow.name = org.apache.camel.component.servicenow
+logger.servicenow.level = DEBUG
+
+logger.mojo.name = org.apache.camel.maven.CamelServiceNowGenerateMojo
+logger.mojo.level = DEBUG
+logger.mojo.additivity = true
+logger.mojo.appenderRef.metadata.ref = out
+
+logger.mojo-test.name = org.apache.camel.maven.CamelServiceNowGenerateMojoTest
+logger.mojo-test.level = DEBUG
+logger.mojo-test.additivity = true
+logger.mojo-test.appenderRef.metadata-ext.ref = out
+
+rootLogger.level = INFO
+rootLogger.appenderRef.root.ref = file

http://git-wip-us.apache.org/repos/asf/camel/blob/109da7c9/components/camel-servicenow/pom.xml
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/pom.xml b/components/camel-servicenow/pom.xml
index e60c8ec..c3ee25c 100644
--- a/components/camel-servicenow/pom.xml
+++ b/components/camel-servicenow/pom.xml
@@ -17,7 +17,8 @@
     limitations under the License.
 
 -->
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
 
   <modelVersion>4.0.0</modelVersion>
 
@@ -27,171 +28,44 @@
     <version>2.20.0-SNAPSHOT</version>
   </parent>
 
-  <artifactId>camel-servicenow</artifactId>
-  <packaging>jar</packaging>
-  <name>Camel :: ServiceNow</name>
-  <description>Camel ServiceNow support</description>
+  <artifactId>camel-servicenow-parent</artifactId>
+  <packaging>pom</packaging>
+  <name>Camel :: ServiceNow :: Parent</name>
+  <description>Camel ServiceNow parent</description>
+
+  <modules>
+    <module>camel-servicenow-component</module>
+    <module>camel-servicenow-maven-plugin</module>
+  </modules>
 
   <properties>
-    <camel.osgi.export.pkg>
-      org.apache.camel.component.servicenow.*
-    </camel.osgi.export.pkg>
-    <camel.osgi.export.service>
-      org.apache.camel.spi.ComponentResolver;component=servicenow
-    </camel.osgi.export.service>
+    <servicenow.component.root>${project.basedir}</servicenow.component.root>
   </properties>
 
-
-  <dependencies>
-    <dependency>
-      <groupId>org.apache.camel</groupId>
-      <artifactId>camel-core</artifactId>
-    </dependency>
-
-    <!-- CXF -->
-    <dependency>
-      <groupId>org.apache.cxf</groupId>
-      <artifactId>cxf-core</artifactId>
-      <version>${cxf-version}</version>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.cxf</groupId>
-      <artifactId>cxf-rt-frontend-jaxrs</artifactId>
-      <version>${cxf-version}</version>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.cxf</groupId>
-      <artifactId>cxf-rt-rs-security-oauth2</artifactId>
-      <version>${cxf-version}</version>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.cxf</groupId>
-      <artifactId>cxf-rt-rs-extension-providers</artifactId>
-      <version>${cxf-version}</version>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.cxf</groupId>
-      <artifactId>cxf-rt-rs-client</artifactId>
-      <version>${cxf-version}</version>
-    </dependency>
-
-    <!-- Jackson -->
-    <dependency>
-      <groupId>com.fasterxml.jackson.core</groupId>
-      <artifactId>jackson-core</artifactId>
-      <version>${jackson2-version}</version>
-    </dependency>
-    <dependency>
-      <groupId>com.fasterxml.jackson.core</groupId>
-      <artifactId>jackson-annotations</artifactId>
-      <version>${jackson2-version}</version>
-    </dependency>
-    <dependency>
-      <groupId>com.fasterxml.jackson.core</groupId>
-      <artifactId>jackson-databind</artifactId>
-      <version>${jackson2-version}</version>
-    </dependency>
-    <dependency>
-      <groupId>com.fasterxml.jackson.jaxrs</groupId>
-      <artifactId>jackson-jaxrs-json-provider</artifactId>
-      <version>${jackson2-version}</version>
-    </dependency>
-
-    <!-- testing -->
-
-    <dependency>
-      <groupId>javax.servlet</groupId>
-      <artifactId>javax.servlet-api</artifactId>
-      <version>${javax.servlet-api-version}</version>
-      <scope>test</scope>
-    </dependency>
-    <dependency>
-      <groupId>org.osgi</groupId>
-      <artifactId>org.osgi.compendium</artifactId>
-      <version>${osgi-version}</version>
-      <scope>test</scope>
-    </dependency>
-
-    <dependency>
-      <groupId>org.apache.camel</groupId>
-      <artifactId>camel-test</artifactId>
-      <scope>test</scope>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.camel</groupId>
-      <artifactId>camel-test-blueprint</artifactId>
-      <scope>test</scope>
-    </dependency>
-
-    <dependency>
-      <groupId>org.apache.logging.log4j</groupId>
-      <artifactId>log4j-api</artifactId>
-      <scope>test</scope>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.logging.log4j</groupId>
-      <artifactId>log4j-core</artifactId>
-      <scope>test</scope>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.logging.log4j</groupId>
-      <artifactId>log4j-slf4j-impl</artifactId>
-      <scope>test</scope>
-    </dependency>
-    <dependency>
-      <groupId>junit</groupId>
-      <artifactId>junit</artifactId>
-      <scope>test</scope>
-    </dependency>
-    <dependency>
-      <groupId>org.mockito</groupId>
-      <artifactId>mockito-all</artifactId>
-      <version>${mockito-version}</version>
-      <scope>test</scope>
-    </dependency>
-    <dependency>
-      <groupId>org.hamcrest</groupId>
-      <artifactId>java-hamcrest</artifactId>
-      <version>${hamcrest-version}</version>
-      <scope>test</scope>
-    </dependency>
-  </dependencies>
-
   <build>
     <plugins>
-          <plugin>
-            <artifactId>maven-surefire-plugin</artifactId>
-            <configuration>
-              <skipTests>true</skipTests>
-            </configuration>
-          </plugin>
+      <plugin>
+        <groupId>org.apache.camel</groupId>
+        <artifactId>camel-package-maven-plugin</artifactId>
+        <version>${project.version}</version>
+        <executions>
+          <execution>
+            <id>prepare</id>
+            <goals>
+              <goal>prepare-components</goal>
+            </goals>
+            <phase>generate-resources</phase>
+          </execution>
+          <execution>
+            <id>validate</id>
+            <goals>
+              <goal>validate-components</goal>
+            </goals>
+            <phase>prepare-package</phase>
+          </execution>
+        </executions>
+      </plugin>
     </plugins>
   </build>
 
-  <profiles>
-    <profile>
-      <id>servicenow-tests</id>
-      <activation>
-        <property>
-            <name>env.SERVICENOW_INSTANCE</name>
-        </property>
-      </activation>
-      <build>
-        <plugins>
-          <plugin>
-            <artifactId>maven-surefire-plugin</artifactId>
-            <configuration>
-              <skipTests>false</skipTests>
-              <systemPropertyVariables>
-                <servicenow.instance>${env.SERVICENOW_INSTANCE}</servicenow.instance>
-                <servicenow.username>${env.SERVICENOW_USERNAME}</servicenow.username>
-                <servicenow.password>${env.SERVICENOW_PASSWORD}</servicenow.password>
-              </systemPropertyVariables>
-            </configuration>
-          </plugin>
-        </plugins>
-      </build>
-    </profile>
-  </profiles>
-
 </project>

http://git-wip-us.apache.org/repos/asf/camel/blob/109da7c9/components/camel-servicenow/src/main/docs/servicenow-component.adoc
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/src/main/docs/servicenow-component.adoc b/components/camel-servicenow/src/main/docs/servicenow-component.adoc
deleted file mode 100644
index 197ebd9..0000000
--- a/components/camel-servicenow/src/main/docs/servicenow-component.adoc
+++ /dev/null
@@ -1,300 +0,0 @@
-## ServiceNow Component
-
-*Available as of Camel version 2.18*
-
-The ServiceNow component provides access to ServiceNow platform through their REST API.
-
-NOTE: From Camel 2.18.1 the component supports multiple version of ServiceNow platform with default to Helsinki. Supported version are <<ServiceNow-Fuji>> and <<ServiceNow-Helsinki>>
-
-
-Maven users will need to add the following dependency to their pom.xml
-for this component:
-
-[source,java]
--------------------------------------------------
-    <dependency>
-        <groupId>org.apache.camel</groupId>
-        <artifactId>camel-servicenow</artifactId>
-        <version>${camel-version}</version>
-    </dependency>
--------------------------------------------------
-
-### URI format
-
-[source,java]
----------------------------------------
-    servicenow://instanceName?[options]
----------------------------------------
-
-### Options
-
-
-// component options: START
-The ServiceNow component supports 10 options which are listed below.
-
-
-
-[width="100%",cols="2,5,^1,2",options="header"]
-|=======================================================================
-| Name | Description | Default | Type
-| **instanceName** (advanced) | The ServiceNow instance name |  | String
-| **configuration** (advanced) | The ServiceNow default configuration |  | ServiceNowConfiguration
-| **apiUrl** (producer) | The ServiceNow REST API url |  | String
-| **userName** (security) | ServiceNow user account name |  | String
-| **password** (security) | ServiceNow account password |  | String
-| **oauthClientId** (security) | OAuth2 ClientID |  | String
-| **oauthClientSecret** (security) | OAuth2 ClientSecret |  | String
-| **oauthTokenUrl** (security) | OAuth token Url |  | 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
-|=======================================================================
-// component options: END
-
-
-// endpoint options: START
-The ServiceNow endpoint is configured using URI syntax:
-
-    servicenow:instanceName
-
-with the following path and query parameters:
-
-#### Path Parameters (1 parameters):
-
-[width="100%",cols="2,5,^1,2",options="header"]
-|=======================================================================
-| Name | Description | Default | Type
-| **instanceName** | *Required* The ServiceNow instance name |  | String
-|=======================================================================
-
-#### Query Parameters (41 parameters):
-
-[width="100%",cols="2,5,^1,2",options="header"]
-|=======================================================================
-| Name | Description | Default | Type
-| **display** (producer) | Set this parameter to true to return only scorecards where the indicator Display field is selected. Set this parameter to all to return scorecards with any Display field value. This parameter is true by default. | true | String
-| **displayValue** (producer) | Return the display value (true) actual value (false) or both (all) for reference fields (default: false) | false | String
-| **excludeReferenceLink** (producer) | True to exclude Table API links for reference fields (default: false) |  | Boolean
-| **favorites** (producer) | Set this parameter to true to return only scorecards that are favorites of the querying user. |  | Boolean
-| **includeAggregates** (producer) | Set this parameter to true to always return all available aggregates for an indicator including when an aggregate has already been applied. If a value is not specified this parameter defaults to false and returns no aggregates. |  | Boolean
-| **includeAvailableAggregates** (producer) | Set this parameter to true to return all available aggregates for an indicator when no aggregate has been applied. If a value is not specified this parameter defaults to false and returns no aggregates. |  | Boolean
-| **includeAvailableBreakdowns** (producer) | Set this parameter to true to return all available breakdowns for an indicator. If a value is not specified this parameter defaults to false and returns no breakdowns. |  | Boolean
-| **includeScoreNotes** (producer) | Set this parameter to true to return all notes associated with the score. The note element contains the note text as well as the author and timestamp when the note was added. |  | Boolean
-| **includeScores** (producer) | Set this parameter to true to return all scores for a scorecard. If a value is not specified this parameter defaults to false and returns only the most recent score value. |  | Boolean
-| **inputDisplayValue** (producer) | True to set raw value of input fields (default: false) |  | Boolean
-| **key** (producer) | Set this parameter to true to return only scorecards for key indicators. |  | Boolean
-| **models** (producer) | Defines both request and response models |  | String
-| **perPage** (producer) | Enter the maximum number of scorecards each query can return. By default this value is 10 and the maximum is 100. | 10 | Integer
-| **release** (producer) | The ServiceNow release to target default to Helsinki See https://docs.servicenow.com | HELSINKI | ServiceNowRelease
-| **requestModels** (producer) | Defines the request model |  | String
-| **resource** (producer) | The default resource can be overridden by header CamelServiceNowResource |  | String
-| **responseModels** (producer) | Defines the response model |  | String
-| **sortBy** (producer) | Specify the value to use when sorting results. By default queries sort records by value. |  | String
-| **sortDir** (producer) | Specify the sort direction ascending or descending. By default queries sort records in descending order. Use sysparm_sortdir=asc to sort in ascending order. |  | String
-| **suppressAutoSysField** (producer) | True to suppress auto generation of system fields (default: false) |  | Boolean
-| **suppressPaginationHeader** (producer) | Set this value to true to remove the Link header from the response. The Link header allows you to request additional pages of data when the number of records matching your query exceeds the query limit |  | Boolean
-| **table** (producer) | The default table can be overridden by header CamelServiceNowTable |  | String
-| **target** (producer) | Set this parameter to true to return only scorecards that have a target. |  | Boolean
-| **topLevelOnly** (producer) | Gets only those categories whose parent is a catalog. |  | Boolean
-| **apiVersion** (advanced) | The ServiceNow REST API version default latest |  | String
-| **httpClientPolicy** (advanced) | To configure http-client |  | HTTPClientPolicy
-| **mapper** (advanced) | Sets Jackson's ObjectMapper to use for request/reply |  | ObjectMapper
-| **proxyAuthorizationPolicy** (advanced) | To configure proxy authentication |  | ProxyAuthorization Policy
-| **retrieveTargetRecordOn Import** (advanced) | Set this parameter to true to retrieve the target record when using import set api. The import set result is then replaced by the target record | false | Boolean
-| **synchronous** (advanced) | Sets whether synchronous processing should be strictly used or Camel is allowed to use asynchronous processing (if supported). | false | boolean
-| **proxyHost** (proxy) | The proxy host name |  | String
-| **proxyPort** (proxy) | The proxy port number |  | Integer
-| **apiUrl** (security) | The ServiceNow REST API url |  | String
-| **oauthClientId** (security) | OAuth2 ClientID |  | String
-| **oauthClientSecret** (security) | OAuth2 ClientSecret |  | String
-| **oauthTokenUrl** (security) | OAuth token Url |  | String
-| **password** (security) | *Required* ServiceNow account password MUST be provided |  | String
-| **proxyPassword** (security) | Password for proxy authentication |  | String
-| **proxyUserName** (security) | Username for proxy authentication |  | String
-| **sslContextParameters** (security) | To configure security using SSLContextParameters. See http://camel.apache.org/camel-configuration-utilities.html |  | SSLContextParameters
-| **userName** (security) | *Required* ServiceNow user account name MUST be provided |  | String
-|=======================================================================
-// endpoint options: END
-
-
-
-### Headers
-
-[width="100%",cols="10%,10%,10%,10%,60%",options="header",]
-|===
-|Name |Type |ServiceNow API Parameter |Endpoint option |Description
-|CamelServiceNowResource |String | - | - | The resource to access
-|CamelServiceNowAction |String | - | - | The action to perform
-|CamelServiceNowActionSubject | - | - | String |The subject to which the action should be applied
-|CamelServiceNowModel |Class | - | - | The data model
-|CamelServiceNowRequestModel |Class | - | - | The request data model
-|CamelServiceNowResponseModel |Class | - | - | The response data model
-|CamelServiceNowOffsetNext | - | - | - | -
-|CamelServiceNowOffsetPrev | - | - | - | -
-|CamelServiceNowOffsetFirst | - | - | - | -
-|CamelServiceNowOffsetLast | - | - | - | -
-|CamelServiceNowContentType | - | - | - | -
-|CamelServiceNowContentEncoding | - | - | - | -
-|CamelServiceNowContentMeta | - | - | - | -
-|CamelServiceNowSysId |String | sys_id | - | -
-|CamelServiceNowUserSysId |String | user_sysid | - | -
-|CamelServiceNowUserId |String | user_id | - | -
-|CamelServiceNowCartItemId |String | cart_item_id | - | -
-|CamelServiceNowFileName |String | file_name | - | -
-|CamelServiceNowTable |String | table_name | - | -
-|CamelServiceNowTableSysId |String | table_sys_id | - | -
-|CamelServiceNowEncryptionContext | String | encryption_context | - | -
-|CamelServiceNowCategory | String | sysparm_category  | - | -
-|CamelServiceNowType |String | sysparm_type | - | -
-|CamelServiceNowCatalog | String | sysparm_catalog | - | -
-|CamelServiceNowQuery |String | sysparm_query | - | -
-|CamelServiceNowDisplayValue |String | sysparm_display_value | displayValue  | -
-|CamelServiceNowInputDisplayValue |Boolean | sysparm_input_display_value | inputDisplayValue  | -
-|CamelServiceNowExcludeReferenceLink |Boolean | sysparm_exclude_reference_link | excludeReferenceLink  | -
-|CamelServiceNowFields |String | sysparm_fields | - | -
-|CamelServiceNowLimit |Integer | sysparm_limit | - | -
-|CamelServiceNowText | String | sysparm_text | - | -
-|CamelServiceNowOffset | Integer | sysparm_offset | - | -
-|CamelServiceNowView |String | sysparm_view | - | -
-|CamelServiceNowSuppressAutoSysField |Boolean | sysparm_suppress_auto_sys_field | suppressAutoSysField | -
-|CamelServiceNowSuppressPaginationHeader | Booleab | sysparm_suppress_pagination_header | suppressPaginationHeader | -
-|CamelServiceNowMinFields |String | sysparm_min_fields | - | -
-|CamelServiceNowMaxFields |String | sysparm_max_fields | - | -
-|CamelServiceNowSumFields |String | sysparm_sum_fields | - | -
-|CamelServiceNowAvgFields |String | sysparm_avg_fields | - | -
-|CamelServiceNowCount |Boolean | sysparm_count | - | -
-|CamelServiceGroupBy |String | sysparm_group_by | - | -
-|CamelServiceOrderBy |String | sysparm_order_by | - | -
-|CamelServiceHaving |String | sysparm_having | - | -
-|CamelServiceNowUUID |String | sysparm_uuid | - | -
-|CamelServiceNowBreakdown| String| sysparm_breakdown | - | -
-|CamelServiceNowIncludeScores| Boolean | sysparm_include_scores | includeScores | -
-|CamelServiceNowIncludeScoreNotes | Boolean | sysparm_include_score_notes | includeScoreNotes | -
-|CamelServiceNowIncludeAggregates | Boolean | sysparm_include_aggregates | includeAggregates | -
-|CamelServiceNowIncludeAvailableBreakdowns | Boolean | sysparm_include_available_breakdowns | includeAvailableBreakdowns | -
-|CamelServiceNowIncludeAvailableAggregates | Boolean | sysparm_include_available_aggregates | includeAvailableAggregates | -
-|CamelServiceNowFavorites | Boolean | sysparm_favorites | favorites | -
-|CamelServiceNowKey  | Boolean | sysparm_key | key | -
-|CamelServiceNowTarget | Boolean | sysparm_target | target | -
-|CamelServiceNowDisplay | String | sysparm_display | display | -
-|CamelServiceNowPerPage | Integer | sysparm_per_page | perPage | -
-|CamelServiceNowSortBy | String | sysparm_sortby | sortBy | -
-|CamelServiceNowSortDir | String | sysparm_sortdit | sortDir | -
-|CamelServiceNowContains | String | sysparm_contains | - | -
-|CamelServiceNowTags | String | sysparm_tags | - | -
-|CamelServiceNowPage | String | sysparm_page | - | -
-|CamelServiceNowElementsFilter | String | sysparm_elements_filter | - | -
-|CamelServiceNowBreakdownRelation | String | sysparm_breakdown_relation | - | -
-|CamelServiceNowDataSource | String | sysparm_data_source | - | -
-|CamelServiceNowTopLevelOnly | Boolean | sysparm_top_level_only | topLevelOnly | -
-|CamelServiceNowApiVersion | String | - | - | The REST API version
-|CamelServiceNowResponseMeta | Map | - | - | Meta data provided along with a response
-|===
-
-[[ServiceNow-Fuji]]
-[cols="10%a,10%a,10%a,70%a", options="header"]
-.API Mapping
-|===
-| CamelServiceNowResource | CamelServiceNowAction | Method | API URI
-1.5+<.^|TABLE
-| RETRIEVE | GET | /api/now/v1/table/{table_name}/{sys_id}
-| CREATE | POST | /api/now/v1/table/{table_name}
-| MODIFY | PUT | /api/now/v1/table/{table_name}/{sys_id}
-| DELETE | DELETE | /api/now/v1/table/{table_name}/{sys_id}
-| UPDATE | PATCH | /api/now/v1/table/{table_name}/{sys_id}
-
-| AGGREGATE
-| RETRIEVE | GET | /api/now/v1/stats/{table_name}
-
-1.2+<.^|IMPORT
-| RETRIEVE | GET | /api/now/import/{table_name}/{sys_id}
-| CREATE | POST | /api/now/import/{table_name}
-|===
-
-NOTE: link:http://wiki.servicenow.com/index.php?title=REST_API#Available_APIs[Fuji REST API Documentation]
-
-[[ServiceNow-Helsinki]]
-[cols="10%a,10%a,10%a,10%a,60%a", options="header"]
-.API Mapping
-|===
-| CamelServiceNowResource | CamelServiceNowAction | CamelServiceNowActionSubject | Method | API URI
-1.5+<.^|TABLE
-| RETRIEVE | | GET | /api/now/v1/table/{table_name}/{sys_id}
-| CREATE | | POST | /api/now/v1/table/{table_name}
-| MODIFY | | PUT | /api/now/v1/table/{table_name}/{sys_id}
-| DELETE | | DELETE | /api/now/v1/table/{table_name}/{sys_id}
-| UPDATE | | PATCH | /api/now/v1/table/{table_name}/{sys_id}
-
-| AGGREGATE
-| RETRIEVE | | GET | /api/now/v1/stats/{table_name}
-
-1.2+<.^|IMPORT
-| RETRIEVE | | GET | /api/now/import/{table_name}/{sys_id}
-| CREATE | | POST | /api/now/import/{table_name}
-
-1.4+<.^|ATTACHMENT
-| RETRIEVE | | GET | /api/now/api/now/attachment/{sys_id}
-| CONTENT | | GET | /api/now/attachment/{sys_id}/file
-| UPLOAD | | POST | /api/now/api/now/attachment/file
-| DELETE | | DELETE | /api/now/attachment/{sys_id}
-
-| SCORECARDS
-| RETRIEVE | PERFORMANCE_ANALYTICS | GET | /api/now/pa/scorecards
-
-1.2+<.^|MISC
-| RETRIEVE | USER_ROLE_INHERITANCE | GET | /api/global/user_role_inheritance
-| CREATE | IDENTIFY_RECONCILE | POST | /api/now/identifyreconcile
-
-1.2+<.^|SERVICE_CATALOG
-| RETRIEVE | | GET | /sn_sc/servicecatalog/catalogs/{sys_id}
-| RETRIEVE | CATEGORIES |  GET | /sn_sc/servicecatalog/catalogs/{sys_id}/categories
-
-1.5+<.^|SERVICE_CATALOG_ITEMS
-| RETRIEVE | | GET | /sn_sc/servicecatalog/items/{sys_id}
-| RETRIEVE | SUBMIT_GUIDE | POST | /sn_sc/servicecatalog/items/{sys_id}/submit_guide
-| RETRIEVE | CHECKOUT_GUIDE | POST | /sn_sc/servicecatalog/items/{sys_id}/checkout_guide
-| CREATE | SUBJECT_CART | POST | /sn_sc/servicecatalog/items/{sys_id}/add_to_cart
-| CREATE | SUBJECT_PRODUCER | POST | /sn_sc/servicecatalog/items/{sys_id}/submit_producer
-
-1.6+<.^|SERVICE_CATALOG_CARTS
-| RETRIEVE | | GET | /sn_sc/servicecatalog/cart
-| RETRIEVE | DELIVERY_ADDRESS | GET | /sn_sc/servicecatalog/cart/delivery_address/{user_id}
-| RETRIEVE | CHECKOUT | POST | /sn_sc/servicecatalog/cart/checkout
-| UPDATE | | POST | /sn_sc/servicecatalog/cart/{cart_item_id}
-| UPDATE | CHECKOUT | POST | /sn_sc/servicecatalog/cart/submit_order
-| DELETE | | DELETE | /sn_sc/servicecatalog/cart/{sys_id}/empty
-
-| SERVICE_CATALOG_CATEGORIES
-| RETRIEVE | | GET | /sn_sc/servicecatalog/categories/{sys_id}
-
-|===
-
-NOTE: https://docs.servicenow.com/bundle/helsinki-servicenow-platform/page/integrate/inbound-rest/reference/r_RESTResources.html[Helsinki REST API Documentation]
-
-### Usage examples:
- 
-{% raw %}
-[source,java]
-.Retrieve 10 Incidents
--------------------------------------------------------------------------------------------------------------------
-context.addRoutes(new RouteBuilder() {
-    public void configure() {
-       from("direct:servicenow")
-           .to("servicenow:{{env:SERVICENOW_INSTANCE}}"
-               + "?userName={{env:SERVICENOW_USERNAME}}"
-               + "&password={{env:SERVICENOW_PASSWORD}}"
-               + "&oauthClientId={{env:SERVICENOW_OAUTH2_CLIENT_ID}}"
-               + "&oauthClientSecret={{env:SERVICENOW_OAUTH2_CLIENT_SECRET}}"
-           .to("mock:servicenow");
-    }
-}); 
-
-FluentProducerTemplate.on(context)
-    .withHeader(ServiceNowConstants.RESOURCE, "table")
-    .withHeader(ServiceNowConstants.ACTION, ServiceNowConstants.ACTION_RETRIEVE)
-    .withHeader(ServiceNowConstants.SYSPARM_LIMIT.getId(), "10")
-    .withHeader(ServiceNowConstants.TABLE, "incident")
-    .withHeader(ServiceNowConstants.MODEL, Incident.class)
-    .to("direct:servicenow")
-    .send();
--------------------------------------------------------------------------------------------------------------------
-{% endraw %}

http://git-wip-us.apache.org/repos/asf/camel/blob/109da7c9/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/AbstractServiceNowProcessor.java
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/AbstractServiceNowProcessor.java b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/AbstractServiceNowProcessor.java
deleted file mode 100644
index 1ae25af..0000000
--- a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/AbstractServiceNowProcessor.java
+++ /dev/null
@@ -1,293 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.camel.component.servicenow;
-
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import javax.ws.rs.core.HttpHeaders;
-import javax.ws.rs.core.Response;
-
-import com.fasterxml.jackson.databind.JavaType;
-import com.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import org.apache.camel.Exchange;
-import org.apache.camel.Message;
-import org.apache.camel.Processor;
-import org.apache.camel.util.ObjectHelper;
-
-public abstract class AbstractServiceNowProcessor implements Processor {
-
-    protected final ServiceNowEndpoint endpoint;
-    protected final ServiceNowConfiguration config;
-    protected final ObjectMapper mapper;
-    protected final ServiceNowClient client;
-
-    // Cache for JavaTypes
-    private final JavaTypeCache javaTypeCache;
-    private final List<ServiceNowDispatcher> dispatchers;
-
-    protected AbstractServiceNowProcessor(ServiceNowEndpoint endpoint) throws Exception {
-        this.javaTypeCache = new JavaTypeCache();
-        this.endpoint = endpoint;
-        this.config = endpoint.getConfiguration();
-        this.mapper = ObjectHelper.notNull(config.getMapper(), "mapper");
-        this.client = new ServiceNowClient(endpoint.getCamelContext(), config);
-        this.dispatchers = new ArrayList<>();
-    }
-
-    protected AbstractServiceNowProcessor setBodyAndHeaders(Message message, Class<?> responseModel, Response response) throws Exception {
-        if (response != null) {
-            setHeaders(message, responseModel, response);
-            setBody(message, responseModel, response);
-        }
-
-        return this;
-    }
-
-    @Override
-    public void process(Exchange exchange) throws Exception {
-        final ServiceNowDispatcher dispatcher = findDispatcher(exchange);
-
-        if (dispatcher != null) {
-            dispatcher.process(exchange);
-        } else {
-            throw new IllegalArgumentException("Unable to process exchange");
-        }
-    }
-
-    // *********************************
-    // Header
-    // *********************************
-
-    protected AbstractServiceNowProcessor setHeaders(Message message, Class<?> responseModel, Response response) throws Exception {
-        ServiceNowHelper.findOffsets(response, (k, v) -> message.setHeader(k, v));
-
-        String attachmentMeta = response.getHeaderString(ServiceNowConstants.ATTACHMENT_META_HEADER);
-        if (ObjectHelper.isNotEmpty(attachmentMeta)) {
-            message.setHeader(
-                ServiceNowConstants.CONTENT_META,
-                mapper.readValue(attachmentMeta, Map.class)
-            );
-        }
-
-        copyHeader(response, HttpHeaders.CONTENT_TYPE, message, ServiceNowConstants.CONTENT_TYPE);
-        copyHeader(response, HttpHeaders.CONTENT_ENCODING, message, ServiceNowConstants.CONTENT_ENCODING);
-
-        if (responseModel != null) {
-            message.getHeaders().putIfAbsent(ServiceNowConstants.MODEL, responseModel.getName());
-            message.getHeaders().putIfAbsent(ServiceNowConstants.RESPONSE_MODEL, responseModel.getName());
-        }
-
-        return this;
-    }
-
-    // *********************************
-    // Body
-    // *********************************
-
-    protected AbstractServiceNowProcessor setBody(Message message, Class<?> model, Response response) throws Exception {
-        if (message != null && response != null) {
-            if (ObjectHelper.isNotEmpty(response.getHeaderString(HttpHeaders.CONTENT_TYPE))) {
-
-                JsonNode root = response.readEntity(JsonNode.class);
-                Map<String, String> responseAttributes = null;
-
-                if (root != null) {
-                    Iterator<Map.Entry<String, JsonNode>> fields = root.fields();
-                    while (fields.hasNext()) {
-                        final Map.Entry<String, JsonNode> entry = fields.next();
-                        final String key = entry.getKey();
-                        final JsonNode node = entry.getValue();
-
-                        if (ObjectHelper.equal("result", key, true)) {
-                            Object body = unwrap(node, model);
-                            if (body != null) {
-                                message.setHeader(ServiceNowConstants.RESPONSE_TYPE, body.getClass());
-                                message.setBody(body);
-                            }
-                        } else {
-                            if (responseAttributes == null) {
-                                responseAttributes = new HashMap<>();
-                            }
-
-                            responseAttributes.put(key, node.textValue());
-                        }
-                    }
-
-                    if (responseAttributes != null) {
-                        message.setHeader(ServiceNowConstants.RESPONSE_META, responseAttributes);
-                    }
-                }
-            }
-        }
-
-        return this;
-    }
-
-    protected AbstractServiceNowProcessor validateBody(Message message, Class<?> model) {
-        return validateBody(message.getBody(), model);
-    }
-
-    protected AbstractServiceNowProcessor validateBody(Object body, Class<?> model) {
-        ObjectHelper.notNull(body, "body");
-
-        if (!body.getClass().isAssignableFrom(model)) {
-            throw new IllegalArgumentException(
-                "Body is not compatible with model (body=" + body.getClass() + ", model=" + model);
-        }
-
-        return this;
-    }
-
-    protected Object unwrap(JsonNode node, Class<?> model) throws IOException {
-        Object result;
-
-        if (node.isArray()) {
-            if (model.isInstance(Map.class)) {
-                // If the model is a Map, there's no need to use any
-                // specific JavaType to instruct Jackson about the
-                // expected element type
-                result = mapper.treeToValue(node, List.class);
-            } else {
-                result = mapper.readValue(node.traverse(), javaTypeCache.get(model));
-            }
-        } else {
-            result = mapper.treeToValue(node, model);
-        }
-
-        return result;
-    }
-
-    // *********************************
-    // Helpers
-    // *********************************
-
-    protected final void addDispatcher(ServiceNowDispatcher dispatcher) {
-        this.dispatchers.add(dispatcher);
-    }
-
-    protected final void addDispatcher(String action, Processor processor) {
-        addDispatcher(ServiceNowDispatcher.on(action, null, processor));
-    }
-
-    protected final void addDispatcher(String action, String subject, Processor processor) {
-        addDispatcher(ServiceNowDispatcher.on(action, subject, processor));
-    }
-
-    protected final ServiceNowDispatcher findDispatcher(Exchange exchange) {
-        ServiceNowDispatcher dispatcher = null;
-        for (int i = 0; i < dispatchers.size(); i++) {
-            dispatcher = dispatchers.get(i);
-            if (dispatcher.match(exchange)) {
-                return dispatcher;
-            }
-        }
-
-        return null;
-    }
-
-    // *********************************
-    // Helpers
-    // *********************************
-
-    protected Object getRequestParamFromHeader(ServiceNowParam sysParam, Message message) {
-        return message.getHeader(
-            sysParam.getHeader(),
-            sysParam.getDefaultValue(config),
-            sysParam.getType()
-        );
-    }
-
-    protected Object getMandatoryRequestParamFromHeader(ServiceNowParam sysParam, Message message) {
-        return ObjectHelper.notNull(
-            getRequestParamFromHeader(sysParam, message),
-            sysParam.getHeader()
-        );
-    }
-
-    protected void copyHeader(Response from, String fromId, Message to, String toId) {
-        Object fromValue = from.getHeaders().getFirst(fromId);
-        if (ObjectHelper.isNotEmpty(fromValue)) {
-            to.setHeader(toId, fromValue);
-        }
-    }
-
-    protected Class<?> getRequestModel(Message message) {
-        return getRequestModel(message, null);
-    }
-
-    protected Class<?> getRequestModel(Message message, String modelName) {
-        Class<?> model = null;
-
-        if (message != null) {
-            model = message.getHeader(ServiceNowConstants.REQUEST_MODEL, Class.class);
-            if (model == null) {
-                model = message.getHeader(ServiceNowConstants.MODEL, Class.class);
-            }
-        }
-
-        return model != null
-            ? model
-            : ObjectHelper.isEmpty(modelName) ? Map.class : config.getRequestModel(modelName, Map.class);
-    }
-
-    protected Class<?> getResponseModel(Message message) {
-        return getRequestModel(message, null);
-    }
-
-    protected Class<?> getResponseModel(Message message, String modelName) {
-        Class<?> model = null;
-
-        if (message != null) {
-            model = message.getHeader(ServiceNowConstants.RESPONSE_MODEL, Class.class);
-            if (model == null) {
-                model = message.getHeader(ServiceNowConstants.MODEL, Class.class);
-            }
-        }
-
-        return model != null
-            ? model
-            : ObjectHelper.isEmpty(modelName) ? Map.class : config.getResponseModel(modelName, Map.class);
-    }
-
-    protected String getApiVersion(Message message) {
-        return message.getHeader(ServiceNowConstants.API_VERSION, config.getApiVersion(), String.class);
-    }
-
-    protected String getTableName(Message message) {
-        return message.getHeader(ServiceNowParams.PARAM_TABLE_NAME.getHeader(), config.getTable(), String.class);
-    }
-
-    protected String getSysID(Message message) {
-        return message.getHeader(ServiceNowParams.PARAM_SYS_ID.getHeader(), String.class);
-    }
-
-    // *************************************************************************
-    // Use ClassValue to lazy create and cache JavaType
-    // *************************************************************************
-
-    private class JavaTypeCache extends ClassValue<JavaType> {
-        @Override
-        protected JavaType computeValue(Class<?> type) {
-            return mapper.getTypeFactory().constructCollectionType(List.class, type);
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/camel/blob/109da7c9/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/AbstractServiceNowProducer.java
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/AbstractServiceNowProducer.java b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/AbstractServiceNowProducer.java
deleted file mode 100644
index 0fd23d7..0000000
--- a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/AbstractServiceNowProducer.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.camel.component.servicenow;
-
-import org.apache.camel.impl.HeaderSelectorProducer;
-
-public abstract class AbstractServiceNowProducer extends HeaderSelectorProducer implements ServiceNowProducer {
-    private final ServiceNowRelease release;
-    private final ServiceNowEndpoint endpoint;
-
-    public AbstractServiceNowProducer(ServiceNowEndpoint endpoint, ServiceNowRelease release) {
-        super(endpoint, ServiceNowConstants.RESOURCE, endpoint.getConfiguration().getResource());
-
-        this.release = release;
-        this.endpoint = endpoint;
-    }
-
-    @Override
-    public ServiceNowRelease getRelease() {
-        return release;
-    }
-
-    protected final ServiceNowConfiguration getConfiguration() {
-        return endpoint.getConfiguration();
-    }
-}

http://git-wip-us.apache.org/repos/asf/camel/blob/109da7c9/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowClient.java
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowClient.java b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowClient.java
deleted file mode 100644
index 5128797..0000000
--- a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowClient.java
+++ /dev/null
@@ -1,274 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.camel.component.servicenow;
-
-import java.util.Arrays;
-import java.util.Map;
-import java.util.function.Function;
-import javax.net.ssl.SSLContext;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.Response;
-
-import com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider;
-import org.apache.camel.CamelContext;
-import org.apache.camel.Message;
-import org.apache.camel.component.servicenow.annotations.ServiceNowSysParm;
-import org.apache.camel.component.servicenow.auth.AuthenticationRequestFilter;
-import org.apache.camel.util.ObjectHelper;
-import org.apache.camel.util.jsse.SSLContextParameters;
-import org.apache.cxf.configuration.jsse.TLSClientParameters;
-import org.apache.cxf.configuration.security.ProxyAuthorizationPolicy;
-import org.apache.cxf.jaxrs.client.WebClient;
-import org.apache.cxf.transport.http.HTTPConduit;
-import org.apache.cxf.transports.http.configuration.HTTPClientPolicy;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public final class ServiceNowClient {
-    private static final Logger LOGGER = LoggerFactory.getLogger(ServiceNowClient.class);
-
-    private final CamelContext camelContext;
-    private final ServiceNowConfiguration configuration;
-    private final WebClient client;
-
-    ServiceNowClient(CamelContext camelContext, ServiceNowConfiguration configuration) throws Exception {
-        this.camelContext = camelContext;
-        this.configuration = configuration;
-        this.client = WebClient.create(
-            configuration.getApiUrl(),
-            Arrays.asList(
-                new AuthenticationRequestFilter(configuration),
-                new JacksonJsonProvider(configuration.getMapper())
-            ),
-            true
-        );
-
-        configureRequestContext(camelContext, configuration, client);
-        configureTls(camelContext, configuration, client);
-        configureHttpClientPolicy(camelContext, configuration, client);
-        configureProxyAuthorizationPolicy(camelContext, configuration, client);
-    }
-
-    public ServiceNowClient types(MediaType type) {
-        return types(type, type);
-    }
-
-    public ServiceNowClient types(MediaType accept, MediaType type) {
-        client.accept(accept);
-        client.type(type);
-        return this;
-    }
-
-    public ServiceNowClient path(Object path) {
-        if (ObjectHelper.isNotEmpty(path)) {
-            client.path(path);
-        }
-
-        return this;
-    }
-
-    public ServiceNowClient type(MediaType ct) {
-        client.type(ct);
-        return this;
-    }
-
-    public ServiceNowClient type(String type) {
-        client.type(type);
-        return this;
-    }
-
-    public ServiceNowClient accept(MediaType... types) {
-        client.accept(types);
-        return this;
-    }
-
-    public ServiceNowClient accept(String... types) {
-        client.accept(types);
-        return this;
-    }
-
-    public ServiceNowClient query(String name, Object... values) {
-        client.query(name, values);
-        return this;
-    }
-
-    public ServiceNowClient queryF(String name, String format, Object... values) {
-        client.query(name, String.format(format, values));
-        return this;
-    }
-
-    public ServiceNowClient query(ServiceNowParam param, Message message) {
-        Object value = param.getHeaderValue(message, configuration);
-        if (value != null) {
-            client.query(param.getId(), value);
-        }
-
-        return this;
-    }
-
-    public ServiceNowClient query(Class<?> model) {
-        if (model != null) {
-            String name;
-            String value;
-
-            for (ServiceNowSysParm parm : model.getAnnotationsByType(ServiceNowSysParm.class)) {
-                name = parm.name();
-                value = parm.value();
-
-                // SysParms defined on model have precedence and replace query param
-                // with same name set via Message headers.
-                if (ObjectHelper.isNotEmpty(name) && ObjectHelper.isNotEmpty(value)) {
-                    LOGGER.debug("Replace query param {} with value {}", name, value);
-                    client.replaceQueryParam(name, value);
-                }
-            }
-        }
-
-        return this;
-    }
-
-    public Response invoke(String httpMethod) throws Exception {
-        return invoke(client, httpMethod, null);
-    }
-
-    public Response invoke(String httpMethod, Object body) throws Exception {
-        return invoke(client, httpMethod, body);
-    }
-
-    public <T> T trasform(String httpMethod, Function<Response, T> function) throws Exception {
-        return function.apply(invoke(client, httpMethod, null));
-    }
-
-    public <T> T trasform(String httpMethod, Object body, Function<Response, T> function) throws Exception {
-        return function.apply(invoke(client, httpMethod, body));
-    }
-
-    public ServiceNowClient reset() {
-        client.back(true);
-        client.reset();
-        client.resetQuery();
-
-        return this;
-    }
-
-    // *******************************
-    // Helpers
-    // *******************************
-
-    private Response invoke(WebClient client, String httpMethod, Object body) throws Exception {
-        Response response = client.invoke(httpMethod, body);
-        int code = response.getStatus();
-
-        // Only ServiceNow known error status codes are mapped
-        // See http://wiki.servicenow.com/index.php?title=REST_API#REST_Response_HTTP_Status_Codes
-        switch(code) {
-        case 200:
-        case 201:
-        case 204:
-            // Success
-            break;
-        case 400:
-        case 401:
-        case 403:
-        case 404:
-        case 405:
-        case 406:
-        case 415:
-            ServiceNowExceptionModel model = response.readEntity(ServiceNowExceptionModel.class);
-            throw new ServiceNowException(
-                code,
-                model.getStatus(),
-                model.getError().get("message"),
-                model.getError().get("detail")
-            );
-        default:
-            throw new ServiceNowException(
-                code,
-                response.readEntity(Map.class)
-            );
-        }
-
-        return response;
-    }
-
-    private static void configureRequestContext(
-            CamelContext context, ServiceNowConfiguration configuration, WebClient client) throws Exception {
-
-        WebClient.getConfig(client)
-            .getRequestContext()
-            .put("org.apache.cxf.http.header.split", true);
-    }
-
-    private static void configureTls(
-        CamelContext camelContext, ServiceNowConfiguration configuration, WebClient client) throws Exception {
-
-        SSLContextParameters sslContextParams = configuration.getSslContextParameters();
-        if (sslContextParams != null) {
-            HTTPConduit conduit = WebClient.getConfig(client).getHttpConduit();
-            TLSClientParameters tlsClientParams = conduit.getTlsClientParameters();
-            if (tlsClientParams == null) {
-                tlsClientParams = new TLSClientParameters();
-            }
-
-            SSLContext sslContext = sslContextParams.createSSLContext(camelContext);
-            tlsClientParams.setSSLSocketFactory(sslContext.getSocketFactory());
-
-            conduit.setTlsClientParameters(tlsClientParams);
-        }
-    }
-
-    private static void configureHttpClientPolicy(
-            CamelContext context, ServiceNowConfiguration configuration, WebClient client) throws Exception {
-
-        HTTPClientPolicy httpPolicy = configuration.getHttpClientPolicy();
-        if (httpPolicy == null) {
-            String host = configuration.getProxyHost();
-            Integer port = configuration.getProxyPort();
-
-            if (host != null && port != null) {
-                httpPolicy = new HTTPClientPolicy();
-                httpPolicy.setProxyServer(host);
-                httpPolicy.setProxyServerPort(port);
-            }
-        }
-
-        if (httpPolicy != null) {
-            WebClient.getConfig(client).getHttpConduit().setClient(httpPolicy);
-        }
-    }
-
-    private static void configureProxyAuthorizationPolicy(
-            CamelContext context, ServiceNowConfiguration configuration, WebClient client) throws Exception {
-
-        ProxyAuthorizationPolicy proxyPolicy = configuration.getProxyAuthorizationPolicy();
-        if (proxyPolicy == null) {
-            String username = configuration.getProxyUserName();
-            String password = configuration.getProxyPassword();
-
-            if (username != null && password != null) {
-                proxyPolicy = new ProxyAuthorizationPolicy();
-                proxyPolicy.setAuthorizationType("Basic");
-                proxyPolicy.setUserName(username);
-                proxyPolicy.setPassword(password);
-            }
-        }
-
-        if (proxyPolicy != null) {
-            WebClient.getConfig(client).getHttpConduit().setProxyAuthorization(proxyPolicy);
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/camel/blob/109da7c9/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowComponent.java
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowComponent.java b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowComponent.java
deleted file mode 100644
index c9cbb89..0000000
--- a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowComponent.java
+++ /dev/null
@@ -1,226 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.camel.component.servicenow;
-
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Map;
-
-import org.apache.camel.CamelContext;
-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;
-import org.apache.camel.util.IntrospectionSupport;
-import org.apache.camel.util.ObjectHelper;
-
-/**
- * Represents the component that manages {@link ServiceNowEndpoint}.
- */
-@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")
-    private ServiceNowConfiguration configuration;
-    @Metadata(label = "security", defaultValue = "false")
-    private boolean useGlobalSslContextParameters;
-
-    private ServiceNowComponentVerifierExtension verifierExtension;
-    private ServiceNowMetaDataExtension metaDataExtension;
-
-    public ServiceNowComponent() {
-        this(null);
-    }
-
-    public ServiceNowComponent(CamelContext camelContext) {
-        super(camelContext);
-
-        this.configuration = new ServiceNowConfiguration();
-
-        registerExtension(ServiceNowComponentVerifierExtension::new);
-        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);
-    }
-
-    public String getInstanceName() {
-        return instanceName;
-    }
-
-    /**
-     * The ServiceNow instance name
-     */
-    public void setInstanceName(String instanceName) {
-        this.instanceName = instanceName;
-    }
-
-    public ServiceNowConfiguration getConfiguration() {
-        return configuration;
-    }
-
-    /**
-     * The ServiceNow default configuration
-     */
-    public void setConfiguration(ServiceNowConfiguration configuration) {
-        this.configuration = configuration;
-    }
-
-    public String getApiUrl() {
-        return configuration.getApiUrl();
-    }
-
-    /**
-     * The ServiceNow REST API url
-     */
-    public void setApiUrl(String apiUrl) {
-        configuration.setApiUrl(apiUrl);
-    }
-
-    public String getUserName() {
-        return configuration.getUserName();
-    }
-
-    /**
-     * ServiceNow user account name
-     */
-    @Metadata(label = "security", secret = true)
-    public void setUserName(String userName) {
-        configuration.setUserName(userName);
-    }
-
-    public String getPassword() {
-        return configuration.getPassword();
-    }
-
-    /**
-     * ServiceNow account password
-     */
-    @Metadata(label = "security", secret = true)
-    public void setPassword(String password) {
-        configuration.setPassword(password);
-    }
-
-    public String getOauthClientId() {
-        return configuration.getOauthClientId();
-    }
-
-    /**
-     * OAuth2 ClientID
-     */
-    @Metadata(label = "security", secret = true)
-    public void setOauthClientId(String oauthClientId) {
-        configuration.setOauthClientId(oauthClientId);
-    }
-
-    public String getOauthClientSecret() {
-        return configuration.getOauthClientSecret();
-    }
-
-    /**
-     * OAuth2 ClientSecret
-     */
-    @Metadata(label = "security", secret = true)
-    public void setOauthClientSecret(String oauthClientSecret) {
-        configuration.setOauthClientSecret(oauthClientSecret);
-    }
-
-    public String getOauthTokenUrl() {
-        return configuration.getOauthTokenUrl();
-    }
-
-    /**
-     * OAuth token Url
-     */
-    @Metadata(label = "security", secret = true)
-    public void setOauthTokenUrl(String oauthTokenUrl) {
-        configuration.setOauthTokenUrl(oauthTokenUrl);
-    }
-
-    @Override
-    public boolean isUseGlobalSslContextParameters() {
-        return this.useGlobalSslContextParameters;
-    }
-
-    /**
-     * Enable usage of global SSL context parameters.
-     */
-    @Override
-    public void setUseGlobalSslContextParameters(boolean useGlobalSslContextParameters) {
-        this.useGlobalSslContextParameters = useGlobalSslContextParameters;
-    }
-
-    @Override
-    public ComponentVerifier getVerifier() {
-        return (scope, parameters) -> getExtension(ComponentVerifierExtension.class).orElseThrow(UnsupportedOperationException::new).verify(scope, parameters);
-    }
-}

http://git-wip-us.apache.org/repos/asf/camel/blob/109da7c9/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowComponentVerifierExtension.java
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowComponentVerifierExtension.java b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowComponentVerifierExtension.java
deleted file mode 100644
index 0422238..0000000
--- a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowComponentVerifierExtension.java
+++ /dev/null
@@ -1,109 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.camel.component.servicenow;
-
-import java.util.Map;
-import javax.ws.rs.HttpMethod;
-import javax.ws.rs.core.MediaType;
-
-import org.apache.camel.component.extension.verifier.DefaultComponentVerifierExtension;
-import org.apache.camel.component.extension.verifier.NoSuchOptionException;
-import org.apache.camel.component.extension.verifier.ResultBuilder;
-import org.apache.camel.component.extension.verifier.ResultErrorBuilder;
-
-final class ServiceNowComponentVerifierExtension extends DefaultComponentVerifierExtension {
-
-    ServiceNowComponentVerifierExtension() {
-        super("servicenow");
-    }
-
-    // *********************************
-    // Parameters validation
-    // *********************************
-
-    @Override
-    protected Result verifyParameters(Map<String, Object> parameters) {
-        ResultBuilder builder = ResultBuilder.withStatusAndScope(Result.Status.OK, Scope.PARAMETERS);
-
-        // Validate using the catalog
-        super.verifyParametersAgainstCatalog(builder, parameters);
-
-        return builder.build();
-    }
-
-    // *********************************
-    // Connectivity validation
-    // *********************************
-
-    @Override
-    protected Result verifyConnectivity(Map<String, Object> parameters) {
-        // Default is success
-        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));
-            }
-
-            new ServiceNowClient(getCamelContext(), configuration)
-                .types(MediaType.APPLICATION_JSON_TYPE)
-                .path("now")
-                .path(configuration.getApiVersion())
-                .path("table")
-                .path(tableName)
-                .query(ServiceNowParams.SYSPARM_LIMIT.getId(), 1L)
-                .invoke(HttpMethod.GET);
-        } catch (NoSuchOptionException e) {
-            builder.error(
-                ResultErrorBuilder.withMissingOption(e.getOptionName()).build()
-            );
-        } catch (ServiceNowException e) {
-            ResultErrorBuilder errorBuilder = ResultErrorBuilder.withException(e)
-                .detail(VerificationError.HttpAttribute.HTTP_CODE, e.getCode())
-                .detail("servicenow_error_message", e.getMessage())
-                .detail("servicenow_error_status", e.getStatus())
-                .detail("servicenow_error_detail", e.getDetail());
-
-            if (e.getCode() == 401) {
-                errorBuilder.code(VerificationError.StandardCode.AUTHENTICATION);
-                errorBuilder.parameterKey("userName");
-                errorBuilder.parameterKey("password");
-                errorBuilder.parameterKey("oauthClientId");
-                errorBuilder.parameterKey("oauthClientSecret");
-            }
-
-            builder.error(errorBuilder.build());
-        } catch (Exception e) {
-            builder.error(
-                ResultErrorBuilder.withException(e).build()
-            );
-        }
-
-        return builder.build();
-    }
-}


[06/19] camel git commit: CAMEL-11550: Component extensions

Posted by lb...@apache.org.
http://git-wip-us.apache.org/repos/asf/camel/blob/42529399/camel-core/src/main/java/org/apache/camel/component/extension/verifier/DefaultComponentVerifierExtension.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/component/extension/verifier/DefaultComponentVerifierExtension.java b/camel-core/src/main/java/org/apache/camel/component/extension/verifier/DefaultComponentVerifierExtension.java
new file mode 100644
index 0000000..a5495ca
--- /dev/null
+++ b/camel-core/src/main/java/org/apache/camel/component/extension/verifier/DefaultComponentVerifierExtension.java
@@ -0,0 +1,214 @@
+/**
+ * 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.extension.verifier;
+
+import java.util.Map;
+import java.util.Optional;
+import java.util.function.Supplier;
+import java.util.stream.Collectors;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.CamelContextAware;
+import org.apache.camel.ComponentVerifier;
+import org.apache.camel.TypeConverter;
+import org.apache.camel.component.extension.ComponentVerifierExtension;
+import org.apache.camel.runtimecatalog.EndpointValidationResult;
+import org.apache.camel.runtimecatalog.RuntimeCamelCatalog;
+import org.apache.camel.util.CamelContextHelper;
+import org.apache.camel.util.EndpointHelper;
+import org.apache.camel.util.IntrospectionSupport;
+
+import static org.apache.camel.util.StreamUtils.stream;
+
+public class DefaultComponentVerifierExtension implements ComponentVerifierExtension, ComponentVerifier, CamelContextAware {
+    private final String defaultScheme;
+    private CamelContext camelContext;
+
+    public DefaultComponentVerifierExtension(String defaultScheme) {
+        this(defaultScheme, null);
+    }
+
+    public DefaultComponentVerifierExtension(String defaultScheme, CamelContext camelContext) {
+        this.defaultScheme = defaultScheme;
+        this.camelContext = camelContext;
+    }
+
+    // *************************************
+    //
+    // *************************************
+
+    @Override
+    public void setCamelContext(CamelContext camelContext) {
+        this.camelContext = camelContext;
+    }
+
+    @Override
+    public CamelContext getCamelContext() {
+        return camelContext;
+    }
+
+    @Override
+    public Result verify(Scope scope, Map<String, Object> parameters) {
+        // Camel context is mandatory
+        if (this.camelContext == null) {
+            return ResultBuilder.withStatusAndScope(Result.Status.ERROR, scope)
+                .error(ResultErrorBuilder.withCodeAndDescription(VerificationError.StandardCode.INTERNAL, "Missing camel-context").build())
+                .build();
+        }
+
+        if (scope == Scope.PARAMETERS) {
+            return verifyParameters(parameters);
+        }
+        if (scope == Scope.CONNECTIVITY) {
+            return verifyConnectivity(parameters);
+        }
+
+        return ResultBuilder.unsupportedScope(scope).build();
+    }
+
+    protected Result verifyConnectivity(Map<String, Object> parameters) {
+        return ResultBuilder.withStatusAndScope(Result.Status.UNSUPPORTED, Scope.CONNECTIVITY).build();
+    }
+
+    protected Result verifyParameters(Map<String, Object> parameters) {
+        ResultBuilder builder = ResultBuilder.withStatusAndScope(Result.Status.OK, Scope.PARAMETERS);
+
+        // Validate against catalog
+        verifyParametersAgainstCatalog(builder, parameters);
+
+        return builder.build();
+    }
+
+    // *************************************
+    // Helpers :: Parameters validation
+    // *************************************
+
+    protected void verifyParametersAgainstCatalog(ResultBuilder builder, Map<String, Object> parameters) {
+        verifyParametersAgainstCatalog(builder, parameters, new CatalogVerifierCustomizer());
+    }
+
+    protected void verifyParametersAgainstCatalog(ResultBuilder builder, Map<String, Object> parameters, CatalogVerifierCustomizer customizer) {
+        String scheme = defaultScheme;
+        if (parameters.containsKey("scheme")) {
+            scheme = parameters.get("scheme").toString();
+        }
+
+        // Grab the runtime catalog to check parameters
+        RuntimeCamelCatalog catalog = camelContext.getRuntimeCamelCatalog();
+
+        // Convert from Map<String, Object> to  Map<String, String> as required
+        // by the Camel Catalog
+        EndpointValidationResult result = catalog.validateProperties(
+            scheme,
+            parameters.entrySet().stream()
+                .collect(
+                    Collectors.toMap(
+                        Map.Entry::getKey,
+                        e -> camelContext.getTypeConverter().convertTo(String.class, e.getValue())
+                    )
+                )
+        );
+
+        if (!result.isSuccess()) {
+            if (customizer.isIncludeUnknown()) {
+                stream(result.getUnknown())
+                    .map(option -> ResultErrorBuilder.withUnknownOption(option).build())
+                    .forEach(builder::error);
+            }
+            if (customizer.isIncludeRequired()) {
+                stream(result.getRequired())
+                    .map(option -> ResultErrorBuilder.withMissingOption(option).build())
+                    .forEach(builder::error);
+            }
+            if (customizer.isIncludeInvalidBoolean()) {
+                stream(result.getInvalidBoolean())
+                    .map(entry -> ResultErrorBuilder.withIllegalOption(entry.getKey(), entry.getValue()).build())
+                    .forEach(builder::error);
+            }
+            if (customizer.isIncludeInvalidInteger()) {
+                stream(result.getInvalidInteger())
+                    .map(entry -> ResultErrorBuilder.withIllegalOption(entry.getKey(), entry.getValue()).build())
+                    .forEach(builder::error);
+            }
+            if (customizer.isIncludeInvalidNumber()) {
+                stream(result.getInvalidNumber())
+                    .map(entry -> ResultErrorBuilder.withIllegalOption(entry.getKey(), entry.getValue()).build())
+                    .forEach(builder::error);
+            }
+            if (customizer.isIncludeInvalidEnum()) {
+                stream(result.getInvalidEnum())
+                    .map(entry ->
+                        ResultErrorBuilder.withIllegalOption(entry.getKey(), entry.getValue())
+                            .detail("enum.values", result.getEnumChoices(entry.getKey()))
+                            .build())
+                    .forEach(builder::error);
+            }
+        }
+    }
+
+    // *************************************
+    // Helpers
+    // *************************************
+
+
+    protected <T> T setProperties(T instance, Map<String, Object> properties) throws Exception {
+        if (camelContext == null) {
+            throw new IllegalStateException("Camel context is null");
+        }
+
+        if (!properties.isEmpty()) {
+            final TypeConverter converter = camelContext.getTypeConverter();
+
+            IntrospectionSupport.setProperties(converter, instance, properties);
+
+            for (Map.Entry<String, Object> entry : properties.entrySet()) {
+                if (entry.getValue() instanceof String) {
+                    String value = (String)entry.getValue();
+                    if (EndpointHelper.isReferenceParameter(value)) {
+                        IntrospectionSupport.setProperty(camelContext, converter, instance, entry.getKey(), null, value, true);
+                    }
+                }
+            }
+        }
+
+        return instance;
+    }
+
+    protected <T> T setProperties(T instance, String prefix, Map<String, Object> properties) throws Exception {
+        return setProperties(
+            instance,
+            IntrospectionSupport.extractProperties(properties, prefix, false)
+        );
+    }
+
+    protected <T> Optional<T> getOption(Map<String, Object> parameters, String key, Class<T> type) {
+        Object value = parameters.get(key);
+        if (value != null) {
+            return Optional.ofNullable(CamelContextHelper.convertTo(camelContext, type, value));
+        }
+
+        return Optional.empty();
+    }
+
+    protected <T> T getOption(Map<String, Object> parameters, String key, Class<T> type, Supplier<T> defaultSupplier) {
+        return getOption(parameters, key, type).orElseGet(defaultSupplier);
+    }
+
+    protected <T> T getMandatoryOption(Map<String, Object> parameters, String key, Class<T> type) throws NoSuchOptionException {
+        return getOption(parameters, key, type).orElseThrow(() ->  new NoSuchOptionException(key));
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/42529399/camel-core/src/main/java/org/apache/camel/component/extension/verifier/DefaultResult.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/component/extension/verifier/DefaultResult.java b/camel-core/src/main/java/org/apache/camel/component/extension/verifier/DefaultResult.java
new file mode 100644
index 0000000..17a82c0
--- /dev/null
+++ b/camel-core/src/main/java/org/apache/camel/component/extension/verifier/DefaultResult.java
@@ -0,0 +1,57 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.extension.verifier;
+
+import java.util.List;
+
+import org.apache.camel.component.extension.ComponentVerifierExtension;
+
+public class DefaultResult implements ComponentVerifierExtension.Result {
+    private final ComponentVerifierExtension.Scope scope;
+    private final Status status;
+    private final List<ComponentVerifierExtension.VerificationError> verificationErrors;
+
+    public DefaultResult(ComponentVerifierExtension.Scope scope, Status status, List<ComponentVerifierExtension.VerificationError> verificationErrors) {
+        this.scope = scope;
+        this.status = status;
+        this.verificationErrors = verificationErrors;
+    }
+
+    @Override
+    public ComponentVerifierExtension.Scope getScope() {
+        return scope;
+    }
+
+    @Override
+    public Status getStatus() {
+        return status;
+    }
+
+    @Override
+    public List<ComponentVerifierExtension.VerificationError> getErrors() {
+        return verificationErrors;
+    }
+
+    @Override
+    public String toString() {
+        return "DefaultResult{"
+               + "scope=" + scope
+               + ", status=" + status
+               + ", errors=" + verificationErrors
+               + '}';
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/42529399/camel-core/src/main/java/org/apache/camel/component/extension/verifier/DefaultResultVerificationError.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/component/extension/verifier/DefaultResultVerificationError.java b/camel-core/src/main/java/org/apache/camel/component/extension/verifier/DefaultResultVerificationError.java
new file mode 100644
index 0000000..2255dc1
--- /dev/null
+++ b/camel-core/src/main/java/org/apache/camel/component/extension/verifier/DefaultResultVerificationError.java
@@ -0,0 +1,66 @@
+/**
+ * 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.extension.verifier;
+
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.camel.component.extension.ComponentVerifierExtension.VerificationError;
+
+public class DefaultResultVerificationError implements VerificationError {
+    private final Code code;
+    private final String description;
+    private final Set<String> parameterKeys;
+    private final Map<Attribute, Object> details;
+
+    public DefaultResultVerificationError(Code code, String description, Set<String> parameterKeys, Map<Attribute, Object> details) {
+        this.code = code;
+        this.description = description;
+        this.parameterKeys = parameterKeys;
+        this.details = details;
+    }
+
+    @Override
+    public Code getCode() {
+        return code;
+    }
+
+    @Override
+    public String getDescription() {
+        return description;
+    }
+
+    @Override
+    public Set<String> getParameterKeys() {
+        return parameterKeys;
+    }
+
+    @Override
+    public Map<Attribute, Object> getDetails() {
+        return details;
+    }
+
+    @Override
+    public String toString() {
+        return "DefaultResultError{"
+               + "code='" + code + '\''
+               + ", description='" + description + '\''
+               + ", parameterKeys=" + parameterKeys
+               + ", details=" + details
+               + '}';
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/42529399/camel-core/src/main/java/org/apache/camel/component/extension/verifier/IllegalOptionException.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/component/extension/verifier/IllegalOptionException.java b/camel-core/src/main/java/org/apache/camel/component/extension/verifier/IllegalOptionException.java
new file mode 100644
index 0000000..a8d717d
--- /dev/null
+++ b/camel-core/src/main/java/org/apache/camel/component/extension/verifier/IllegalOptionException.java
@@ -0,0 +1,39 @@
+/**
+ * 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.extension.verifier;
+
+public class IllegalOptionException extends ComponentVerifierException {
+    private final String optionName;
+    private final String optionValue;
+
+    public IllegalOptionException(String optionName) {
+        this(optionName, null);
+    }
+
+    public IllegalOptionException(String optionName, String optionValue) {
+        this.optionName = optionName;
+        this.optionValue = optionValue;
+    }
+
+    public String getOptionName() {
+        return optionName;
+    }
+
+    public String getOptionValue() {
+        return optionValue;
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/42529399/camel-core/src/main/java/org/apache/camel/component/extension/verifier/NoSuchOptionException.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/component/extension/verifier/NoSuchOptionException.java b/camel-core/src/main/java/org/apache/camel/component/extension/verifier/NoSuchOptionException.java
new file mode 100644
index 0000000..a03d9f0
--- /dev/null
+++ b/camel-core/src/main/java/org/apache/camel/component/extension/verifier/NoSuchOptionException.java
@@ -0,0 +1,29 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.extension.verifier;
+
+public class NoSuchOptionException extends ComponentVerifierException {
+    private final String optionName;
+
+    public NoSuchOptionException(String optionName) {
+        this.optionName = optionName;
+    }
+
+    public String getOptionName() {
+        return optionName;
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/42529399/camel-core/src/main/java/org/apache/camel/component/extension/verifier/OptionsGroup.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/component/extension/verifier/OptionsGroup.java b/camel-core/src/main/java/org/apache/camel/component/extension/verifier/OptionsGroup.java
new file mode 100644
index 0000000..62f81c4
--- /dev/null
+++ b/camel-core/src/main/java/org/apache/camel/component/extension/verifier/OptionsGroup.java
@@ -0,0 +1,142 @@
+/**
+ * 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.extension.verifier;
+
+import java.io.Serializable;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.LinkedHashSet;
+import java.util.Set;
+
+/**
+ * A named group of options. A group of options requires that a set of
+ * component parameters is given as a whole.
+ *
+ * <a id="#syntax">The option syntax can be
+ * {@code "propertyName"} to denote required property and
+ * {@code "!propertyName"} to denote required absence of a property.
+ */
+public final class OptionsGroup implements Serializable {
+    private final String name;
+    private final Set<String> options;
+
+    /**
+     * Creates new named {@link OptionsGroup}.
+     *
+     * @param name the name of the group
+     */
+    public OptionsGroup(String name) {
+        this.name = name;
+        this.options = new HashSet<>();
+    }
+
+    /**
+     * Creates new named {@link OptionsGroup} with a set of option
+     * definitions.
+     *
+     * @param name the name of the group
+     * @param options names of properties in the syntax mentioned in {@link OptionsGroup}
+     */
+    public OptionsGroup(String name, Collection<String> options) {
+        this.name = name;
+        this.options = new LinkedHashSet<>(options);
+    }
+
+    /**
+     * Adds a option definition to this group. The option syntax can be
+     * {@code "propertyName"} to denote required property and
+     * {@code "!propertyName"} to denote required absence of a property.
+     *
+     * @param option definition.
+     */
+    public void addOption(String option) {
+        this.options.add(option);
+    }
+
+    /**
+     * The name of the group.
+     */
+    public String getName() {
+        return name;
+    }
+
+    /**
+     * The option definitions in this group.
+     */
+    public Set<String> getOptions() {
+        return this.options;
+    }
+
+    /**
+     * Adds a option definition to this group. The option syntax can be
+     * {@code "propertyName"} to denote required property and
+     * {@code "!propertyName"} to denote required absence of a property.
+     *
+     * @param option definition.
+     */
+    public OptionsGroup option(String option) {
+        this.options.add(option);
+        return this;
+    }
+
+    /**
+     * Adds a number of option definitions to this group. The option
+     * syntax can be {@code "propertyName"} to denote required
+     * property and {@code "!propertyName"} to denote required absence
+     * of a property.
+     *
+     * @param options options definition
+     */
+    public OptionsGroup options(String... options) {
+        for (String option : options) {
+            addOption(option);
+        }
+
+        return this;
+    }
+
+    /**
+     * Creates new group with the specified name.
+     *
+     * @param name the name of the group
+     */
+    public static OptionsGroup withName(String name) {
+        return new OptionsGroup(name);
+    }
+
+    /**
+     * Creates new group with the specified name of the given
+     * {@link Enum} name.
+     *
+     * @param enumItem the name of the group
+     * @see Enum#name()
+     */
+    public static OptionsGroup withName(Enum<?> enumItem) {
+        return new OptionsGroup(enumItem.name());
+    }
+
+    /**
+     * Creates new group with the specified name and option definitions.
+     *
+     * @param name the name of the group
+     * @param options options definition 
+     */
+    public static OptionsGroup withNameAndOptions(String name, String... options) {
+        return new OptionsGroup(name, Arrays.asList(options));
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/42529399/camel-core/src/main/java/org/apache/camel/component/extension/verifier/ResultBuilder.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/component/extension/verifier/ResultBuilder.java b/camel-core/src/main/java/org/apache/camel/component/extension/verifier/ResultBuilder.java
new file mode 100644
index 0000000..637bd08
--- /dev/null
+++ b/camel-core/src/main/java/org/apache/camel/component/extension/verifier/ResultBuilder.java
@@ -0,0 +1,141 @@
+/**
+ * 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.extension.verifier;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Optional;
+import java.util.function.Supplier;
+
+import org.apache.camel.component.extension.ComponentVerifierExtension;
+import org.apache.camel.util.function.ThrowingBiConsumer;
+import org.apache.camel.util.function.ThrowingConsumer;
+
+public final class ResultBuilder {
+    private Optional<ComponentVerifierExtension.Scope> scope;
+    private Optional<ComponentVerifierExtension.Result.Status> status;
+    private List<ComponentVerifierExtension.VerificationError> verificationErrors;
+
+    public ResultBuilder() {
+        this.scope = Optional.empty();
+        this.status = scope.empty();
+    }
+
+    // **********************************
+    // Accessors
+    // **********************************
+
+    public ResultBuilder scope(ComponentVerifierExtension.Scope scope) {
+        this.scope = Optional.of(scope);
+        return this;
+    }
+
+    public ResultBuilder status(ComponentVerifierExtension.Result.Status status) {
+        this.status = Optional.of(status);
+        return this;
+    }
+
+    public ResultBuilder error(ComponentVerifierExtension.VerificationError verificationError) {
+        if (this.verificationErrors == null) {
+            this.verificationErrors = new ArrayList<>();
+        }
+
+        this.verificationErrors.add(verificationError);
+        this.status = Optional.of(ComponentVerifierExtension.Result.Status.ERROR);
+
+        return this;
+    }
+
+    public ResultBuilder error(Optional<ComponentVerifierExtension.VerificationError> error) {
+        error.ifPresent(e -> error(e));
+        return this;
+    }
+
+    public ResultBuilder error(Supplier<Optional<ComponentVerifierExtension.VerificationError>> supplier) {
+        return error(supplier.get());
+    }
+
+    public ResultBuilder error(ThrowingConsumer<ResultBuilder, Exception> consumer) {
+        try {
+            consumer.accept(this);
+        } catch (NoSuchOptionException e) {
+            error(ResultErrorBuilder.withMissingOption(e.getOptionName()).build());
+        } catch (IllegalOptionException e) {
+            error(ResultErrorBuilder.withIllegalOption(e.getOptionName(), e.getOptionValue()).build());
+        } catch (Exception e) {
+            error(ResultErrorBuilder.withException(e).build());
+        }
+
+        return this;
+    }
+
+    public <T> ResultBuilder error(T data, ThrowingBiConsumer<ResultBuilder, T, Exception> consumer) {
+        try {
+            consumer.accept(this, data);
+        } catch (NoSuchOptionException e) {
+            error(ResultErrorBuilder.withMissingOption(e.getOptionName()).build());
+        } catch (IllegalOptionException e) {
+            error(ResultErrorBuilder.withIllegalOption(e.getOptionName(), e.getOptionValue()).build());
+        } catch (Exception e) {
+            error(ResultErrorBuilder.withException(e).build());
+        }
+
+        return this;
+    }
+
+    public ResultBuilder errors(List<ComponentVerifierExtension.VerificationError> verificationErrors) {
+        verificationErrors.forEach(this::error);
+        return this;
+    }
+
+    // **********************************
+    // Build
+    // **********************************
+
+    public ComponentVerifierExtension.Result build() {
+        return new DefaultResult(
+            scope.orElse(ComponentVerifierExtension.Scope.PARAMETERS),
+            status.orElse(ComponentVerifierExtension.Result.Status.UNSUPPORTED),
+            verificationErrors != null ? Collections.unmodifiableList(verificationErrors) : Collections.emptyList()
+        );
+    }
+
+    // **********************************
+    // Helpers
+    // **********************************
+
+    public static ResultBuilder withStatus(ComponentVerifierExtension.Result.Status status) {
+        return new ResultBuilder().status(status);
+    }
+
+    public static ResultBuilder withStatusAndScope(ComponentVerifierExtension.Result.Status status, ComponentVerifierExtension.Scope scope) {
+        return new ResultBuilder().status(status).scope(scope);
+    }
+
+    public static ResultBuilder withScope(ComponentVerifierExtension.Scope scope) {
+        return new ResultBuilder().scope(scope);
+    }
+
+    public static ResultBuilder unsupported() {
+        return withStatusAndScope(ComponentVerifierExtension.Result.Status.UNSUPPORTED, ComponentVerifierExtension.Scope.PARAMETERS);
+    }
+
+    public static ResultBuilder unsupportedScope(ComponentVerifierExtension.Scope scope) {
+        return withStatusAndScope(ComponentVerifierExtension.Result.Status.UNSUPPORTED, scope);
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/42529399/camel-core/src/main/java/org/apache/camel/component/extension/verifier/ResultErrorBuilder.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/component/extension/verifier/ResultErrorBuilder.java b/camel-core/src/main/java/org/apache/camel/component/extension/verifier/ResultErrorBuilder.java
new file mode 100644
index 0000000..313e9c2
--- /dev/null
+++ b/camel-core/src/main/java/org/apache/camel/component/extension/verifier/ResultErrorBuilder.java
@@ -0,0 +1,213 @@
+/**
+ * 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.extension.verifier;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Optional;
+import java.util.Set;
+import java.util.function.Supplier;
+
+import org.apache.camel.component.extension.ComponentVerifierExtension.VerificationError;
+import org.apache.camel.util.ObjectHelper;
+
+public final class ResultErrorBuilder {
+    private VerificationError.Code code;
+    private String description;
+    private Set<String> parameters;
+    private Map<VerificationError.Attribute, Object> attributes;
+
+    public ResultErrorBuilder() {
+    }
+
+    // **********************************
+    // Accessors
+    // **********************************
+
+    public ResultErrorBuilder code(VerificationError.Code code) {
+        this.code = code;
+        return this;
+    }
+
+    public ResultErrorBuilder code(String code) {
+        code(VerificationError.asCode(code));
+        return this;
+    }
+
+    public ResultErrorBuilder description(String description) {
+        this.description = description;
+        return this;
+    }
+
+    public ResultErrorBuilder parameterKey(String parameter) {
+        if (parameter != null) {
+            if (this.parameters == null) {
+                this.parameters = new HashSet<>();
+            }
+
+            this.parameters.add(parameter);
+        }
+        return this;
+    }
+
+    public ResultErrorBuilder parameterKeys(Collection<String> parameterList) {
+        if (parameterList != null) {
+            parameterList.forEach(this::parameterKey);
+        }
+
+        return this;
+    }
+
+    public ResultErrorBuilder detail(String key, Object value) {
+        detail(VerificationError.asAttribute(key), value);
+        return this;
+    }
+
+    public ResultErrorBuilder detail(VerificationError.Attribute key, Object value) {
+        if (value != null) {
+            if (this.attributes == null) {
+                this.attributes = new HashMap<>();
+            }
+
+            this.attributes.put(key, value);
+        }
+        return this;
+    }
+
+    public <T> ResultErrorBuilder detail(String key, Supplier<Optional<T>> supplier) {
+        detail(VerificationError.asAttribute(key), supplier);
+        return this;
+    }
+
+    public <T> ResultErrorBuilder detail(VerificationError.Attribute key, Supplier<Optional<T>> supplier) {
+        supplier.get().ifPresent(value -> detail(key, value));
+        return this;
+    }
+
+    public ResultErrorBuilder details(Map<VerificationError.Attribute, Object> details) {
+        for (Map.Entry<VerificationError.Attribute, Object> entry : details.entrySet()) {
+            detail(entry.getKey(), entry.getValue());
+        }
+
+        return this;
+    }
+
+    // **********************************
+    // Build
+    // **********************************
+
+    public VerificationError build() {
+        return new DefaultResultVerificationError(
+            code,
+            description,
+            parameters != null ? Collections.unmodifiableSet(parameters) : Collections.emptySet(),
+            attributes != null ? Collections.unmodifiableMap(attributes) : Collections.emptyMap()
+        );
+    }
+
+    // **********************************
+    // Helpers
+    // **********************************
+
+    public static ResultErrorBuilder fromError(VerificationError error) {
+        return new ResultErrorBuilder()
+            .code(error.getCode())
+            .description(error.getDescription())
+            .parameterKeys(error.getParameterKeys())
+            .details(error.getDetails());
+    }
+
+    public static ResultErrorBuilder withCode(VerificationError.Code code) {
+        return new ResultErrorBuilder().code(code);
+    }
+
+    public static ResultErrorBuilder withCode(String code) {
+        return new ResultErrorBuilder().code(code);
+    }
+
+    public static ResultErrorBuilder withHttpCode(int code) {
+        return withCode(convertHttpCodeToErrorCode(code))
+            .detail(VerificationError.HttpAttribute.HTTP_CODE, code);
+    }
+
+    public static ResultErrorBuilder withHttpCodeAndText(int code, String text) {
+        return withCodeAndDescription(convertHttpCodeToErrorCode(code), text)
+            .detail(VerificationError.HttpAttribute.HTTP_CODE, code)
+            .detail(VerificationError.HttpAttribute.HTTP_TEXT, text);
+    }
+
+    private static VerificationError.StandardCode convertHttpCodeToErrorCode(int code) {
+        return code >= 400 && code < 500 ? VerificationError.StandardCode.AUTHENTICATION : VerificationError.StandardCode.GENERIC;
+    }
+
+    public static ResultErrorBuilder withCodeAndDescription(VerificationError.Code code, String description) {
+        return new ResultErrorBuilder().code(code).description(description);
+    }
+
+    public static ResultErrorBuilder withUnsupportedScope(String scope) {
+        return new ResultErrorBuilder()
+            .code(VerificationError.StandardCode.UNSUPPORTED_SCOPE)
+            .description("Unsupported scope: " + scope);
+    }
+
+    public static ResultErrorBuilder withUnsupportedComponent(String component) {
+        return new ResultErrorBuilder()
+            .code(VerificationError.StandardCode.UNSUPPORTED_COMPONENT)
+            .description("Unsupported component: " + component);
+    }
+
+    public static ResultErrorBuilder withException(Exception exception) {
+        return new ResultErrorBuilder()
+            .code(VerificationError.StandardCode.EXCEPTION)
+            .description(exception.getMessage())
+            .detail(VerificationError.ExceptionAttribute.EXCEPTION_INSTANCE, exception)
+            .detail(VerificationError.ExceptionAttribute.EXCEPTION_CLASS, exception.getClass().getName());
+    }
+
+    public static ResultErrorBuilder withMissingOption(String optionName) {
+        return new ResultErrorBuilder()
+            .code(VerificationError.StandardCode.MISSING_PARAMETER)
+            .description(optionName + " should be set")
+            .parameterKey(optionName);
+    }
+
+    public static ResultErrorBuilder withUnknownOption(String optionName) {
+        return new ResultErrorBuilder()
+            .code(VerificationError.StandardCode.UNKNOWN_PARAMETER)
+            .description("Unknown option " + optionName)
+            .parameterKey(optionName);
+    }
+
+    public static ResultErrorBuilder withIllegalOption(String optionName) {
+        return new ResultErrorBuilder()
+            .code(VerificationError.StandardCode.ILLEGAL_PARAMETER)
+            .description("Illegal option " + optionName)
+            .parameterKey(optionName);
+    }
+
+    public static ResultErrorBuilder withIllegalOption(String optionName, String optionValue) {
+        return ObjectHelper.isNotEmpty(optionValue)
+            ? new ResultErrorBuilder()
+                .code(VerificationError.StandardCode.ILLEGAL_PARAMETER_VALUE)
+                .description(optionName + " has wrong value (" + optionValue + ")")
+                .parameterKey(optionName)
+            : withIllegalOption(optionName);
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/42529399/camel-core/src/main/java/org/apache/camel/component/extension/verifier/ResultErrorHelper.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/component/extension/verifier/ResultErrorHelper.java b/camel-core/src/main/java/org/apache/camel/component/extension/verifier/ResultErrorHelper.java
new file mode 100644
index 0000000..d03307e
--- /dev/null
+++ b/camel-core/src/main/java/org/apache/camel/component/extension/verifier/ResultErrorHelper.java
@@ -0,0 +1,164 @@
+/**
+ * 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.extension.verifier;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.Set;
+import java.util.TreeSet;
+import java.util.stream.Collectors;
+
+import org.apache.camel.component.extension.ComponentVerifierExtension.VerificationError;
+import org.apache.camel.util.ObjectHelper;
+
+/**
+ * Helper that validates component parameters.
+ */
+public final class ResultErrorHelper {
+
+    private ResultErrorHelper() {
+    }
+
+    // **********************************
+    // Helpers
+    // **********************************
+
+    /**
+     *
+     * @param parameterName the required option
+     * @param parameters the
+     * @return
+     */
+    public static Optional<VerificationError> requiresOption(String parameterName, Map<String, Object> parameters) {
+        if (ObjectHelper.isEmpty(parameters.get(parameterName))) {
+            return Optional.of(ResultErrorBuilder.withMissingOption(parameterName).build());
+        }
+
+        return Optional.empty();
+    }
+
+    /**
+     * Validates that the given parameters satisfy any grouped options
+     * ({@link OptionsGroup}). A parameter set is valid if it is
+     * present and required by least one of the groups.
+     *
+     * <p>As an example consider that there are two option groups that
+     * can be specified:
+     * <ul>
+     * <li>optionA: requires param1 and param2
+     * <li>optionB: requires param1 and param3
+     * </ul>
+     *
+     * Valid parameters are those that include param1 and either param2
+     * and/or param3.
+     *
+     * <p>Note the special syntax of {@link OptionsGroup#getOptions()}
+     * that can require an property ({@code "propertyName"}) or can
+     * forbid the presence of a property ({@code "!propertyName"}).
+     *
+     * <p>With that if in the example above if param2 is specified
+     * specifying param3 is not allowed, and vice versa option groups
+     * should be defined with options:
+     * <ul>
+     * <li>optionA: ["param1", "param2", "!param3"]
+     * <li>optionB: ["param1", "!param2", "param3"]
+     * </ul>
+     *
+     * @param parameters given parameters of a component
+     * @param groups groups of options
+     * @see OptionsGroup
+     */
+    public static List<VerificationError> requiresAny(Map<String, Object> parameters, OptionsGroup... groups) {
+        return requiresAny(parameters, Arrays.asList(groups));
+    }
+
+    /**
+     * Validates that the given parameters satisfy any grouped options
+     * ({@link OptionsGroup}). A parameter set is valid if it is
+     * present and required by least one of the groups.
+     *
+     * @param parameters given parameters of a component
+     * @param groups groups of options
+     * @see #requiresAny(Map, OptionsGroup...)
+     * @see OptionsGroup
+     */
+    public static List<VerificationError> requiresAny(Map<String, Object> parameters, Collection<OptionsGroup> groups) {
+        final List<VerificationError> verificationErrors = new ArrayList<>();
+        final Set<String> keys = new HashSet<>(parameters.keySet());
+
+        for (OptionsGroup group : groups) {
+            final Set<String> required = required(group.getOptions());
+            final Set<String> excluded = excluded(group.getOptions());
+
+            final ResultErrorBuilder builder = new ResultErrorBuilder()
+                .code(VerificationError.StandardCode.ILLEGAL_PARAMETER_GROUP_COMBINATION)
+                .detail(VerificationError.GroupAttribute.GROUP_NAME, group.getName())
+                .detail(VerificationError.GroupAttribute.GROUP_OPTIONS, String.join(",", parameters(group.getOptions())));
+
+            if (keys.containsAll(required)) {
+                // All the options of this group are found so we are good
+                final Set<String> shouldBeExcluded = new HashSet<>(keys);
+                shouldBeExcluded.retainAll(excluded);
+
+                if (shouldBeExcluded.isEmpty()) {
+                    // None of the excluded properties is present, also good
+                    return Collections.emptyList();
+                }
+
+                shouldBeExcluded.forEach(builder::parameterKey);
+                verificationErrors.add(builder.build());
+            } else {
+
+                for (String option : required) {
+                    if (!parameters.containsKey(option)) {
+                        builder.parameterKey(option);
+                    }
+                }
+
+                for (String option : excluded) {
+                    if (parameters.containsKey(option)) {
+                        builder.parameterKey(option);
+                    }
+                }
+
+                verificationErrors.add(builder.build());
+            }
+        }
+
+        return verificationErrors;
+    }
+
+    static Set<String> required(final Set<String> options) {
+        return options.stream().filter(o -> !o.startsWith("!")).collect(Collectors.toSet());
+    }
+
+    static Set<String> excluded(final Set<String> options) {
+        return options.stream().filter(o -> o.startsWith("!")).map(o -> o.substring(1)).collect(Collectors.toSet());
+    }
+
+    static Set<String> parameters(final Set<String> options) {
+        final Set<String> withoutExclusionMark = options.stream().map(o -> o.replaceFirst("!", "")).collect(Collectors.toSet());
+
+        return new TreeSet<String>(withoutExclusionMark);
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/42529399/camel-core/src/main/java/org/apache/camel/component/extension/verifier/package.html
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/component/extension/verifier/package.html b/camel-core/src/main/java/org/apache/camel/component/extension/verifier/package.html
new file mode 100644
index 0000000..cfeb0f5
--- /dev/null
+++ b/camel-core/src/main/java/org/apache/camel/component/extension/verifier/package.html
@@ -0,0 +1,25 @@
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one or more
+  ~ contributor license agreements.  See the NOTICE file distributed with
+  ~ this work for additional information regarding copyright ownership.
+  ~ The ASF licenses this file to You under the Apache License, Version 2.0
+  ~ (the "License"); you may not use this file except in compliance with
+  ~ the License.  You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+<html>
+<head>
+</head>
+<body>
+
+Verifier component extension
+
+</body>
+</html>

http://git-wip-us.apache.org/repos/asf/camel/blob/42529399/camel-core/src/main/java/org/apache/camel/component/rest/RestComponent.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/component/rest/RestComponent.java b/camel-core/src/main/java/org/apache/camel/component/rest/RestComponent.java
index 264750c..e2651a2 100644
--- a/camel-core/src/main/java/org/apache/camel/component/rest/RestComponent.java
+++ b/camel-core/src/main/java/org/apache/camel/component/rest/RestComponent.java
@@ -27,6 +27,7 @@ import org.apache.camel.CamelContext;
 import org.apache.camel.ComponentVerifier;
 import org.apache.camel.Endpoint;
 import org.apache.camel.VerifiableComponent;
+import org.apache.camel.component.extension.ComponentVerifierExtension;
 import org.apache.camel.impl.DefaultComponent;
 import org.apache.camel.model.rest.RestConstants;
 import org.apache.camel.spi.Metadata;
@@ -50,6 +51,10 @@ public class RestComponent extends DefaultComponent implements VerifiableCompone
     @Metadata(label = "producer")
     private String host;
 
+    public RestComponent() {
+        registerExtension(RestComponentVerifierExtension::new);
+    }
+
     @Override
     protected Endpoint createEndpoint(String uri, String remaining, Map<String, Object> parameters) throws Exception {
         String restConfigurationName = getAndRemoveParameter(parameters, "componentName", String.class, componentName);
@@ -235,13 +240,8 @@ public class RestComponent extends DefaultComponent implements VerifiableCompone
         }
     }
 
-    /**
-     * Get the {@link ComponentVerifier}
-     *
-     * @return the Component Verifier
-     */
     @Override
     public ComponentVerifier getVerifier() {
-        return new RestComponentVerifier(this);
+        return (scope, parameters) -> getExtension(ComponentVerifierExtension.class).orElseThrow(UnsupportedOperationException::new).verify(scope, parameters);
     }
 }

http://git-wip-us.apache.org/repos/asf/camel/blob/42529399/camel-core/src/main/java/org/apache/camel/component/rest/RestComponentVerifier.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/component/rest/RestComponentVerifier.java b/camel-core/src/main/java/org/apache/camel/component/rest/RestComponentVerifier.java
deleted file mode 100644
index 4013e5f..0000000
--- a/camel-core/src/main/java/org/apache/camel/component/rest/RestComponentVerifier.java
+++ /dev/null
@@ -1,152 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.camel.component.rest;
-
-import java.util.HashMap;
-import java.util.Map;
-
-import org.apache.camel.Component;
-import org.apache.camel.ComponentVerifier;
-import org.apache.camel.VerifiableComponent;
-import org.apache.camel.impl.verifier.CatalogVerifierCustomizer;
-import org.apache.camel.impl.verifier.DefaultComponentVerifier;
-import org.apache.camel.impl.verifier.ResultBuilder;
-import org.apache.camel.impl.verifier.ResultErrorBuilder;
-import org.apache.camel.runtimecatalog.JSonSchemaHelper;
-import org.apache.camel.runtimecatalog.RuntimeCamelCatalog;
-import org.apache.camel.spi.RestConsumerFactory;
-import org.apache.camel.spi.RestProducerFactory;
-import org.apache.camel.util.ObjectHelper;
-import org.apache.camel.util.function.Suppliers;
-
-public class RestComponentVerifier extends DefaultComponentVerifier {
-    private static final CatalogVerifierCustomizer CUSTOMIZER = new CatalogVerifierCustomizer().excludeUnknown();
-    private final RestComponent component;
-
-    RestComponentVerifier(RestComponent component) {
-        super("rest", component.getCamelContext());
-
-        this.component = component;
-    }
-
-    // *********************************
-    // Parameters validation
-    // *********************************
-
-    @Override
-    protected Result verifyParameters(Map<String, Object> parameters) {
-        ResultBuilder builder = ResultBuilder.withStatusAndScope(Result.Status.OK, Scope.PARAMETERS);
-
-        // Validate using the catalog but do not report unknown options as error
-        // as the may be used to customize the underlying component
-        super.verifyParametersAgainstCatalog(builder, parameters, CUSTOMIZER);
-
-        verifyUnderlyingComponent(Scope.PARAMETERS, builder, parameters);
-
-        return builder.build();
-    }
-
-    // *********************************
-    // Connectivity validation
-    // *********************************
-
-    @Override
-    protected Result verifyConnectivity(Map<String, Object> parameters) {
-        ResultBuilder builder = ResultBuilder.withStatusAndScope(Result.Status.OK, Scope.CONNECTIVITY);
-
-        verifyUnderlyingComponent(Scope.CONNECTIVITY, builder, parameters);
-
-        return builder.build();
-    }
-
-    // *********************************
-    // Helpers
-    // *********************************
-
-    protected void verifyUnderlyingComponent(Scope scope, ResultBuilder builder, Map<String, Object> parameters) {
-        // componentName is required for validation even at runtime camel might
-        // be able to find a suitable component at runtime.
-        String componentName = (String)parameters.get("componentName");
-        if (ObjectHelper.isNotEmpty(componentName)) {
-            try {
-                Component component = getTransportComponent(componentName);
-                if (component instanceof VerifiableComponent) {
-                    final RuntimeCamelCatalog catalog = getCamelContext().getRuntimeCamelCatalog();
-                    final String json = catalog.componentJSonSchema("rest");
-                    final Map<String, Object> restParameters = new HashMap<>(parameters);
-
-                    for (Map<String, String> m : JSonSchemaHelper.parseJsonSchema("componentProperties", json, true)) {
-                        String name = m.get("name");
-                        Object val = restParameters.remove(name);
-                        if (val != null) {
-                            // Add rest prefix to properties belonging to the rest
-                            // component so the underlying component know we want
-                            // to validate rest-related stuffs.
-                            restParameters.put("rest." + name, parameters.get(name));
-                        }
-                    }
-                    for (Map<String, String> m : JSonSchemaHelper.parseJsonSchema("properties", json, true)) {
-                        String name = m.get("name");
-                        Object val = restParameters.remove(name);
-                        if (val != null) {
-                            // Add rest prefix to properties belonging to the rest
-                            // component so the underlying component know we want
-                            // to validate rest-related stuffs.
-                            restParameters.put("rest." + name, parameters.get(name));
-                        }
-                    }
-
-                    ComponentVerifier verifier = ((VerifiableComponent)component).getVerifier();
-
-                    // restParameters now should contains rest-component related
-                    // properties with "rest." prefix and all the remaining can
-                    // be used to customize the underlying component (i.e. http
-                    // proxies, auth, etc)
-                    Result result = verifier.verify(scope, restParameters);
-
-                    // Combine errors and add an information about the component
-                    // they comes from
-                    for (VerificationError error : result.getErrors()) {
-                        builder.error(
-                            ResultErrorBuilder.fromError(error)
-                                .detail("component", componentName)
-                                .build()
-                        );
-                    }
-                } else {
-                    builder.error(
-                        ResultErrorBuilder.withUnsupportedComponent(componentName).build()
-                    );
-                }
-            } catch (Exception e) {
-                builder.error(
-                    ResultErrorBuilder.withException(e).build()
-                );
-            }
-        } else {
-            builder.error(ResultErrorBuilder.withMissingOption("componentName").build());
-        }
-    }
-
-    private Component getTransportComponent(String componentName) throws Exception {
-        return Suppliers.firstMatching(
-            comp -> comp != null && (comp instanceof RestConsumerFactory || comp instanceof RestProducerFactory),
-            () -> getCamelContext().getRegistry().lookupByNameAndType(componentName, Component.class),
-            () -> getCamelContext().getComponent(componentName, true, false)
-        ).orElse(null);
-    }
-}

http://git-wip-us.apache.org/repos/asf/camel/blob/42529399/camel-core/src/main/java/org/apache/camel/component/rest/RestComponentVerifierExtension.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/component/rest/RestComponentVerifierExtension.java b/camel-core/src/main/java/org/apache/camel/component/rest/RestComponentVerifierExtension.java
new file mode 100644
index 0000000..7a7fe76
--- /dev/null
+++ b/camel-core/src/main/java/org/apache/camel/component/rest/RestComponentVerifierExtension.java
@@ -0,0 +1,151 @@
+/**
+ * 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.rest;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Optional;
+
+import org.apache.camel.Component;
+import org.apache.camel.ComponentVerifier;
+import org.apache.camel.component.extension.ComponentVerifierExtension;
+import org.apache.camel.component.extension.verifier.CatalogVerifierCustomizer;
+import org.apache.camel.component.extension.verifier.DefaultComponentVerifierExtension;
+import org.apache.camel.component.extension.verifier.ResultBuilder;
+import org.apache.camel.component.extension.verifier.ResultErrorBuilder;
+import org.apache.camel.runtimecatalog.JSonSchemaHelper;
+import org.apache.camel.runtimecatalog.RuntimeCamelCatalog;
+import org.apache.camel.spi.RestConsumerFactory;
+import org.apache.camel.spi.RestProducerFactory;
+import org.apache.camel.util.ObjectHelper;
+import org.apache.camel.util.function.Suppliers;
+
+public class RestComponentVerifierExtension extends DefaultComponentVerifierExtension implements ComponentVerifier {
+    private static final CatalogVerifierCustomizer CUSTOMIZER = new CatalogVerifierCustomizer().excludeUnknown();
+
+    RestComponentVerifierExtension() {
+        super("rest");
+    }
+
+    // *********************************
+    // Parameters validation
+    // *********************************
+
+    @Override
+    protected Result verifyParameters(Map<String, Object> parameters) {
+        ResultBuilder builder = ResultBuilder.withStatusAndScope(Result.Status.OK, Scope.PARAMETERS);
+
+        // Validate using the catalog but do not report unknown options as error
+        // as the may be used to customize the underlying component
+        super.verifyParametersAgainstCatalog(builder, parameters, CUSTOMIZER);
+
+        verifyUnderlyingComponent(Scope.PARAMETERS, builder, parameters);
+
+        return builder.build();
+    }
+
+    // *********************************
+    // Connectivity validation
+    // *********************************
+
+    @Override
+    protected Result verifyConnectivity(Map<String, Object> parameters) {
+        ResultBuilder builder = ResultBuilder.withStatusAndScope(Result.Status.OK, Scope.CONNECTIVITY);
+
+        verifyUnderlyingComponent(Scope.CONNECTIVITY, builder, parameters);
+
+        return builder.build();
+    }
+
+    // *********************************
+    // Helpers
+    // *********************************
+
+    protected void verifyUnderlyingComponent(Scope scope, ResultBuilder builder, Map<String, Object> parameters) {
+        // componentName is required for validation even at runtime camel might
+        // be able to find a suitable component at runtime.
+        String componentName = (String)parameters.get("componentName");
+        if (ObjectHelper.isNotEmpty(componentName)) {
+            try {
+                final Component component = getTransportComponent(componentName);
+                final Optional<ComponentVerifierExtension> extension = component.getExtension(ComponentVerifierExtension.class);
+
+                if (extension.isPresent()) {
+                    final ComponentVerifierExtension verifier = extension.get();
+                    final RuntimeCamelCatalog catalog = getCamelContext().getRuntimeCamelCatalog();
+                    final String json = catalog.componentJSonSchema("rest");
+                    final Map<String, Object> restParameters = new HashMap<>(parameters);
+
+                    for (Map<String, String> m : JSonSchemaHelper.parseJsonSchema("componentProperties", json, true)) {
+                        String name = m.get("name");
+                        Object val = restParameters.remove(name);
+                        if (val != null) {
+                            // Add rest prefix to properties belonging to the rest
+                            // component so the underlying component know we want
+                            // to validate rest-related stuffs.
+                            restParameters.put("rest." + name, parameters.get(name));
+                        }
+                    }
+                    for (Map<String, String> m : JSonSchemaHelper.parseJsonSchema("properties", json, true)) {
+                        String name = m.get("name");
+                        Object val = restParameters.remove(name);
+                        if (val != null) {
+                            // Add rest prefix to properties belonging to the rest
+                            // component so the underlying component know we want
+                            // to validate rest-related stuffs.
+                            restParameters.put("rest." + name, parameters.get(name));
+                        }
+                    }
+
+                    // restParameters now should contains rest-component related
+                    // properties with "rest." prefix and all the remaining can
+                    // be used to customize the underlying component (i.e. http
+                    // proxies, auth, etc)
+                    Result result = verifier.verify(scope, restParameters);
+
+                    // Combine errors and add an information about the component
+                    // they comes from
+                    for (VerificationError error : result.getErrors()) {
+                        builder.error(
+                            ResultErrorBuilder.fromError(error)
+                                .detail("component", componentName)
+                                .build()
+                        );
+                    }
+                } else {
+                    builder.error(
+                        ResultErrorBuilder.withUnsupportedComponent(componentName).build()
+                    );
+                }
+            } catch (Exception e) {
+                builder.error(
+                    ResultErrorBuilder.withException(e).build()
+                );
+            }
+        } else {
+            builder.error(ResultErrorBuilder.withMissingOption("componentName").build());
+        }
+    }
+
+    private Component getTransportComponent(String componentName) throws Exception {
+        return Suppliers.firstMatching(
+            comp -> comp != null && (comp instanceof RestConsumerFactory || comp instanceof RestProducerFactory),
+            () -> getCamelContext().getRegistry().lookupByNameAndType(componentName, Component.class),
+            () -> getCamelContext().getComponent(componentName, true, false)
+        ).orElse(null);
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/42529399/camel-core/src/main/java/org/apache/camel/impl/DefaultComponent.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/impl/DefaultComponent.java b/camel-core/src/main/java/org/apache/camel/impl/DefaultComponent.java
index 9c97c2b..e8d994e 100644
--- a/camel-core/src/main/java/org/apache/camel/impl/DefaultComponent.java
+++ b/camel-core/src/main/java/org/apache/camel/impl/DefaultComponent.java
@@ -18,10 +18,14 @@ package org.apache.camel.impl;
 
 import java.net.URI;
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.List;
 import java.util.Map;
+import java.util.Optional;
+import java.util.function.Supplier;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
+import java.util.stream.Collectors;
 
 import org.apache.camel.CamelContext;
 import org.apache.camel.Component;
@@ -29,6 +33,8 @@ import org.apache.camel.ComponentConfiguration;
 import org.apache.camel.Endpoint;
 import org.apache.camel.EndpointConfiguration;
 import org.apache.camel.ResolveEndpointFailedException;
+import org.apache.camel.component.extension.ComponentExtension;
+import org.apache.camel.component.extension.ComponentExtensionHelper;
 import org.apache.camel.spi.Metadata;
 import org.apache.camel.support.ServiceSupport;
 import org.apache.camel.util.CamelContextHelper;
@@ -37,9 +43,11 @@ import org.apache.camel.util.IntrospectionSupport;
 import org.apache.camel.util.ObjectHelper;
 import org.apache.camel.util.URISupport;
 import org.apache.camel.util.UnsafeUriCharactersEncoder;
+import org.apache.camel.util.function.Suppliers;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+
 /**
  * Default component to use for base for components implementations.
  */
@@ -47,6 +55,8 @@ public abstract class DefaultComponent extends ServiceSupport implements Compone
     private static final Logger LOG = LoggerFactory.getLogger(DefaultComponent.class);
     private static final Pattern RAW_PATTERN = Pattern.compile("RAW(.*&&.*)");
 
+    private final List<Supplier<ComponentExtension>> extensions = new ArrayList<>();
+
     private CamelContext camelContext;
 
     @Metadata(label = "advanced", defaultValue = "true",
@@ -476,4 +486,30 @@ public abstract class DefaultComponent extends ServiceSupport implements Compone
         return null;
     }
 
+    protected final void registerExtension(ComponentExtension extension) {
+        extensions.add(() -> extension);
+    }
+
+    protected final void registerExtension(Supplier<ComponentExtension> supplier) {
+        extensions.add(Suppliers.memorize(supplier));
+    }
+
+    @Override
+    public Collection<Class<? extends ComponentExtension>> getSupportedExtensions() {
+        return extensions.stream()
+            .map(Supplier::get)
+            .map(ComponentExtension::getClass)
+            .collect(Collectors.toList());
+    }
+
+    @Override
+    public <T extends ComponentExtension> Optional<T> getExtension(Class<T> extensionType) {
+        return extensions.stream()
+            .map(Supplier::get)
+            .filter(extensionType::isInstance)
+            .findFirst()
+            .map(extensionType::cast)
+            .map(e -> ComponentExtensionHelper.trySetComponent(e, this))
+            .map(e -> ComponentExtensionHelper.trySetCamelContext(e, getCamelContext()));
+    }
 }

http://git-wip-us.apache.org/repos/asf/camel/blob/42529399/camel-core/src/main/java/org/apache/camel/impl/verifier/CatalogVerifierCustomizer.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/impl/verifier/CatalogVerifierCustomizer.java b/camel-core/src/main/java/org/apache/camel/impl/verifier/CatalogVerifierCustomizer.java
deleted file mode 100644
index 43d6993..0000000
--- a/camel-core/src/main/java/org/apache/camel/impl/verifier/CatalogVerifierCustomizer.java
+++ /dev/null
@@ -1,104 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.camel.impl.verifier;
-
-public class CatalogVerifierCustomizer {
-    private boolean includeUnknown = true;
-    private boolean includeRequired = true;
-    private boolean includeInvalidBoolean = true;
-    private boolean includeInvalidInteger = true;
-    private boolean includeInvalidNumber = true;
-    private boolean includeInvalidEnum = true;
-
-    public boolean isIncludeUnknown() {
-        return includeUnknown;
-    }
-
-    public void setIncludeUnknown(boolean includeUnknown) {
-        this.includeUnknown = includeUnknown;
-    }
-
-    public boolean isIncludeRequired() {
-        return includeRequired;
-    }
-
-    public void setIncludeRequired(boolean includeRequired) {
-        this.includeRequired = includeRequired;
-    }
-
-    public boolean isIncludeInvalidBoolean() {
-        return includeInvalidBoolean;
-    }
-
-    public void setIncludeInvalidBoolean(boolean includeInvalidBoolean) {
-        this.includeInvalidBoolean = includeInvalidBoolean;
-    }
-
-    public boolean isIncludeInvalidInteger() {
-        return includeInvalidInteger;
-    }
-
-    public void setIncludeInvalidInteger(boolean includeInvalidInteger) {
-        this.includeInvalidInteger = includeInvalidInteger;
-    }
-
-    public boolean isIncludeInvalidNumber() {
-        return includeInvalidNumber;
-    }
-
-    public void setIncludeInvalidNumber(boolean includeInvalidNumber) {
-        this.includeInvalidNumber = includeInvalidNumber;
-    }
-
-    public boolean isIncludeInvalidEnum() {
-        return includeInvalidEnum;
-    }
-
-    public void setIncludeInvalidEnum(boolean includeInvalidEnum) {
-        this.includeInvalidEnum = includeInvalidEnum;
-    }
-
-    public CatalogVerifierCustomizer excludeUnknown() {
-        this.includeUnknown = false;
-        return this;
-    }
-
-    public CatalogVerifierCustomizer excludeRequired() {
-        this.includeRequired = false;
-        return this;
-    }
-
-    public CatalogVerifierCustomizer excludeInvalidBoolean() {
-        this.includeInvalidBoolean = false;
-        return this;
-    }
-
-    public CatalogVerifierCustomizer excludeInvalidInteger() {
-        this.includeInvalidInteger = false;
-        return this;
-    }
-
-    public CatalogVerifierCustomizer excludeInvalidNumber() {
-        this.includeInvalidNumber = false;
-        return this;
-    }
-
-    public CatalogVerifierCustomizer excludeInvalidEnum() {
-        this.includeInvalidEnum = false;
-        return this;
-    }
-}

http://git-wip-us.apache.org/repos/asf/camel/blob/42529399/camel-core/src/main/java/org/apache/camel/impl/verifier/DefaultComponentVerifier.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/impl/verifier/DefaultComponentVerifier.java b/camel-core/src/main/java/org/apache/camel/impl/verifier/DefaultComponentVerifier.java
deleted file mode 100644
index f05cdb1..0000000
--- a/camel-core/src/main/java/org/apache/camel/impl/verifier/DefaultComponentVerifier.java
+++ /dev/null
@@ -1,202 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.camel.impl.verifier;
-
-import java.util.Map;
-import java.util.Optional;
-import java.util.function.Supplier;
-import java.util.stream.Collectors;
-
-import org.apache.camel.CamelContext;
-import org.apache.camel.ComponentVerifier;
-import org.apache.camel.NoSuchOptionException;
-import org.apache.camel.TypeConverter;
-import org.apache.camel.runtimecatalog.EndpointValidationResult;
-import org.apache.camel.runtimecatalog.RuntimeCamelCatalog;
-import org.apache.camel.util.CamelContextHelper;
-import org.apache.camel.util.EndpointHelper;
-import org.apache.camel.util.IntrospectionSupport;
-
-import static org.apache.camel.util.StreamUtils.stream;
-
-public class DefaultComponentVerifier implements ComponentVerifier {
-    private final String defaultScheme;
-    private final CamelContext camelContext;
-
-    public DefaultComponentVerifier(String defaultScheme, CamelContext camelContext) {
-        this.defaultScheme = defaultScheme;
-        this.camelContext = camelContext;
-    }
-
-    // *************************************
-    //
-    // *************************************
-
-    @Override
-    public Result verify(Scope scope, Map<String, Object> parameters) {
-        // Camel context is mandatory
-        if (this.camelContext == null) {
-            return ResultBuilder.withStatusAndScope(Result.Status.ERROR, scope)
-                .error(ResultErrorBuilder.withCodeAndDescription(VerificationError.StandardCode.INTERNAL, "Missing camel-context").build())
-                .build();
-        }
-
-        if (scope == Scope.PARAMETERS) {
-            return verifyParameters(parameters);
-        }
-        if (scope == Scope.CONNECTIVITY) {
-            return verifyConnectivity(parameters);
-        }
-
-        return ResultBuilder.unsupportedScope(scope).build();
-    }
-
-    protected Result verifyConnectivity(Map<String, Object> parameters) {
-        return ResultBuilder.withStatusAndScope(Result.Status.UNSUPPORTED, Scope.CONNECTIVITY).build();
-    }
-
-    protected Result verifyParameters(Map<String, Object> parameters) {
-        ResultBuilder builder = ResultBuilder.withStatusAndScope(Result.Status.OK, Scope.PARAMETERS);
-
-        // Validate against catalog
-        verifyParametersAgainstCatalog(builder, parameters);
-
-        return builder.build();
-    }
-
-    // *************************************
-    // Helpers :: Parameters validation
-    // *************************************
-
-    protected void verifyParametersAgainstCatalog(ResultBuilder builder, Map<String, Object> parameters) {
-        verifyParametersAgainstCatalog(builder, parameters, new CatalogVerifierCustomizer());
-    }
-
-    protected void verifyParametersAgainstCatalog(ResultBuilder builder, Map<String, Object> parameters, CatalogVerifierCustomizer customizer) {
-        String scheme = defaultScheme;
-        if (parameters.containsKey("scheme")) {
-            scheme = parameters.get("scheme").toString();
-        }
-
-        // Grab the runtime catalog to check parameters
-        RuntimeCamelCatalog catalog = camelContext.getRuntimeCamelCatalog();
-
-        // Convert from Map<String, Object> to  Map<String, String> as required
-        // by the Camel Catalog
-        EndpointValidationResult result = catalog.validateProperties(
-            scheme,
-            parameters.entrySet().stream()
-                .collect(
-                    Collectors.toMap(
-                        Map.Entry::getKey,
-                        e -> camelContext.getTypeConverter().convertTo(String.class, e.getValue())
-                    )
-                )
-        );
-
-        if (!result.isSuccess()) {
-            if (customizer.isIncludeUnknown()) {
-                stream(result.getUnknown())
-                    .map(option -> ResultErrorBuilder.withUnknownOption(option).build())
-                    .forEach(builder::error);
-            }
-            if (customizer.isIncludeRequired()) {
-                stream(result.getRequired())
-                    .map(option -> ResultErrorBuilder.withMissingOption(option).build())
-                    .forEach(builder::error);
-            }
-            if (customizer.isIncludeInvalidBoolean()) {
-                stream(result.getInvalidBoolean())
-                    .map(entry -> ResultErrorBuilder.withIllegalOption(entry.getKey(), entry.getValue()).build())
-                    .forEach(builder::error);
-            }
-            if (customizer.isIncludeInvalidInteger()) {
-                stream(result.getInvalidInteger())
-                    .map(entry -> ResultErrorBuilder.withIllegalOption(entry.getKey(), entry.getValue()).build())
-                    .forEach(builder::error);
-            }
-            if (customizer.isIncludeInvalidNumber()) {
-                stream(result.getInvalidNumber())
-                    .map(entry -> ResultErrorBuilder.withIllegalOption(entry.getKey(), entry.getValue()).build())
-                    .forEach(builder::error);
-            }
-            if (customizer.isIncludeInvalidEnum()) {
-                stream(result.getInvalidEnum())
-                    .map(entry ->
-                        ResultErrorBuilder.withIllegalOption(entry.getKey(), entry.getValue())
-                            .detail("enum.values", result.getEnumChoices(entry.getKey()))
-                            .build())
-                    .forEach(builder::error);
-            }
-        }
-    }
-
-    // *************************************
-    // Helpers
-    // *************************************
-
-    protected CamelContext getCamelContext() {
-        return camelContext;
-    }
-
-    protected <T> T setProperties(T instance, Map<String, Object> properties) throws Exception {
-        if (camelContext == null) {
-            throw new IllegalStateException("Camel context is null");
-        }
-
-        if (!properties.isEmpty()) {
-            final TypeConverter converter = camelContext.getTypeConverter();
-
-            IntrospectionSupport.setProperties(converter, instance, properties);
-
-            for (Map.Entry<String, Object> entry : properties.entrySet()) {
-                if (entry.getValue() instanceof String) {
-                    String value = (String)entry.getValue();
-                    if (EndpointHelper.isReferenceParameter(value)) {
-                        IntrospectionSupport.setProperty(camelContext, converter, instance, entry.getKey(), null, value, true);
-                    }
-                }
-            }
-        }
-
-        return instance;
-    }
-
-    protected <T> T setProperties(T instance, String prefix, Map<String, Object> properties) throws Exception {
-        return setProperties(
-            instance,
-            IntrospectionSupport.extractProperties(properties, prefix, false)
-        );
-    }
-
-    protected <T> Optional<T> getOption(Map<String, Object> parameters, String key, Class<T> type) {
-        Object value = parameters.get(key);
-        if (value != null) {
-            return Optional.ofNullable(CamelContextHelper.convertTo(camelContext, type, value));
-        }
-
-        return Optional.empty();
-    }
-
-    protected <T> T getOption(Map<String, Object> parameters, String key, Class<T> type, Supplier<T> defaultSupplier) {
-        return getOption(parameters, key, type).orElseGet(defaultSupplier);
-    }
-
-    protected <T> T getMandatoryOption(Map<String, Object> parameters, String key, Class<T> type) throws NoSuchOptionException {
-        return getOption(parameters, key, type).orElseThrow(() ->  new NoSuchOptionException(key));
-    }
-}

http://git-wip-us.apache.org/repos/asf/camel/blob/42529399/camel-core/src/main/java/org/apache/camel/impl/verifier/DefaultResult.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/impl/verifier/DefaultResult.java b/camel-core/src/main/java/org/apache/camel/impl/verifier/DefaultResult.java
deleted file mode 100644
index ad36d5f..0000000
--- a/camel-core/src/main/java/org/apache/camel/impl/verifier/DefaultResult.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.camel.impl.verifier;
-
-import java.util.List;
-
-import org.apache.camel.ComponentVerifier;
-
-public class DefaultResult implements ComponentVerifier.Result {
-    private final ComponentVerifier.Scope scope;
-    private final Status status;
-    private final List<ComponentVerifier.VerificationError> verificationErrors;
-
-    public DefaultResult(ComponentVerifier.Scope scope, Status status, List<ComponentVerifier.VerificationError> verificationErrors) {
-        this.scope = scope;
-        this.status = status;
-        this.verificationErrors = verificationErrors;
-    }
-
-    @Override
-    public ComponentVerifier.Scope getScope() {
-        return scope;
-    }
-
-    @Override
-    public Status getStatus() {
-        return status;
-    }
-
-    @Override
-    public List<ComponentVerifier.VerificationError> getErrors() {
-        return verificationErrors;
-    }
-
-    @Override
-    public String toString() {
-        return "DefaultResult{"
-               + "scope=" + scope
-               + ", status=" + status
-               + ", errors=" + verificationErrors
-               + '}';
-    }
-}

http://git-wip-us.apache.org/repos/asf/camel/blob/42529399/camel-core/src/main/java/org/apache/camel/impl/verifier/DefaultResultVerificationError.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/impl/verifier/DefaultResultVerificationError.java b/camel-core/src/main/java/org/apache/camel/impl/verifier/DefaultResultVerificationError.java
deleted file mode 100644
index 8bc8727..0000000
--- a/camel-core/src/main/java/org/apache/camel/impl/verifier/DefaultResultVerificationError.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.camel.impl.verifier;
-
-import java.util.Map;
-import java.util.Set;
-
-import org.apache.camel.ComponentVerifier.VerificationError;
-
-public class DefaultResultVerificationError implements VerificationError {
-    private final Code code;
-    private final String description;
-    private final Set<String> parameterKeys;
-    private final Map<Attribute, Object> details;
-
-    public DefaultResultVerificationError(Code code, String description, Set<String> parameterKeys, Map<Attribute, Object> details) {
-        this.code = code;
-        this.description = description;
-        this.parameterKeys = parameterKeys;
-        this.details = details;
-    }
-
-    @Override
-    public Code getCode() {
-        return code;
-    }
-
-    @Override
-    public String getDescription() {
-        return description;
-    }
-
-    @Override
-    public Set<String> getParameterKeys() {
-        return parameterKeys;
-    }
-
-    @Override
-    public Map<Attribute, Object> getDetails() {
-        return details;
-    }
-
-    @Override
-    public String toString() {
-        return "DefaultResultError{"
-               + "code='" + code + '\''
-               + ", description='" + description + '\''
-               + ", parameterKeys=" + parameterKeys
-               + ", details=" + details
-               + '}';
-    }
-}


[19/19] camel git commit: CAMEL-11555: ServiceNow : create a maven plugin to generate models based on table layout

Posted by lb...@apache.org.
CAMEL-11555: ServiceNow : create a maven plugin to generate models based on table layout


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

Branch: refs/heads/master
Commit: 109da7c9a62cf6e0b6fcf027cc82d99310843c4e
Parents: 80e25c4
Author: lburgazzoli <lb...@gmail.com>
Authored: Wed Aug 2 18:18:21 2017 +0200
Committer: lburgazzoli <lb...@gmail.com>
Committed: Fri Aug 4 18:09:05 2017 +0200

----------------------------------------------------------------------
 .../camel-servicenow-component/pom.xml          | 197 ++++++
 .../src/main/docs/servicenow-component.adoc     | 300 ++++++++
 .../servicenow/AbstractServiceNowProcessor.java | 293 ++++++++
 .../servicenow/AbstractServiceNowProducer.java  |  40 ++
 .../component/servicenow/ServiceNowClient.java  | 274 ++++++++
 .../servicenow/ServiceNowComponent.java         | 226 ++++++
 .../ServiceNowComponentVerifierExtension.java   | 109 +++
 .../servicenow/ServiceNowConfiguration.java     | 689 +++++++++++++++++++
 .../servicenow/ServiceNowConstants.java         |  80 +++
 .../servicenow/ServiceNowDispatcher.java        |  55 ++
 .../servicenow/ServiceNowEndpoint.java          |  80 +++
 .../servicenow/ServiceNowException.java         |  69 ++
 .../servicenow/ServiceNowExceptionModel.java    |  43 ++
 .../component/servicenow/ServiceNowHelper.java  |  95 +++
 .../servicenow/ServiceNowMetaDataExtension.java | 478 +++++++++++++
 .../component/servicenow/ServiceNowParam.java   |  28 +
 .../component/servicenow/ServiceNowParams.java  | 123 ++++
 .../servicenow/ServiceNowProducer.java          |  23 +
 .../servicenow/ServiceNowProducerSupplier.java  |  22 +
 .../component/servicenow/ServiceNowRelease.java |  41 ++
 .../annotations/ServiceNowSysParm.java          |  32 +
 .../annotations/ServiceNowSysParms.java         |  28 +
 .../auth/AuthenticationRequestFilter.java       |  56 ++
 .../component/servicenow/auth/OAuthToken.java   | 107 +++
 .../servicenow/model/DictionaryEntry.java       |  56 ++
 .../servicenow/model/ImportSetResponse.java     |  57 ++
 .../servicenow/model/ImportSetResult.java       |  83 +++
 .../component/servicenow/model/Reference.java   |  56 ++
 .../fuji/FujiServiceNowAggregateProcessor.java  |  72 ++
 .../fuji/FujiServiceNowImportSetProcessor.java  |  86 +++
 .../releases/fuji/FujiServiceNowProcessor.java  |  60 ++
 .../releases/fuji/FujiServiceNowProducer.java   |  36 +
 .../fuji/FujiServiceNowTableProcessor.java      | 175 +++++
 .../HelsinkiServiceNowAggregateProcessor.java   |  77 +++
 .../HelsinkiServiceNowAttachmentProcessor.java  | 179 +++++
 .../HelsinkiServiceNowImportSetProcessor.java   | 143 ++++
 .../HelsinkiServiceNowMiscProcessor.java        |  94 +++
 .../helsinki/HelsinkiServiceNowProducer.java    |  42 ++
 .../HelsinkiServiceNowScorecardProcessor.java   |  87 +++
 ...iServiceNowServiceCatalogCartsProcessor.java | 218 ++++++
 ...iceNowServiceCatalogCategoriesProcessor.java |  69 ++
 ...iServiceNowServiceCatalogItemsProcessor.java | 216 ++++++
 ...lsinkiServiceNowServiceCatalogProcessor.java | 118 ++++
 .../HelsinkiServiceNowTableProcessor.java       | 214 ++++++
 .../src/main/resources/META-INF/LICENSE.txt     | 203 ++++++
 .../src/main/resources/META-INF/NOTICE.txt      |  11 +
 .../org/apache/camel/component/servicenow       |  18 +
 .../servicenow/ServiceNowAttachmentTest.java    | 129 ++++
 .../ServiceNowBlueprintComponentAuthTest.java   |  67 ++
 .../ServiceNowBlueprintEndpointAuthTest.java    |  61 ++
 ...erviceNowComponentVerifierExtensionTest.java | 151 ++++
 .../ServiceNowComponentVerifierTest.java        | 147 ++++
 .../servicenow/ServiceNowImportSetTest.java     | 147 ++++
 .../ServiceNowMetaDataExtensionTest.java        |  87 +++
 .../servicenow/ServiceNowScorecardTest.java     |  63 ++
 .../ServiceNowServiceCatalogTest.java           |  93 +++
 .../servicenow/ServiceNowTableTest.java         | 361 ++++++++++
 .../component/servicenow/ServiceNowTest.java    | 174 +++++
 .../servicenow/ServiceNowTestSupport.java       | 122 ++++
 .../servicenow/model/AttachmentMeta.java        |  92 +++
 .../component/servicenow/model/Incident.java    |  97 +++
 .../servicenow/model/IncidentWithParms.java     |  64 ++
 .../component/servicenow/model/Scorecard.java   |  46 ++
 .../blueprint/blueprint-component-auth.xml      |  55 ++
 .../blueprint/blueprint-endpoint-auth.xml       |  37 +
 .../src/test/resources/log4j2.properties        |  43 ++
 .../src/test/resources/my-content.txt           |  16 +
 .../camel-servicenow-maven-plugin/pom.xml       | 319 +++++++++
 .../src/it/settings.xml                         |  53 ++
 .../src/it/simple-it/pom.xml                    |  64 ++
 .../src/it/simple-it/verify.groovy              |  21 +
 .../maven/CamelServiceNowGenerateMojo.java      | 324 +++++++++
 .../maven/CamelServiceNowGenerateMojoTest.java  |  40 ++
 .../maven/CamelServiceNowMojoTestSupport.java   |  56 ++
 .../src/test/resources/log4j2.properties        |  43 ++
 components/camel-servicenow/pom.xml             | 192 +-----
 .../src/main/docs/servicenow-component.adoc     | 300 --------
 .../servicenow/AbstractServiceNowProcessor.java | 293 --------
 .../servicenow/AbstractServiceNowProducer.java  |  40 --
 .../component/servicenow/ServiceNowClient.java  | 274 --------
 .../servicenow/ServiceNowComponent.java         | 226 ------
 .../ServiceNowComponentVerifierExtension.java   | 109 ---
 .../servicenow/ServiceNowConfiguration.java     | 689 -------------------
 .../servicenow/ServiceNowConstants.java         |  80 ---
 .../servicenow/ServiceNowDispatcher.java        |  55 --
 .../servicenow/ServiceNowEndpoint.java          |  80 ---
 .../servicenow/ServiceNowException.java         |  69 --
 .../servicenow/ServiceNowExceptionModel.java    |  43 --
 .../component/servicenow/ServiceNowHelper.java  |  95 ---
 .../servicenow/ServiceNowMetaDataExtension.java | 457 ------------
 .../component/servicenow/ServiceNowParam.java   |  28 -
 .../component/servicenow/ServiceNowParams.java  | 123 ----
 .../servicenow/ServiceNowProducer.java          |  23 -
 .../servicenow/ServiceNowProducerSupplier.java  |  22 -
 .../component/servicenow/ServiceNowRelease.java |  41 --
 .../annotations/ServiceNowSysParm.java          |  32 -
 .../annotations/ServiceNowSysParms.java         |  28 -
 .../auth/AuthenticationRequestFilter.java       |  56 --
 .../component/servicenow/auth/OAuthToken.java   | 107 ---
 .../servicenow/model/DictionaryEntry.java       |  56 --
 .../servicenow/model/ImportSetResponse.java     |  57 --
 .../servicenow/model/ImportSetResult.java       |  83 ---
 .../component/servicenow/model/Reference.java   |  56 --
 .../fuji/FujiServiceNowAggregateProcessor.java  |  72 --
 .../fuji/FujiServiceNowImportSetProcessor.java  |  86 ---
 .../releases/fuji/FujiServiceNowProcessor.java  |  60 --
 .../releases/fuji/FujiServiceNowProducer.java   |  36 -
 .../fuji/FujiServiceNowTableProcessor.java      | 175 -----
 .../HelsinkiServiceNowAggregateProcessor.java   |  77 ---
 .../HelsinkiServiceNowAttachmentProcessor.java  | 179 -----
 .../HelsinkiServiceNowImportSetProcessor.java   | 143 ----
 .../HelsinkiServiceNowMiscProcessor.java        |  94 ---
 .../helsinki/HelsinkiServiceNowProducer.java    |  42 --
 .../HelsinkiServiceNowScorecardProcessor.java   |  87 ---
 ...iServiceNowServiceCatalogCartsProcessor.java | 218 ------
 ...iceNowServiceCatalogCategoriesProcessor.java |  69 --
 ...iServiceNowServiceCatalogItemsProcessor.java | 216 ------
 ...lsinkiServiceNowServiceCatalogProcessor.java | 118 ----
 .../HelsinkiServiceNowTableProcessor.java       | 214 ------
 .../src/main/resources/META-INF/LICENSE.txt     | 203 ------
 .../src/main/resources/META-INF/NOTICE.txt      |  11 -
 .../org/apache/camel/component/servicenow       |  18 -
 .../servicenow/ServiceNowAttachmentTest.java    | 129 ----
 .../ServiceNowBlueprintComponentAuthTest.java   |  67 --
 .../ServiceNowBlueprintEndpointAuthTest.java    |  61 --
 ...erviceNowComponentVerifierExtensionTest.java | 151 ----
 .../ServiceNowComponentVerifierTest.java        | 147 ----
 .../servicenow/ServiceNowImportSetTest.java     | 147 ----
 .../ServiceNowMetaDataExtensionTest.java        |  87 ---
 .../servicenow/ServiceNowScorecardTest.java     |  63 --
 .../ServiceNowServiceCatalogTest.java           |  93 ---
 .../servicenow/ServiceNowTableTest.java         | 361 ----------
 .../component/servicenow/ServiceNowTest.java    | 174 -----
 .../servicenow/ServiceNowTestSupport.java       | 122 ----
 .../servicenow/model/AttachmentMeta.java        |  92 ---
 .../component/servicenow/model/Incident.java    |  97 ---
 .../servicenow/model/IncidentWithParms.java     |  64 --
 .../component/servicenow/model/Scorecard.java   |  46 --
 .../blueprint/blueprint-component-auth.xml      |  55 --
 .../blueprint/blueprint-endpoint-auth.xml       |  37 -
 .../src/test/resources/log4j2.properties        |  43 --
 .../src/test/resources/my-content.txt           |  16 -
 parent/pom.xml                                  |   3 +
 .../packaging/PrepareCatalogKarafMojo.java      |   5 +-
 .../maven/packaging/PrepareCatalogMojo.java     |   9 +-
 .../packaging/PrepareCatalogSpringBootMojo.java |   3 +
 .../maven/packaging/model/ComponentModel.java   |   2 +
 147 files changed, 8882 insertions(+), 7854 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/camel/blob/109da7c9/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
new file mode 100644
index 0000000..ea7040d
--- /dev/null
+++ b/components/camel-servicenow/camel-servicenow-component/pom.xml
@@ -0,0 +1,197 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You under the Apache License, Version 2.0
+    (the "License"); you may not use this file except in compliance with
+    the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+
+  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+    <groupId>org.apache.camel</groupId>
+    <artifactId>camel-servicenow-parent</artifactId>
+    <version>2.20.0-SNAPSHOT</version>
+  </parent>
+
+  <artifactId>camel-servicenow</artifactId>
+  <packaging>jar</packaging>
+  <name>Camel :: ServiceNow</name>
+  <description>Camel ServiceNow support</description>
+
+  <properties>
+    <camel.osgi.export.pkg>
+      org.apache.camel.component.servicenow.*
+    </camel.osgi.export.pkg>
+    <camel.osgi.export.service>
+      org.apache.camel.spi.ComponentResolver;component=servicenow
+    </camel.osgi.export.service>
+  </properties>
+
+
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.camel</groupId>
+      <artifactId>camel-core</artifactId>
+    </dependency>
+
+    <!-- CXF -->
+    <dependency>
+      <groupId>org.apache.cxf</groupId>
+      <artifactId>cxf-core</artifactId>
+      <version>${cxf-version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.cxf</groupId>
+      <artifactId>cxf-rt-frontend-jaxrs</artifactId>
+      <version>${cxf-version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.cxf</groupId>
+      <artifactId>cxf-rt-rs-security-oauth2</artifactId>
+      <version>${cxf-version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.cxf</groupId>
+      <artifactId>cxf-rt-rs-extension-providers</artifactId>
+      <version>${cxf-version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.cxf</groupId>
+      <artifactId>cxf-rt-rs-client</artifactId>
+      <version>${cxf-version}</version>
+    </dependency>
+
+    <!-- Jackson -->
+    <dependency>
+      <groupId>com.fasterxml.jackson.core</groupId>
+      <artifactId>jackson-core</artifactId>
+      <version>${jackson2-version}</version>
+    </dependency>
+    <dependency>
+      <groupId>com.fasterxml.jackson.core</groupId>
+      <artifactId>jackson-annotations</artifactId>
+      <version>${jackson2-version}</version>
+    </dependency>
+    <dependency>
+      <groupId>com.fasterxml.jackson.core</groupId>
+      <artifactId>jackson-databind</artifactId>
+      <version>${jackson2-version}</version>
+    </dependency>
+    <dependency>
+      <groupId>com.fasterxml.jackson.jaxrs</groupId>
+      <artifactId>jackson-jaxrs-json-provider</artifactId>
+      <version>${jackson2-version}</version>
+    </dependency>
+
+    <!-- testing -->
+
+    <dependency>
+      <groupId>javax.servlet</groupId>
+      <artifactId>javax.servlet-api</artifactId>
+      <version>${javax.servlet-api-version}</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.osgi</groupId>
+      <artifactId>org.osgi.compendium</artifactId>
+      <version>${osgi-version}</version>
+      <scope>test</scope>
+    </dependency>
+
+    <dependency>
+      <groupId>org.apache.camel</groupId>
+      <artifactId>camel-test</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.camel</groupId>
+      <artifactId>camel-test-blueprint</artifactId>
+      <scope>test</scope>
+    </dependency>
+
+    <dependency>
+      <groupId>org.apache.logging.log4j</groupId>
+      <artifactId>log4j-api</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.logging.log4j</groupId>
+      <artifactId>log4j-core</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.logging.log4j</groupId>
+      <artifactId>log4j-slf4j-impl</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.mockito</groupId>
+      <artifactId>mockito-all</artifactId>
+      <version>${mockito-version}</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.hamcrest</groupId>
+      <artifactId>java-hamcrest</artifactId>
+      <version>${hamcrest-version}</version>
+      <scope>test</scope>
+    </dependency>
+  </dependencies>
+
+  <build>
+    <plugins>
+          <plugin>
+            <artifactId>maven-surefire-plugin</artifactId>
+            <configuration>
+              <skipTests>true</skipTests>
+            </configuration>
+          </plugin>
+    </plugins>
+  </build>
+
+  <profiles>
+    <profile>
+      <id>servicenow-tests</id>
+      <activation>
+        <property>
+            <name>env.SERVICENOW_INSTANCE</name>
+        </property>
+      </activation>
+      <build>
+        <plugins>
+          <plugin>
+            <artifactId>maven-surefire-plugin</artifactId>
+            <configuration>
+              <skipTests>false</skipTests>
+              <systemPropertyVariables>
+                <servicenow.instance>${env.SERVICENOW_INSTANCE}</servicenow.instance>
+                <servicenow.username>${env.SERVICENOW_USERNAME}</servicenow.username>
+                <servicenow.password>${env.SERVICENOW_PASSWORD}</servicenow.password>
+              </systemPropertyVariables>
+            </configuration>
+          </plugin>
+        </plugins>
+      </build>
+    </profile>
+  </profiles>
+
+</project>

http://git-wip-us.apache.org/repos/asf/camel/blob/109da7c9/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
new file mode 100644
index 0000000..197ebd9
--- /dev/null
+++ b/components/camel-servicenow/camel-servicenow-component/src/main/docs/servicenow-component.adoc
@@ -0,0 +1,300 @@
+## ServiceNow Component
+
+*Available as of Camel version 2.18*
+
+The ServiceNow component provides access to ServiceNow platform through their REST API.
+
+NOTE: From Camel 2.18.1 the component supports multiple version of ServiceNow platform with default to Helsinki. Supported version are <<ServiceNow-Fuji>> and <<ServiceNow-Helsinki>>
+
+
+Maven users will need to add the following dependency to their pom.xml
+for this component:
+
+[source,java]
+-------------------------------------------------
+    <dependency>
+        <groupId>org.apache.camel</groupId>
+        <artifactId>camel-servicenow</artifactId>
+        <version>${camel-version}</version>
+    </dependency>
+-------------------------------------------------
+
+### URI format
+
+[source,java]
+---------------------------------------
+    servicenow://instanceName?[options]
+---------------------------------------
+
+### Options
+
+
+// component options: START
+The ServiceNow component supports 10 options which are listed below.
+
+
+
+[width="100%",cols="2,5,^1,2",options="header"]
+|=======================================================================
+| Name | Description | Default | Type
+| **instanceName** (advanced) | The ServiceNow instance name |  | String
+| **configuration** (advanced) | The ServiceNow default configuration |  | ServiceNowConfiguration
+| **apiUrl** (producer) | The ServiceNow REST API url |  | String
+| **userName** (security) | ServiceNow user account name |  | String
+| **password** (security) | ServiceNow account password |  | String
+| **oauthClientId** (security) | OAuth2 ClientID |  | String
+| **oauthClientSecret** (security) | OAuth2 ClientSecret |  | String
+| **oauthTokenUrl** (security) | OAuth token Url |  | 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
+|=======================================================================
+// component options: END
+
+
+// endpoint options: START
+The ServiceNow endpoint is configured using URI syntax:
+
+    servicenow:instanceName
+
+with the following path and query parameters:
+
+#### Path Parameters (1 parameters):
+
+[width="100%",cols="2,5,^1,2",options="header"]
+|=======================================================================
+| Name | Description | Default | Type
+| **instanceName** | *Required* The ServiceNow instance name |  | String
+|=======================================================================
+
+#### Query Parameters (41 parameters):
+
+[width="100%",cols="2,5,^1,2",options="header"]
+|=======================================================================
+| Name | Description | Default | Type
+| **display** (producer) | Set this parameter to true to return only scorecards where the indicator Display field is selected. Set this parameter to all to return scorecards with any Display field value. This parameter is true by default. | true | String
+| **displayValue** (producer) | Return the display value (true) actual value (false) or both (all) for reference fields (default: false) | false | String
+| **excludeReferenceLink** (producer) | True to exclude Table API links for reference fields (default: false) |  | Boolean
+| **favorites** (producer) | Set this parameter to true to return only scorecards that are favorites of the querying user. |  | Boolean
+| **includeAggregates** (producer) | Set this parameter to true to always return all available aggregates for an indicator including when an aggregate has already been applied. If a value is not specified this parameter defaults to false and returns no aggregates. |  | Boolean
+| **includeAvailableAggregates** (producer) | Set this parameter to true to return all available aggregates for an indicator when no aggregate has been applied. If a value is not specified this parameter defaults to false and returns no aggregates. |  | Boolean
+| **includeAvailableBreakdowns** (producer) | Set this parameter to true to return all available breakdowns for an indicator. If a value is not specified this parameter defaults to false and returns no breakdowns. |  | Boolean
+| **includeScoreNotes** (producer) | Set this parameter to true to return all notes associated with the score. The note element contains the note text as well as the author and timestamp when the note was added. |  | Boolean
+| **includeScores** (producer) | Set this parameter to true to return all scores for a scorecard. If a value is not specified this parameter defaults to false and returns only the most recent score value. |  | Boolean
+| **inputDisplayValue** (producer) | True to set raw value of input fields (default: false) |  | Boolean
+| **key** (producer) | Set this parameter to true to return only scorecards for key indicators. |  | Boolean
+| **models** (producer) | Defines both request and response models |  | String
+| **perPage** (producer) | Enter the maximum number of scorecards each query can return. By default this value is 10 and the maximum is 100. | 10 | Integer
+| **release** (producer) | The ServiceNow release to target default to Helsinki See https://docs.servicenow.com | HELSINKI | ServiceNowRelease
+| **requestModels** (producer) | Defines the request model |  | String
+| **resource** (producer) | The default resource can be overridden by header CamelServiceNowResource |  | String
+| **responseModels** (producer) | Defines the response model |  | String
+| **sortBy** (producer) | Specify the value to use when sorting results. By default queries sort records by value. |  | String
+| **sortDir** (producer) | Specify the sort direction ascending or descending. By default queries sort records in descending order. Use sysparm_sortdir=asc to sort in ascending order. |  | String
+| **suppressAutoSysField** (producer) | True to suppress auto generation of system fields (default: false) |  | Boolean
+| **suppressPaginationHeader** (producer) | Set this value to true to remove the Link header from the response. The Link header allows you to request additional pages of data when the number of records matching your query exceeds the query limit |  | Boolean
+| **table** (producer) | The default table can be overridden by header CamelServiceNowTable |  | String
+| **target** (producer) | Set this parameter to true to return only scorecards that have a target. |  | Boolean
+| **topLevelOnly** (producer) | Gets only those categories whose parent is a catalog. |  | Boolean
+| **apiVersion** (advanced) | The ServiceNow REST API version default latest |  | String
+| **httpClientPolicy** (advanced) | To configure http-client |  | HTTPClientPolicy
+| **mapper** (advanced) | Sets Jackson's ObjectMapper to use for request/reply |  | ObjectMapper
+| **proxyAuthorizationPolicy** (advanced) | To configure proxy authentication |  | ProxyAuthorization Policy
+| **retrieveTargetRecordOn Import** (advanced) | Set this parameter to true to retrieve the target record when using import set api. The import set result is then replaced by the target record | false | Boolean
+| **synchronous** (advanced) | Sets whether synchronous processing should be strictly used or Camel is allowed to use asynchronous processing (if supported). | false | boolean
+| **proxyHost** (proxy) | The proxy host name |  | String
+| **proxyPort** (proxy) | The proxy port number |  | Integer
+| **apiUrl** (security) | The ServiceNow REST API url |  | String
+| **oauthClientId** (security) | OAuth2 ClientID |  | String
+| **oauthClientSecret** (security) | OAuth2 ClientSecret |  | String
+| **oauthTokenUrl** (security) | OAuth token Url |  | String
+| **password** (security) | *Required* ServiceNow account password MUST be provided |  | String
+| **proxyPassword** (security) | Password for proxy authentication |  | String
+| **proxyUserName** (security) | Username for proxy authentication |  | String
+| **sslContextParameters** (security) | To configure security using SSLContextParameters. See http://camel.apache.org/camel-configuration-utilities.html |  | SSLContextParameters
+| **userName** (security) | *Required* ServiceNow user account name MUST be provided |  | String
+|=======================================================================
+// endpoint options: END
+
+
+
+### Headers
+
+[width="100%",cols="10%,10%,10%,10%,60%",options="header",]
+|===
+|Name |Type |ServiceNow API Parameter |Endpoint option |Description
+|CamelServiceNowResource |String | - | - | The resource to access
+|CamelServiceNowAction |String | - | - | The action to perform
+|CamelServiceNowActionSubject | - | - | String |The subject to which the action should be applied
+|CamelServiceNowModel |Class | - | - | The data model
+|CamelServiceNowRequestModel |Class | - | - | The request data model
+|CamelServiceNowResponseModel |Class | - | - | The response data model
+|CamelServiceNowOffsetNext | - | - | - | -
+|CamelServiceNowOffsetPrev | - | - | - | -
+|CamelServiceNowOffsetFirst | - | - | - | -
+|CamelServiceNowOffsetLast | - | - | - | -
+|CamelServiceNowContentType | - | - | - | -
+|CamelServiceNowContentEncoding | - | - | - | -
+|CamelServiceNowContentMeta | - | - | - | -
+|CamelServiceNowSysId |String | sys_id | - | -
+|CamelServiceNowUserSysId |String | user_sysid | - | -
+|CamelServiceNowUserId |String | user_id | - | -
+|CamelServiceNowCartItemId |String | cart_item_id | - | -
+|CamelServiceNowFileName |String | file_name | - | -
+|CamelServiceNowTable |String | table_name | - | -
+|CamelServiceNowTableSysId |String | table_sys_id | - | -
+|CamelServiceNowEncryptionContext | String | encryption_context | - | -
+|CamelServiceNowCategory | String | sysparm_category  | - | -
+|CamelServiceNowType |String | sysparm_type | - | -
+|CamelServiceNowCatalog | String | sysparm_catalog | - | -
+|CamelServiceNowQuery |String | sysparm_query | - | -
+|CamelServiceNowDisplayValue |String | sysparm_display_value | displayValue  | -
+|CamelServiceNowInputDisplayValue |Boolean | sysparm_input_display_value | inputDisplayValue  | -
+|CamelServiceNowExcludeReferenceLink |Boolean | sysparm_exclude_reference_link | excludeReferenceLink  | -
+|CamelServiceNowFields |String | sysparm_fields | - | -
+|CamelServiceNowLimit |Integer | sysparm_limit | - | -
+|CamelServiceNowText | String | sysparm_text | - | -
+|CamelServiceNowOffset | Integer | sysparm_offset | - | -
+|CamelServiceNowView |String | sysparm_view | - | -
+|CamelServiceNowSuppressAutoSysField |Boolean | sysparm_suppress_auto_sys_field | suppressAutoSysField | -
+|CamelServiceNowSuppressPaginationHeader | Booleab | sysparm_suppress_pagination_header | suppressPaginationHeader | -
+|CamelServiceNowMinFields |String | sysparm_min_fields | - | -
+|CamelServiceNowMaxFields |String | sysparm_max_fields | - | -
+|CamelServiceNowSumFields |String | sysparm_sum_fields | - | -
+|CamelServiceNowAvgFields |String | sysparm_avg_fields | - | -
+|CamelServiceNowCount |Boolean | sysparm_count | - | -
+|CamelServiceGroupBy |String | sysparm_group_by | - | -
+|CamelServiceOrderBy |String | sysparm_order_by | - | -
+|CamelServiceHaving |String | sysparm_having | - | -
+|CamelServiceNowUUID |String | sysparm_uuid | - | -
+|CamelServiceNowBreakdown| String| sysparm_breakdown | - | -
+|CamelServiceNowIncludeScores| Boolean | sysparm_include_scores | includeScores | -
+|CamelServiceNowIncludeScoreNotes | Boolean | sysparm_include_score_notes | includeScoreNotes | -
+|CamelServiceNowIncludeAggregates | Boolean | sysparm_include_aggregates | includeAggregates | -
+|CamelServiceNowIncludeAvailableBreakdowns | Boolean | sysparm_include_available_breakdowns | includeAvailableBreakdowns | -
+|CamelServiceNowIncludeAvailableAggregates | Boolean | sysparm_include_available_aggregates | includeAvailableAggregates | -
+|CamelServiceNowFavorites | Boolean | sysparm_favorites | favorites | -
+|CamelServiceNowKey  | Boolean | sysparm_key | key | -
+|CamelServiceNowTarget | Boolean | sysparm_target | target | -
+|CamelServiceNowDisplay | String | sysparm_display | display | -
+|CamelServiceNowPerPage | Integer | sysparm_per_page | perPage | -
+|CamelServiceNowSortBy | String | sysparm_sortby | sortBy | -
+|CamelServiceNowSortDir | String | sysparm_sortdit | sortDir | -
+|CamelServiceNowContains | String | sysparm_contains | - | -
+|CamelServiceNowTags | String | sysparm_tags | - | -
+|CamelServiceNowPage | String | sysparm_page | - | -
+|CamelServiceNowElementsFilter | String | sysparm_elements_filter | - | -
+|CamelServiceNowBreakdownRelation | String | sysparm_breakdown_relation | - | -
+|CamelServiceNowDataSource | String | sysparm_data_source | - | -
+|CamelServiceNowTopLevelOnly | Boolean | sysparm_top_level_only | topLevelOnly | -
+|CamelServiceNowApiVersion | String | - | - | The REST API version
+|CamelServiceNowResponseMeta | Map | - | - | Meta data provided along with a response
+|===
+
+[[ServiceNow-Fuji]]
+[cols="10%a,10%a,10%a,70%a", options="header"]
+.API Mapping
+|===
+| CamelServiceNowResource | CamelServiceNowAction | Method | API URI
+1.5+<.^|TABLE
+| RETRIEVE | GET | /api/now/v1/table/{table_name}/{sys_id}
+| CREATE | POST | /api/now/v1/table/{table_name}
+| MODIFY | PUT | /api/now/v1/table/{table_name}/{sys_id}
+| DELETE | DELETE | /api/now/v1/table/{table_name}/{sys_id}
+| UPDATE | PATCH | /api/now/v1/table/{table_name}/{sys_id}
+
+| AGGREGATE
+| RETRIEVE | GET | /api/now/v1/stats/{table_name}
+
+1.2+<.^|IMPORT
+| RETRIEVE | GET | /api/now/import/{table_name}/{sys_id}
+| CREATE | POST | /api/now/import/{table_name}
+|===
+
+NOTE: link:http://wiki.servicenow.com/index.php?title=REST_API#Available_APIs[Fuji REST API Documentation]
+
+[[ServiceNow-Helsinki]]
+[cols="10%a,10%a,10%a,10%a,60%a", options="header"]
+.API Mapping
+|===
+| CamelServiceNowResource | CamelServiceNowAction | CamelServiceNowActionSubject | Method | API URI
+1.5+<.^|TABLE
+| RETRIEVE | | GET | /api/now/v1/table/{table_name}/{sys_id}
+| CREATE | | POST | /api/now/v1/table/{table_name}
+| MODIFY | | PUT | /api/now/v1/table/{table_name}/{sys_id}
+| DELETE | | DELETE | /api/now/v1/table/{table_name}/{sys_id}
+| UPDATE | | PATCH | /api/now/v1/table/{table_name}/{sys_id}
+
+| AGGREGATE
+| RETRIEVE | | GET | /api/now/v1/stats/{table_name}
+
+1.2+<.^|IMPORT
+| RETRIEVE | | GET | /api/now/import/{table_name}/{sys_id}
+| CREATE | | POST | /api/now/import/{table_name}
+
+1.4+<.^|ATTACHMENT
+| RETRIEVE | | GET | /api/now/api/now/attachment/{sys_id}
+| CONTENT | | GET | /api/now/attachment/{sys_id}/file
+| UPLOAD | | POST | /api/now/api/now/attachment/file
+| DELETE | | DELETE | /api/now/attachment/{sys_id}
+
+| SCORECARDS
+| RETRIEVE | PERFORMANCE_ANALYTICS | GET | /api/now/pa/scorecards
+
+1.2+<.^|MISC
+| RETRIEVE | USER_ROLE_INHERITANCE | GET | /api/global/user_role_inheritance
+| CREATE | IDENTIFY_RECONCILE | POST | /api/now/identifyreconcile
+
+1.2+<.^|SERVICE_CATALOG
+| RETRIEVE | | GET | /sn_sc/servicecatalog/catalogs/{sys_id}
+| RETRIEVE | CATEGORIES |  GET | /sn_sc/servicecatalog/catalogs/{sys_id}/categories
+
+1.5+<.^|SERVICE_CATALOG_ITEMS
+| RETRIEVE | | GET | /sn_sc/servicecatalog/items/{sys_id}
+| RETRIEVE | SUBMIT_GUIDE | POST | /sn_sc/servicecatalog/items/{sys_id}/submit_guide
+| RETRIEVE | CHECKOUT_GUIDE | POST | /sn_sc/servicecatalog/items/{sys_id}/checkout_guide
+| CREATE | SUBJECT_CART | POST | /sn_sc/servicecatalog/items/{sys_id}/add_to_cart
+| CREATE | SUBJECT_PRODUCER | POST | /sn_sc/servicecatalog/items/{sys_id}/submit_producer
+
+1.6+<.^|SERVICE_CATALOG_CARTS
+| RETRIEVE | | GET | /sn_sc/servicecatalog/cart
+| RETRIEVE | DELIVERY_ADDRESS | GET | /sn_sc/servicecatalog/cart/delivery_address/{user_id}
+| RETRIEVE | CHECKOUT | POST | /sn_sc/servicecatalog/cart/checkout
+| UPDATE | | POST | /sn_sc/servicecatalog/cart/{cart_item_id}
+| UPDATE | CHECKOUT | POST | /sn_sc/servicecatalog/cart/submit_order
+| DELETE | | DELETE | /sn_sc/servicecatalog/cart/{sys_id}/empty
+
+| SERVICE_CATALOG_CATEGORIES
+| RETRIEVE | | GET | /sn_sc/servicecatalog/categories/{sys_id}
+
+|===
+
+NOTE: https://docs.servicenow.com/bundle/helsinki-servicenow-platform/page/integrate/inbound-rest/reference/r_RESTResources.html[Helsinki REST API Documentation]
+
+### Usage examples:
+ 
+{% raw %}
+[source,java]
+.Retrieve 10 Incidents
+-------------------------------------------------------------------------------------------------------------------
+context.addRoutes(new RouteBuilder() {
+    public void configure() {
+       from("direct:servicenow")
+           .to("servicenow:{{env:SERVICENOW_INSTANCE}}"
+               + "?userName={{env:SERVICENOW_USERNAME}}"
+               + "&password={{env:SERVICENOW_PASSWORD}}"
+               + "&oauthClientId={{env:SERVICENOW_OAUTH2_CLIENT_ID}}"
+               + "&oauthClientSecret={{env:SERVICENOW_OAUTH2_CLIENT_SECRET}}"
+           .to("mock:servicenow");
+    }
+}); 
+
+FluentProducerTemplate.on(context)
+    .withHeader(ServiceNowConstants.RESOURCE, "table")
+    .withHeader(ServiceNowConstants.ACTION, ServiceNowConstants.ACTION_RETRIEVE)
+    .withHeader(ServiceNowConstants.SYSPARM_LIMIT.getId(), "10")
+    .withHeader(ServiceNowConstants.TABLE, "incident")
+    .withHeader(ServiceNowConstants.MODEL, Incident.class)
+    .to("direct:servicenow")
+    .send();
+-------------------------------------------------------------------------------------------------------------------
+{% endraw %}

http://git-wip-us.apache.org/repos/asf/camel/blob/109da7c9/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/AbstractServiceNowProcessor.java
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/AbstractServiceNowProcessor.java b/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/AbstractServiceNowProcessor.java
new file mode 100644
index 0000000..1ae25af
--- /dev/null
+++ b/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/AbstractServiceNowProcessor.java
@@ -0,0 +1,293 @@
+/**
+ * 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.servicenow;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.Response;
+
+import com.fasterxml.jackson.databind.JavaType;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.apache.camel.Exchange;
+import org.apache.camel.Message;
+import org.apache.camel.Processor;
+import org.apache.camel.util.ObjectHelper;
+
+public abstract class AbstractServiceNowProcessor implements Processor {
+
+    protected final ServiceNowEndpoint endpoint;
+    protected final ServiceNowConfiguration config;
+    protected final ObjectMapper mapper;
+    protected final ServiceNowClient client;
+
+    // Cache for JavaTypes
+    private final JavaTypeCache javaTypeCache;
+    private final List<ServiceNowDispatcher> dispatchers;
+
+    protected AbstractServiceNowProcessor(ServiceNowEndpoint endpoint) throws Exception {
+        this.javaTypeCache = new JavaTypeCache();
+        this.endpoint = endpoint;
+        this.config = endpoint.getConfiguration();
+        this.mapper = ObjectHelper.notNull(config.getMapper(), "mapper");
+        this.client = new ServiceNowClient(endpoint.getCamelContext(), config);
+        this.dispatchers = new ArrayList<>();
+    }
+
+    protected AbstractServiceNowProcessor setBodyAndHeaders(Message message, Class<?> responseModel, Response response) throws Exception {
+        if (response != null) {
+            setHeaders(message, responseModel, response);
+            setBody(message, responseModel, response);
+        }
+
+        return this;
+    }
+
+    @Override
+    public void process(Exchange exchange) throws Exception {
+        final ServiceNowDispatcher dispatcher = findDispatcher(exchange);
+
+        if (dispatcher != null) {
+            dispatcher.process(exchange);
+        } else {
+            throw new IllegalArgumentException("Unable to process exchange");
+        }
+    }
+
+    // *********************************
+    // Header
+    // *********************************
+
+    protected AbstractServiceNowProcessor setHeaders(Message message, Class<?> responseModel, Response response) throws Exception {
+        ServiceNowHelper.findOffsets(response, (k, v) -> message.setHeader(k, v));
+
+        String attachmentMeta = response.getHeaderString(ServiceNowConstants.ATTACHMENT_META_HEADER);
+        if (ObjectHelper.isNotEmpty(attachmentMeta)) {
+            message.setHeader(
+                ServiceNowConstants.CONTENT_META,
+                mapper.readValue(attachmentMeta, Map.class)
+            );
+        }
+
+        copyHeader(response, HttpHeaders.CONTENT_TYPE, message, ServiceNowConstants.CONTENT_TYPE);
+        copyHeader(response, HttpHeaders.CONTENT_ENCODING, message, ServiceNowConstants.CONTENT_ENCODING);
+
+        if (responseModel != null) {
+            message.getHeaders().putIfAbsent(ServiceNowConstants.MODEL, responseModel.getName());
+            message.getHeaders().putIfAbsent(ServiceNowConstants.RESPONSE_MODEL, responseModel.getName());
+        }
+
+        return this;
+    }
+
+    // *********************************
+    // Body
+    // *********************************
+
+    protected AbstractServiceNowProcessor setBody(Message message, Class<?> model, Response response) throws Exception {
+        if (message != null && response != null) {
+            if (ObjectHelper.isNotEmpty(response.getHeaderString(HttpHeaders.CONTENT_TYPE))) {
+
+                JsonNode root = response.readEntity(JsonNode.class);
+                Map<String, String> responseAttributes = null;
+
+                if (root != null) {
+                    Iterator<Map.Entry<String, JsonNode>> fields = root.fields();
+                    while (fields.hasNext()) {
+                        final Map.Entry<String, JsonNode> entry = fields.next();
+                        final String key = entry.getKey();
+                        final JsonNode node = entry.getValue();
+
+                        if (ObjectHelper.equal("result", key, true)) {
+                            Object body = unwrap(node, model);
+                            if (body != null) {
+                                message.setHeader(ServiceNowConstants.RESPONSE_TYPE, body.getClass());
+                                message.setBody(body);
+                            }
+                        } else {
+                            if (responseAttributes == null) {
+                                responseAttributes = new HashMap<>();
+                            }
+
+                            responseAttributes.put(key, node.textValue());
+                        }
+                    }
+
+                    if (responseAttributes != null) {
+                        message.setHeader(ServiceNowConstants.RESPONSE_META, responseAttributes);
+                    }
+                }
+            }
+        }
+
+        return this;
+    }
+
+    protected AbstractServiceNowProcessor validateBody(Message message, Class<?> model) {
+        return validateBody(message.getBody(), model);
+    }
+
+    protected AbstractServiceNowProcessor validateBody(Object body, Class<?> model) {
+        ObjectHelper.notNull(body, "body");
+
+        if (!body.getClass().isAssignableFrom(model)) {
+            throw new IllegalArgumentException(
+                "Body is not compatible with model (body=" + body.getClass() + ", model=" + model);
+        }
+
+        return this;
+    }
+
+    protected Object unwrap(JsonNode node, Class<?> model) throws IOException {
+        Object result;
+
+        if (node.isArray()) {
+            if (model.isInstance(Map.class)) {
+                // If the model is a Map, there's no need to use any
+                // specific JavaType to instruct Jackson about the
+                // expected element type
+                result = mapper.treeToValue(node, List.class);
+            } else {
+                result = mapper.readValue(node.traverse(), javaTypeCache.get(model));
+            }
+        } else {
+            result = mapper.treeToValue(node, model);
+        }
+
+        return result;
+    }
+
+    // *********************************
+    // Helpers
+    // *********************************
+
+    protected final void addDispatcher(ServiceNowDispatcher dispatcher) {
+        this.dispatchers.add(dispatcher);
+    }
+
+    protected final void addDispatcher(String action, Processor processor) {
+        addDispatcher(ServiceNowDispatcher.on(action, null, processor));
+    }
+
+    protected final void addDispatcher(String action, String subject, Processor processor) {
+        addDispatcher(ServiceNowDispatcher.on(action, subject, processor));
+    }
+
+    protected final ServiceNowDispatcher findDispatcher(Exchange exchange) {
+        ServiceNowDispatcher dispatcher = null;
+        for (int i = 0; i < dispatchers.size(); i++) {
+            dispatcher = dispatchers.get(i);
+            if (dispatcher.match(exchange)) {
+                return dispatcher;
+            }
+        }
+
+        return null;
+    }
+
+    // *********************************
+    // Helpers
+    // *********************************
+
+    protected Object getRequestParamFromHeader(ServiceNowParam sysParam, Message message) {
+        return message.getHeader(
+            sysParam.getHeader(),
+            sysParam.getDefaultValue(config),
+            sysParam.getType()
+        );
+    }
+
+    protected Object getMandatoryRequestParamFromHeader(ServiceNowParam sysParam, Message message) {
+        return ObjectHelper.notNull(
+            getRequestParamFromHeader(sysParam, message),
+            sysParam.getHeader()
+        );
+    }
+
+    protected void copyHeader(Response from, String fromId, Message to, String toId) {
+        Object fromValue = from.getHeaders().getFirst(fromId);
+        if (ObjectHelper.isNotEmpty(fromValue)) {
+            to.setHeader(toId, fromValue);
+        }
+    }
+
+    protected Class<?> getRequestModel(Message message) {
+        return getRequestModel(message, null);
+    }
+
+    protected Class<?> getRequestModel(Message message, String modelName) {
+        Class<?> model = null;
+
+        if (message != null) {
+            model = message.getHeader(ServiceNowConstants.REQUEST_MODEL, Class.class);
+            if (model == null) {
+                model = message.getHeader(ServiceNowConstants.MODEL, Class.class);
+            }
+        }
+
+        return model != null
+            ? model
+            : ObjectHelper.isEmpty(modelName) ? Map.class : config.getRequestModel(modelName, Map.class);
+    }
+
+    protected Class<?> getResponseModel(Message message) {
+        return getRequestModel(message, null);
+    }
+
+    protected Class<?> getResponseModel(Message message, String modelName) {
+        Class<?> model = null;
+
+        if (message != null) {
+            model = message.getHeader(ServiceNowConstants.RESPONSE_MODEL, Class.class);
+            if (model == null) {
+                model = message.getHeader(ServiceNowConstants.MODEL, Class.class);
+            }
+        }
+
+        return model != null
+            ? model
+            : ObjectHelper.isEmpty(modelName) ? Map.class : config.getResponseModel(modelName, Map.class);
+    }
+
+    protected String getApiVersion(Message message) {
+        return message.getHeader(ServiceNowConstants.API_VERSION, config.getApiVersion(), String.class);
+    }
+
+    protected String getTableName(Message message) {
+        return message.getHeader(ServiceNowParams.PARAM_TABLE_NAME.getHeader(), config.getTable(), String.class);
+    }
+
+    protected String getSysID(Message message) {
+        return message.getHeader(ServiceNowParams.PARAM_SYS_ID.getHeader(), String.class);
+    }
+
+    // *************************************************************************
+    // Use ClassValue to lazy create and cache JavaType
+    // *************************************************************************
+
+    private class JavaTypeCache extends ClassValue<JavaType> {
+        @Override
+        protected JavaType computeValue(Class<?> type) {
+            return mapper.getTypeFactory().constructCollectionType(List.class, type);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/109da7c9/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/AbstractServiceNowProducer.java
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/AbstractServiceNowProducer.java b/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/AbstractServiceNowProducer.java
new file mode 100644
index 0000000..0fd23d7
--- /dev/null
+++ b/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/AbstractServiceNowProducer.java
@@ -0,0 +1,40 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.servicenow;
+
+import org.apache.camel.impl.HeaderSelectorProducer;
+
+public abstract class AbstractServiceNowProducer extends HeaderSelectorProducer implements ServiceNowProducer {
+    private final ServiceNowRelease release;
+    private final ServiceNowEndpoint endpoint;
+
+    public AbstractServiceNowProducer(ServiceNowEndpoint endpoint, ServiceNowRelease release) {
+        super(endpoint, ServiceNowConstants.RESOURCE, endpoint.getConfiguration().getResource());
+
+        this.release = release;
+        this.endpoint = endpoint;
+    }
+
+    @Override
+    public ServiceNowRelease getRelease() {
+        return release;
+    }
+
+    protected final ServiceNowConfiguration getConfiguration() {
+        return endpoint.getConfiguration();
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/109da7c9/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
new file mode 100644
index 0000000..5128797
--- /dev/null
+++ b/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/ServiceNowClient.java
@@ -0,0 +1,274 @@
+/**
+ * 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.servicenow;
+
+import java.util.Arrays;
+import java.util.Map;
+import java.util.function.Function;
+import javax.net.ssl.SSLContext;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+import com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider;
+import org.apache.camel.CamelContext;
+import org.apache.camel.Message;
+import org.apache.camel.component.servicenow.annotations.ServiceNowSysParm;
+import org.apache.camel.component.servicenow.auth.AuthenticationRequestFilter;
+import org.apache.camel.util.ObjectHelper;
+import org.apache.camel.util.jsse.SSLContextParameters;
+import org.apache.cxf.configuration.jsse.TLSClientParameters;
+import org.apache.cxf.configuration.security.ProxyAuthorizationPolicy;
+import org.apache.cxf.jaxrs.client.WebClient;
+import org.apache.cxf.transport.http.HTTPConduit;
+import org.apache.cxf.transports.http.configuration.HTTPClientPolicy;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public final class ServiceNowClient {
+    private static final Logger LOGGER = LoggerFactory.getLogger(ServiceNowClient.class);
+
+    private final CamelContext camelContext;
+    private final ServiceNowConfiguration configuration;
+    private final WebClient client;
+
+    ServiceNowClient(CamelContext camelContext, ServiceNowConfiguration configuration) throws Exception {
+        this.camelContext = camelContext;
+        this.configuration = configuration;
+        this.client = WebClient.create(
+            configuration.getApiUrl(),
+            Arrays.asList(
+                new AuthenticationRequestFilter(configuration),
+                new JacksonJsonProvider(configuration.getMapper())
+            ),
+            true
+        );
+
+        configureRequestContext(camelContext, configuration, client);
+        configureTls(camelContext, configuration, client);
+        configureHttpClientPolicy(camelContext, configuration, client);
+        configureProxyAuthorizationPolicy(camelContext, configuration, client);
+    }
+
+    public ServiceNowClient types(MediaType type) {
+        return types(type, type);
+    }
+
+    public ServiceNowClient types(MediaType accept, MediaType type) {
+        client.accept(accept);
+        client.type(type);
+        return this;
+    }
+
+    public ServiceNowClient path(Object path) {
+        if (ObjectHelper.isNotEmpty(path)) {
+            client.path(path);
+        }
+
+        return this;
+    }
+
+    public ServiceNowClient type(MediaType ct) {
+        client.type(ct);
+        return this;
+    }
+
+    public ServiceNowClient type(String type) {
+        client.type(type);
+        return this;
+    }
+
+    public ServiceNowClient accept(MediaType... types) {
+        client.accept(types);
+        return this;
+    }
+
+    public ServiceNowClient accept(String... types) {
+        client.accept(types);
+        return this;
+    }
+
+    public ServiceNowClient query(String name, Object... values) {
+        client.query(name, values);
+        return this;
+    }
+
+    public ServiceNowClient queryF(String name, String format, Object... values) {
+        client.query(name, String.format(format, values));
+        return this;
+    }
+
+    public ServiceNowClient query(ServiceNowParam param, Message message) {
+        Object value = param.getHeaderValue(message, configuration);
+        if (value != null) {
+            client.query(param.getId(), value);
+        }
+
+        return this;
+    }
+
+    public ServiceNowClient query(Class<?> model) {
+        if (model != null) {
+            String name;
+            String value;
+
+            for (ServiceNowSysParm parm : model.getAnnotationsByType(ServiceNowSysParm.class)) {
+                name = parm.name();
+                value = parm.value();
+
+                // SysParms defined on model have precedence and replace query param
+                // with same name set via Message headers.
+                if (ObjectHelper.isNotEmpty(name) && ObjectHelper.isNotEmpty(value)) {
+                    LOGGER.debug("Replace query param {} with value {}", name, value);
+                    client.replaceQueryParam(name, value);
+                }
+            }
+        }
+
+        return this;
+    }
+
+    public Response invoke(String httpMethod) throws Exception {
+        return invoke(client, httpMethod, null);
+    }
+
+    public Response invoke(String httpMethod, Object body) throws Exception {
+        return invoke(client, httpMethod, body);
+    }
+
+    public <T> T trasform(String httpMethod, Function<Response, T> function) throws Exception {
+        return function.apply(invoke(client, httpMethod, null));
+    }
+
+    public <T> T trasform(String httpMethod, Object body, Function<Response, T> function) throws Exception {
+        return function.apply(invoke(client, httpMethod, body));
+    }
+
+    public ServiceNowClient reset() {
+        client.back(true);
+        client.reset();
+        client.resetQuery();
+
+        return this;
+    }
+
+    // *******************************
+    // Helpers
+    // *******************************
+
+    private Response invoke(WebClient client, String httpMethod, Object body) throws Exception {
+        Response response = client.invoke(httpMethod, body);
+        int code = response.getStatus();
+
+        // Only ServiceNow known error status codes are mapped
+        // See http://wiki.servicenow.com/index.php?title=REST_API#REST_Response_HTTP_Status_Codes
+        switch(code) {
+        case 200:
+        case 201:
+        case 204:
+            // Success
+            break;
+        case 400:
+        case 401:
+        case 403:
+        case 404:
+        case 405:
+        case 406:
+        case 415:
+            ServiceNowExceptionModel model = response.readEntity(ServiceNowExceptionModel.class);
+            throw new ServiceNowException(
+                code,
+                model.getStatus(),
+                model.getError().get("message"),
+                model.getError().get("detail")
+            );
+        default:
+            throw new ServiceNowException(
+                code,
+                response.readEntity(Map.class)
+            );
+        }
+
+        return response;
+    }
+
+    private static void configureRequestContext(
+            CamelContext context, ServiceNowConfiguration configuration, WebClient client) throws Exception {
+
+        WebClient.getConfig(client)
+            .getRequestContext()
+            .put("org.apache.cxf.http.header.split", true);
+    }
+
+    private static void configureTls(
+        CamelContext camelContext, ServiceNowConfiguration configuration, WebClient client) throws Exception {
+
+        SSLContextParameters sslContextParams = configuration.getSslContextParameters();
+        if (sslContextParams != null) {
+            HTTPConduit conduit = WebClient.getConfig(client).getHttpConduit();
+            TLSClientParameters tlsClientParams = conduit.getTlsClientParameters();
+            if (tlsClientParams == null) {
+                tlsClientParams = new TLSClientParameters();
+            }
+
+            SSLContext sslContext = sslContextParams.createSSLContext(camelContext);
+            tlsClientParams.setSSLSocketFactory(sslContext.getSocketFactory());
+
+            conduit.setTlsClientParameters(tlsClientParams);
+        }
+    }
+
+    private static void configureHttpClientPolicy(
+            CamelContext context, ServiceNowConfiguration configuration, WebClient client) throws Exception {
+
+        HTTPClientPolicy httpPolicy = configuration.getHttpClientPolicy();
+        if (httpPolicy == null) {
+            String host = configuration.getProxyHost();
+            Integer port = configuration.getProxyPort();
+
+            if (host != null && port != null) {
+                httpPolicy = new HTTPClientPolicy();
+                httpPolicy.setProxyServer(host);
+                httpPolicy.setProxyServerPort(port);
+            }
+        }
+
+        if (httpPolicy != null) {
+            WebClient.getConfig(client).getHttpConduit().setClient(httpPolicy);
+        }
+    }
+
+    private static void configureProxyAuthorizationPolicy(
+            CamelContext context, ServiceNowConfiguration configuration, WebClient client) throws Exception {
+
+        ProxyAuthorizationPolicy proxyPolicy = configuration.getProxyAuthorizationPolicy();
+        if (proxyPolicy == null) {
+            String username = configuration.getProxyUserName();
+            String password = configuration.getProxyPassword();
+
+            if (username != null && password != null) {
+                proxyPolicy = new ProxyAuthorizationPolicy();
+                proxyPolicy.setAuthorizationType("Basic");
+                proxyPolicy.setUserName(username);
+                proxyPolicy.setPassword(password);
+            }
+        }
+
+        if (proxyPolicy != null) {
+            WebClient.getConfig(client).getHttpConduit().setProxyAuthorization(proxyPolicy);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/109da7c9/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
new file mode 100644
index 0000000..c9cbb89
--- /dev/null
+++ b/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/ServiceNowComponent.java
@@ -0,0 +1,226 @@
+/**
+ * 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.servicenow;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Map;
+
+import org.apache.camel.CamelContext;
+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;
+import org.apache.camel.util.IntrospectionSupport;
+import org.apache.camel.util.ObjectHelper;
+
+/**
+ * Represents the component that manages {@link ServiceNowEndpoint}.
+ */
+@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")
+    private ServiceNowConfiguration configuration;
+    @Metadata(label = "security", defaultValue = "false")
+    private boolean useGlobalSslContextParameters;
+
+    private ServiceNowComponentVerifierExtension verifierExtension;
+    private ServiceNowMetaDataExtension metaDataExtension;
+
+    public ServiceNowComponent() {
+        this(null);
+    }
+
+    public ServiceNowComponent(CamelContext camelContext) {
+        super(camelContext);
+
+        this.configuration = new ServiceNowConfiguration();
+
+        registerExtension(ServiceNowComponentVerifierExtension::new);
+        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);
+    }
+
+    public String getInstanceName() {
+        return instanceName;
+    }
+
+    /**
+     * The ServiceNow instance name
+     */
+    public void setInstanceName(String instanceName) {
+        this.instanceName = instanceName;
+    }
+
+    public ServiceNowConfiguration getConfiguration() {
+        return configuration;
+    }
+
+    /**
+     * The ServiceNow default configuration
+     */
+    public void setConfiguration(ServiceNowConfiguration configuration) {
+        this.configuration = configuration;
+    }
+
+    public String getApiUrl() {
+        return configuration.getApiUrl();
+    }
+
+    /**
+     * The ServiceNow REST API url
+     */
+    public void setApiUrl(String apiUrl) {
+        configuration.setApiUrl(apiUrl);
+    }
+
+    public String getUserName() {
+        return configuration.getUserName();
+    }
+
+    /**
+     * ServiceNow user account name
+     */
+    @Metadata(label = "security", secret = true)
+    public void setUserName(String userName) {
+        configuration.setUserName(userName);
+    }
+
+    public String getPassword() {
+        return configuration.getPassword();
+    }
+
+    /**
+     * ServiceNow account password
+     */
+    @Metadata(label = "security", secret = true)
+    public void setPassword(String password) {
+        configuration.setPassword(password);
+    }
+
+    public String getOauthClientId() {
+        return configuration.getOauthClientId();
+    }
+
+    /**
+     * OAuth2 ClientID
+     */
+    @Metadata(label = "security", secret = true)
+    public void setOauthClientId(String oauthClientId) {
+        configuration.setOauthClientId(oauthClientId);
+    }
+
+    public String getOauthClientSecret() {
+        return configuration.getOauthClientSecret();
+    }
+
+    /**
+     * OAuth2 ClientSecret
+     */
+    @Metadata(label = "security", secret = true)
+    public void setOauthClientSecret(String oauthClientSecret) {
+        configuration.setOauthClientSecret(oauthClientSecret);
+    }
+
+    public String getOauthTokenUrl() {
+        return configuration.getOauthTokenUrl();
+    }
+
+    /**
+     * OAuth token Url
+     */
+    @Metadata(label = "security", secret = true)
+    public void setOauthTokenUrl(String oauthTokenUrl) {
+        configuration.setOauthTokenUrl(oauthTokenUrl);
+    }
+
+    @Override
+    public boolean isUseGlobalSslContextParameters() {
+        return this.useGlobalSslContextParameters;
+    }
+
+    /**
+     * Enable usage of global SSL context parameters.
+     */
+    @Override
+    public void setUseGlobalSslContextParameters(boolean useGlobalSslContextParameters) {
+        this.useGlobalSslContextParameters = useGlobalSslContextParameters;
+    }
+
+    @Override
+    public ComponentVerifier getVerifier() {
+        return (scope, parameters) -> getExtension(ComponentVerifierExtension.class).orElseThrow(UnsupportedOperationException::new).verify(scope, parameters);
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/109da7c9/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
new file mode 100644
index 0000000..0422238
--- /dev/null
+++ b/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/ServiceNowComponentVerifierExtension.java
@@ -0,0 +1,109 @@
+/**
+ * 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.servicenow;
+
+import java.util.Map;
+import javax.ws.rs.HttpMethod;
+import javax.ws.rs.core.MediaType;
+
+import org.apache.camel.component.extension.verifier.DefaultComponentVerifierExtension;
+import org.apache.camel.component.extension.verifier.NoSuchOptionException;
+import org.apache.camel.component.extension.verifier.ResultBuilder;
+import org.apache.camel.component.extension.verifier.ResultErrorBuilder;
+
+final class ServiceNowComponentVerifierExtension extends DefaultComponentVerifierExtension {
+
+    ServiceNowComponentVerifierExtension() {
+        super("servicenow");
+    }
+
+    // *********************************
+    // Parameters validation
+    // *********************************
+
+    @Override
+    protected Result verifyParameters(Map<String, Object> parameters) {
+        ResultBuilder builder = ResultBuilder.withStatusAndScope(Result.Status.OK, Scope.PARAMETERS);
+
+        // Validate using the catalog
+        super.verifyParametersAgainstCatalog(builder, parameters);
+
+        return builder.build();
+    }
+
+    // *********************************
+    // Connectivity validation
+    // *********************************
+
+    @Override
+    protected Result verifyConnectivity(Map<String, Object> parameters) {
+        // Default is success
+        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));
+            }
+
+            new ServiceNowClient(getCamelContext(), configuration)
+                .types(MediaType.APPLICATION_JSON_TYPE)
+                .path("now")
+                .path(configuration.getApiVersion())
+                .path("table")
+                .path(tableName)
+                .query(ServiceNowParams.SYSPARM_LIMIT.getId(), 1L)
+                .invoke(HttpMethod.GET);
+        } catch (NoSuchOptionException e) {
+            builder.error(
+                ResultErrorBuilder.withMissingOption(e.getOptionName()).build()
+            );
+        } catch (ServiceNowException e) {
+            ResultErrorBuilder errorBuilder = ResultErrorBuilder.withException(e)
+                .detail(VerificationError.HttpAttribute.HTTP_CODE, e.getCode())
+                .detail("servicenow_error_message", e.getMessage())
+                .detail("servicenow_error_status", e.getStatus())
+                .detail("servicenow_error_detail", e.getDetail());
+
+            if (e.getCode() == 401) {
+                errorBuilder.code(VerificationError.StandardCode.AUTHENTICATION);
+                errorBuilder.parameterKey("userName");
+                errorBuilder.parameterKey("password");
+                errorBuilder.parameterKey("oauthClientId");
+                errorBuilder.parameterKey("oauthClientSecret");
+            }
+
+            builder.error(errorBuilder.build());
+        } catch (Exception e) {
+            builder.error(
+                ResultErrorBuilder.withException(e).build()
+            );
+        }
+
+        return builder.build();
+    }
+}


[10/19] camel git commit: CAMEL-11555: ServiceNow : create a maven plugin to generate models based on table layout

Posted by lb...@apache.org.
http://git-wip-us.apache.org/repos/asf/camel/blob/109da7c9/components/camel-servicenow/src/test/java/org/apache/camel/component/servicenow/ServiceNowTableTest.java
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/src/test/java/org/apache/camel/component/servicenow/ServiceNowTableTest.java b/components/camel-servicenow/src/test/java/org/apache/camel/component/servicenow/ServiceNowTableTest.java
deleted file mode 100644
index e775e85..0000000
--- a/components/camel-servicenow/src/test/java/org/apache/camel/component/servicenow/ServiceNowTableTest.java
+++ /dev/null
@@ -1,361 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.camel.component.servicenow;
-
-import java.util.List;
-
-import org.apache.camel.CamelExecutionException;
-import org.apache.camel.Exchange;
-import org.apache.camel.builder.RouteBuilder;
-import org.apache.camel.component.mock.MockEndpoint;
-import org.apache.camel.component.servicenow.model.Incident;
-import org.apache.camel.component.servicenow.model.IncidentWithParms;
-import org.junit.Test;
-
-public class ServiceNowTableTest extends ServiceNowTestSupport {
-
-    @Test
-    public void testRetrieveSome() throws Exception {
-        MockEndpoint mock = getMockEndpoint("mock:servicenow");
-        mock.expectedMessageCount(1);
-
-        template().sendBodyAndHeaders(
-            "direct:servicenow",
-            null,
-            kvBuilder()
-                .put(ServiceNowConstants.RESOURCE, "table")
-                .put(ServiceNowConstants.ACTION, ServiceNowConstants.ACTION_RETRIEVE)
-                .put(ServiceNowParams.SYSPARM_LIMIT, 10)
-                .put(ServiceNowParams.PARAM_TABLE_NAME, "incident")
-                .build()
-        );
-
-        mock.assertIsSatisfied();
-
-        Exchange exchange = mock.getExchanges().get(0);
-        List<Incident> items = exchange.getIn().getBody(List.class);
-
-        assertNotNull(items);
-        assertTrue(items.size() <= 10);
-        assertNotNull(exchange.getIn().getHeader(ServiceNowConstants.RESPONSE_TYPE));
-        assertNotNull(exchange.getIn().getHeader(ServiceNowConstants.OFFSET_FIRST));
-        assertNotNull(exchange.getIn().getHeader(ServiceNowConstants.OFFSET_NEXT));
-        assertNotNull(exchange.getIn().getHeader(ServiceNowConstants.OFFSET_LAST));
-    }
-
-    @Test
-    public void testRetrieveSomeWithParams() throws Exception {
-        MockEndpoint mock = getMockEndpoint("mock:servicenow");
-        mock.expectedMessageCount(1);
-
-        template().sendBodyAndHeaders(
-            "direct:servicenow",
-            null,
-            kvBuilder()
-                .put(ServiceNowConstants.RESOURCE, "table")
-                .put(ServiceNowConstants.ACTION, ServiceNowConstants.ACTION_RETRIEVE)
-                .put(ServiceNowParams.SYSPARM_LIMIT, 10)
-                .put(ServiceNowParams.SYSPARM_EXCLUDE_REFERENCE_LINK, false)
-                .put(ServiceNowParams.PARAM_TABLE_NAME, "incident")
-                .put(ServiceNowConstants.MODEL, IncidentWithParms.class)
-                .build()
-        );
-
-        mock.assertIsSatisfied();
-
-        Exchange exchange = mock.getExchanges().get(0);
-        List<Incident> items = exchange.getIn().getBody(List.class);
-
-        assertNotNull(items);
-        assertFalse(items.isEmpty());
-        assertTrue(items.size() <= 10);
-        assertNotNull(exchange.getIn().getHeader(ServiceNowConstants.RESPONSE_TYPE));
-        assertNotNull(exchange.getIn().getHeader(ServiceNowConstants.OFFSET_FIRST));
-        assertNotNull(exchange.getIn().getHeader(ServiceNowConstants.OFFSET_NEXT));
-        assertNotNull(exchange.getIn().getHeader(ServiceNowConstants.OFFSET_LAST));
-    }
-
-    @Test
-    public void testRetrieveSomeWithDefaults() throws Exception {
-        MockEndpoint mock = getMockEndpoint("mock:servicenow-defaults");
-        mock.expectedMessageCount(1);
-
-        template().sendBodyAndHeaders(
-            "direct:servicenow-defaults",
-            null,
-            kvBuilder()
-                .put(ServiceNowConstants.ACTION, ServiceNowConstants.ACTION_RETRIEVE)
-                .put(ServiceNowParams.SYSPARM_LIMIT, 10)
-                .build()
-        );
-
-        mock.assertIsSatisfied();
-
-        Exchange exchange = mock.getExchanges().get(0);
-        List<Incident> items = exchange.getIn().getBody(List.class);
-
-        assertNotNull(items);
-        assertTrue(items.size() <= 10);
-    }
-
-    @Test
-    public void testIncidentWorkflow() throws Exception {
-
-        Incident incident = null;
-        String sysId;
-        String number;
-        MockEndpoint mock = getMockEndpoint("mock:servicenow");
-
-        // ************************
-        // Create incident
-        // ************************
-
-        {
-            mock.reset();
-            mock.expectedMessageCount(1);
-
-            incident = new Incident();
-            incident.setDescription("my incident");
-            incident.setShortDescription("An incident");
-            incident.setSeverity(1);
-            incident.setImpact(1);
-
-            template().sendBodyAndHeaders(
-                "direct:servicenow",
-                incident,
-                kvBuilder()
-                    .put(ServiceNowConstants.RESOURCE, "table")
-                    .put(ServiceNowConstants.ACTION, ServiceNowConstants.ACTION_CREATE)
-                    .put(ServiceNowParams.PARAM_TABLE_NAME, "incident")
-                    .build()
-            );
-
-            mock.assertIsSatisfied();
-
-            incident = mock.getExchanges().get(0).getIn().getBody(Incident.class);
-            sysId = incident.getId();
-            number = incident.getNumber();
-
-            LOGGER.info("****************************************************");
-            LOGGER.info(" Incident created");
-            LOGGER.info("  sysid  = {}", sysId);
-            LOGGER.info("  number = {}", number);
-            LOGGER.info("****************************************************");
-        }
-
-        // ************************
-        // Search for the incident
-        // ************************
-
-        {
-            LOGGER.info("Search the record {}", sysId);
-
-            mock.reset();
-            mock.expectedMessageCount(1);
-
-            template().sendBodyAndHeaders(
-                "direct:servicenow",
-                null,
-                kvBuilder()
-                    .put(ServiceNowConstants.RESOURCE, "table")
-                    .put(ServiceNowConstants.ACTION, ServiceNowConstants.ACTION_RETRIEVE)
-                    .put(ServiceNowParams.PARAM_TABLE_NAME, "incident")
-                    .put(ServiceNowParams.SYSPARM_QUERY, "number=" + number)
-                    .build()
-            );
-
-            mock.assertIsSatisfied();
-
-            List<Incident> incidents = mock.getExchanges().get(0).getIn().getBody(List.class);
-            assertEquals(1, incidents.size());
-            assertEquals(number, incidents.get(0).getNumber());
-            assertEquals(sysId, incidents.get(0).getId());
-        }
-
-        // ************************
-        // Modify the incident
-        // ************************
-
-        {
-            LOGGER.info("Update the record {}", sysId);
-
-            mock.reset();
-            mock.expectedMessageCount(1);
-
-            incident = new Incident();
-            incident.setDescription("my incident");
-            incident.setShortDescription("The incident");
-            incident.setSeverity(2);
-            incident.setImpact(3);
-
-            template().sendBodyAndHeaders(
-                "direct:servicenow",
-                incident,
-                kvBuilder()
-                    .put(ServiceNowConstants.RESOURCE, "table")
-                    .put(ServiceNowConstants.ACTION, ServiceNowConstants.ACTION_MODIFY)
-                    .put(ServiceNowParams.PARAM_TABLE_NAME, "incident")
-                    .put(ServiceNowParams.PARAM_SYS_ID, sysId)
-                    .build()
-            );
-
-            mock.assertIsSatisfied();
-
-            incident = mock.getExchanges().get(0).getIn().getBody(Incident.class);
-            assertEquals(number, incident.getNumber());
-            assertEquals(2, incident.getSeverity());
-            assertEquals(3, incident.getImpact());
-            assertEquals("The incident", incident.getShortDescription());
-        }
-
-        // ************************
-        // Retrieve it via query
-        // ************************
-
-        {
-            LOGGER.info("Retrieve the record {}", sysId);
-
-            mock.reset();
-            mock.expectedMessageCount(1);
-
-            template().sendBodyAndHeaders(
-                "direct:servicenow",
-                null,
-                kvBuilder()
-                    .put(ServiceNowConstants.RESOURCE, "table")
-                    .put(ServiceNowConstants.ACTION, ServiceNowConstants.ACTION_RETRIEVE)
-                    .put(ServiceNowParams.PARAM_TABLE_NAME, "incident")
-                    .put(ServiceNowParams.SYSPARM_QUERY, "number=" + number)
-                    .build()
-            );
-
-            mock.assertIsSatisfied();
-
-            List<Incident> incidents = mock.getExchanges().get(0).getIn().getBody(List.class);
-            assertEquals(1, incidents.size());
-            assertEquals(number, incidents.get(0).getNumber());
-            assertEquals(sysId, incidents.get(0).getId());
-            assertEquals(2, incidents.get(0).getSeverity());
-            assertEquals(3, incidents.get(0).getImpact());
-            assertEquals("The incident", incidents.get(0).getShortDescription());
-        }
-
-        // ************************
-        // Retrieve by sys id
-        // ************************
-
-        {
-            LOGGER.info("Search the record {}", sysId);
-
-            mock.reset();
-            mock.expectedMessageCount(1);
-
-            template().sendBodyAndHeaders(
-                "direct:servicenow",
-                null,
-                kvBuilder()
-                    .put(ServiceNowConstants.RESOURCE, "table")
-                    .put(ServiceNowConstants.ACTION, ServiceNowConstants.ACTION_RETRIEVE)
-                    .put(ServiceNowParams.PARAM_TABLE_NAME, "incident")
-                    .put(ServiceNowParams.PARAM_SYS_ID, sysId)
-                    .build()
-            );
-
-            mock.assertIsSatisfied();
-
-            incident = mock.getExchanges().get(0).getIn().getBody(Incident.class);
-            assertEquals(2, incident.getSeverity());
-            assertEquals(3, incident.getImpact());
-            assertEquals("The incident", incident.getShortDescription());
-            assertEquals(number, incident.getNumber());
-        }
-
-        // ************************
-        // Delete it
-        // ************************
-
-        {
-            LOGGER.info("Delete the record {}", sysId);
-
-            mock.reset();
-            mock.expectedMessageCount(1);
-
-            template().sendBodyAndHeaders(
-                "direct:servicenow",
-                null,
-                kvBuilder()
-                    .put(ServiceNowConstants.RESOURCE, "table")
-                    .put(ServiceNowConstants.ACTION, ServiceNowConstants.ACTION_DELETE)
-                    .put(ServiceNowParams.PARAM_TABLE_NAME, "incident")
-                    .put(ServiceNowParams.PARAM_SYS_ID, sysId)
-                    .build()
-            );
-
-            mock.assertIsSatisfied();
-        }
-
-        // ************************
-        // Retrieve by id, should fail
-        // ************************
-
-        {
-            LOGGER.info("Find the record {}, should fail", sysId);
-
-            try {
-                template().sendBodyAndHeaders(
-                    "direct:servicenow",
-                    null,
-                    kvBuilder()
-                        .put(ServiceNowConstants.RESOURCE, "table")
-                        .put(ServiceNowConstants.ACTION, ServiceNowConstants.ACTION_RETRIEVE)
-                        .put(ServiceNowParams.PARAM_SYS_ID, sysId)
-                        .put(ServiceNowParams.PARAM_TABLE_NAME, "incident")
-                        .build()
-                );
-
-                fail("Record " + number + " should have been deleted");
-            } catch (CamelExecutionException e) {
-                assertTrue(e.getCause() instanceof ServiceNowException);
-                // we are good
-            }
-        }
-    }
-
-    // *************************************************************************
-    //
-    // *************************************************************************
-
-    @Override
-    protected RouteBuilder createRouteBuilder() throws Exception {
-        return new RouteBuilder() {
-            public void configure() {
-                from("direct:servicenow")
-                    .to("servicenow:{{env:SERVICENOW_INSTANCE}}"
-                        + "?model.incident=org.apache.camel.component.servicenow.model.Incident")
-                    .to("log:org.apache.camel.component.servicenow?level=INFO&showAll=true")
-                    .to("mock:servicenow");
-                from("direct:servicenow-defaults")
-                    .to("servicenow:{{env:SERVICENOW_INSTANCE}}"
-                        + "?model.incident=org.apache.camel.component.servicenow.model.Incident"
-                        + "&resource=table"
-                        + "&table=incident")
-                    .to("log:org.apache.camel.component.servicenow?level=INFO&showAll=true")
-                    .to("mock:servicenow-defaults");
-            }
-        };
-    }
-}

http://git-wip-us.apache.org/repos/asf/camel/blob/109da7c9/components/camel-servicenow/src/test/java/org/apache/camel/component/servicenow/ServiceNowTest.java
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/src/test/java/org/apache/camel/component/servicenow/ServiceNowTest.java b/components/camel-servicenow/src/test/java/org/apache/camel/component/servicenow/ServiceNowTest.java
deleted file mode 100644
index 426a8bfa..0000000
--- a/components/camel-servicenow/src/test/java/org/apache/camel/component/servicenow/ServiceNowTest.java
+++ /dev/null
@@ -1,174 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.camel.component.servicenow;
-
-import java.util.UUID;
-
-import com.fasterxml.jackson.databind.JsonNode;
-import org.apache.camel.CamelExecutionException;
-import org.apache.camel.builder.RouteBuilder;
-import org.apache.camel.component.mock.MockEndpoint;
-import org.apache.camel.component.servicenow.model.Incident;
-import org.junit.Test;
-
-public class ServiceNowTest extends ServiceNowTestSupport {
-
-    @Test
-    public void testExceptions() throws Exception {
-        // 404
-        try {
-            template().sendBodyAndHeaders(
-                "direct:servicenow",
-                null,
-                kvBuilder()
-                    .put(ServiceNowConstants.RESOURCE, "table")
-                    .put(ServiceNowConstants.ACTION, ServiceNowConstants.ACTION_RETRIEVE)
-                    .put(ServiceNowParams.SYSPARM_QUERY, "number=" + UUID.randomUUID().toString())
-                    .put(ServiceNowParams.PARAM_TABLE_NAME, "incident")
-                    .build()
-            );
-        } catch (CamelExecutionException e) {
-            assertTrue(e.getCause() instanceof ServiceNowException);
-
-            ServiceNowException sne = (ServiceNowException)e.getCause();
-            assertEquals("failure", sne.getStatus());
-            assertTrue(sne.getMessage().contains("No Record found"));
-            assertTrue(sne.getDetail().contains("Records matching query not found"));
-        }
-
-        // 400
-        try {
-            template().sendBodyAndHeaders(
-                "direct:servicenow",
-                null,
-                kvBuilder()
-                    .put(ServiceNowConstants.RESOURCE, "table")
-                    .put(ServiceNowConstants.ACTION, ServiceNowConstants.ACTION_RETRIEVE)
-                    .put(ServiceNowParams.SYSPARM_QUERY, "number=" + UUID.randomUUID().toString())
-                    .put(ServiceNowParams.PARAM_TABLE_NAME, "notExistingTable")
-                    .build()
-            );
-        } catch (CamelExecutionException e) {
-            assertTrue(e.getCause() instanceof ServiceNowException);
-
-            ServiceNowException sne = (ServiceNowException)e.getCause();
-            assertEquals("failure", sne.getStatus());
-            assertTrue(sne.getMessage().contains("Invalid table notExistingTable"));
-            assertNull(sne.getDetail());
-        }
-    }
-
-    @Test
-    public void testBodyMismatch() throws Exception {
-        try {
-            template().sendBodyAndHeaders(
-                "direct:servicenow",
-                "NotAnIncidentObject",
-                kvBuilder()
-                    .put(ServiceNowConstants.RESOURCE, "table")
-                    .put(ServiceNowConstants.ACTION, ServiceNowConstants.ACTION_CREATE)
-                    .put(ServiceNowParams.PARAM_TABLE_NAME, "incident")
-                    .build()
-            );
-
-            fail("Should fail as body is not compatible with model defined in route for table incident");
-        } catch (CamelExecutionException e) {
-            assertTrue(e.getCause() instanceof IllegalArgumentException);
-        }
-    }
-
-    @Test
-    public void testRequestResponseModels() throws Exception {
-        MockEndpoint mock = getMockEndpoint("mock:servicenow");
-
-        mock.reset();
-        mock.expectedMessageCount(1);
-
-        Incident incident = new Incident();
-        incident.setDescription("my incident");
-        incident.setShortDescription("An incident");
-        incident.setSeverity(1);
-        incident.setImpact(1);
-
-        template().sendBodyAndHeaders(
-            "direct:servicenow",
-            incident,
-            kvBuilder()
-                .put(ServiceNowConstants.RESOURCE, ServiceNowConstants.RESOURCE_TABLE)
-                .put(ServiceNowConstants.ACTION, ServiceNowConstants.ACTION_CREATE)
-                .put(ServiceNowConstants.REQUEST_MODEL, Incident.class)
-                .put(ServiceNowConstants.RESPONSE_MODEL, JsonNode.class)
-                .put(ServiceNowParams.PARAM_TABLE_NAME, "incident")
-                .build()
-        );
-
-        mock.assertIsSatisfied();
-
-        Object body = mock.getExchanges().get(0).getIn().getBody();
-        assertNotNull(body);
-        assertTrue(body instanceof JsonNode);
-    }
-
-    @Test
-    public void testVersionedApiRequest() throws Exception {
-        MockEndpoint mock = getMockEndpoint("mock:servicenow");
-
-        mock.reset();
-        mock.expectedMessageCount(1);
-
-        Incident incident = new Incident();
-        incident.setDescription("my incident");
-        incident.setShortDescription("An incident");
-        incident.setSeverity(1);
-        incident.setImpact(1);
-
-        template().sendBodyAndHeaders(
-            "direct:servicenow",
-            incident,
-            kvBuilder()
-                .put(ServiceNowConstants.RESOURCE, ServiceNowConstants.RESOURCE_TABLE)
-                .put(ServiceNowConstants.API_VERSION, "v1")
-                .put(ServiceNowConstants.ACTION, ServiceNowConstants.ACTION_CREATE)
-                .put(ServiceNowConstants.REQUEST_MODEL, Incident.class)
-                .put(ServiceNowConstants.RESPONSE_MODEL, JsonNode.class)
-                .put(ServiceNowParams.PARAM_TABLE_NAME, "incident")
-                .build()
-        );
-
-        mock.assertIsSatisfied();
-
-        Object body = mock.getExchanges().get(0).getIn().getBody();
-        assertNotNull(body);
-        assertTrue(body instanceof JsonNode);
-    }
-
-    // *************************************************************************
-    //
-    // *************************************************************************
-
-    @Override
-    protected RouteBuilder createRouteBuilder() throws Exception {
-        return new RouteBuilder() {
-            public void configure() {
-                from("direct:servicenow")
-                    .to("servicenow:{{env:SERVICENOW_INSTANCE}}")
-                    .to("log:org.apache.camel.component.servicenow?level=INFO&showAll=true")
-                    .to("mock:servicenow");
-            }
-        };
-    }
-}

http://git-wip-us.apache.org/repos/asf/camel/blob/109da7c9/components/camel-servicenow/src/test/java/org/apache/camel/component/servicenow/ServiceNowTestSupport.java
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/src/test/java/org/apache/camel/component/servicenow/ServiceNowTestSupport.java b/components/camel-servicenow/src/test/java/org/apache/camel/component/servicenow/ServiceNowTestSupport.java
deleted file mode 100644
index b3cc5c4..0000000
--- a/components/camel-servicenow/src/test/java/org/apache/camel/component/servicenow/ServiceNowTestSupport.java
+++ /dev/null
@@ -1,122 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.camel.component.servicenow;
-
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Map;
-
-import org.apache.camel.CamelContext;
-import org.apache.camel.test.junit4.CamelTestSupport;
-import org.apache.camel.util.ObjectHelper;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-class ServiceNowTestSupport extends CamelTestSupport {
-    protected static final Logger LOGGER = LoggerFactory.getLogger(ServiceNowTestSupport.class);
-
-    private final boolean setUpComponent;
-
-    ServiceNowTestSupport() {
-        this(true);
-    }
-
-    ServiceNowTestSupport(boolean setUpComponent) {
-        this.setUpComponent = setUpComponent;
-    }
-
-    @Override
-    protected CamelContext createCamelContext() throws Exception {
-        CamelContext context = super.createCamelContext();
-        if (setUpComponent) {
-            configureServicenowComponent(context);
-        }
-
-        return context;
-    }
-
-    protected Map<String, Object> getParameters() {
-        HashMap<String, Object> parameters = new HashMap<>();
-        parameters.put("instanceName", getSystemPropertyOrEnvVar("servicenow.instance"));
-        parameters.put("userName", getSystemPropertyOrEnvVar("servicenow.username"));
-        parameters.put("password", getSystemPropertyOrEnvVar("servicenow.password"));
-        parameters.put("oauthClientId", getSystemPropertyOrEnvVar("servicenow.oauth2.client.id"));
-        parameters.put("oauthClientSecret", getSystemPropertyOrEnvVar("servicenow.oauth2.client.secret"));
-
-        return parameters;
-    }
-
-    public void configureServicenowComponent(CamelContext camelContext) throws Exception {
-        String userName = getSystemPropertyOrEnvVar("servicenow.username");
-        String password = getSystemPropertyOrEnvVar("servicenow.password");
-        String oauthClientId = getSystemPropertyOrEnvVar("servicenow.oauth2.client.id");
-        String oauthClientSecret = getSystemPropertyOrEnvVar("servicenow.oauth2.client.secret");
-
-        if (ObjectHelper.isNotEmpty(userName) && ObjectHelper.isNotEmpty(password)) {
-            ServiceNowComponent component = new ServiceNowComponent();
-            component.setUserName(userName);
-            component.setPassword(password);
-
-            if (ObjectHelper.isNotEmpty(oauthClientId) && ObjectHelper.isNotEmpty(oauthClientSecret)) {
-                component.setOauthClientId(oauthClientId);
-                component.setOauthClientSecret(oauthClientSecret);
-            }
-
-            camelContext.addComponent("servicenow", component);
-        }
-    }
-
-    public static String getSystemPropertyOrEnvVar(String systemProperty) {
-        String answer = System.getProperty(systemProperty);
-        if (ObjectHelper.isEmpty(answer)) {
-            String envProperty = systemProperty.toUpperCase().replaceAll("[.-]", "_");
-            answer = System.getenv(envProperty);
-        }
-
-        return answer;
-    }
-
-    protected static KVBuilder kvBuilder() {
-        return new KVBuilder(new HashMap<>());
-    }
-
-    protected static KVBuilder kvBuilder(Map<String, Object> headers) {
-        return new KVBuilder(headers);
-    }
-
-    protected static final class KVBuilder {
-        private final Map<String, Object> headers;
-
-        private KVBuilder(Map<String, Object> headers) {
-            this.headers = new HashMap<>(headers);
-        }
-
-        public KVBuilder put(String key, Object val) {
-            headers.put(key, val);
-            return this;
-        }
-
-        public KVBuilder put(ServiceNowParam key, Object val) {
-            headers.put(key.getHeader(), val);
-            return this;
-        }
-
-        public Map<String, Object> build() {
-            return Collections.unmodifiableMap(this.headers);
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/camel/blob/109da7c9/components/camel-servicenow/src/test/java/org/apache/camel/component/servicenow/model/AttachmentMeta.java
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/src/test/java/org/apache/camel/component/servicenow/model/AttachmentMeta.java b/components/camel-servicenow/src/test/java/org/apache/camel/component/servicenow/model/AttachmentMeta.java
deleted file mode 100644
index 21fbb38..0000000
--- a/components/camel-servicenow/src/test/java/org/apache/camel/component/servicenow/model/AttachmentMeta.java
+++ /dev/null
@@ -1,92 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.camel.component.servicenow.model;
-
-import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
-import com.fasterxml.jackson.annotation.JsonInclude;
-import com.fasterxml.jackson.annotation.JsonProperty;
-
-@JsonIgnoreProperties(ignoreUnknown = true)
-@JsonInclude(JsonInclude.Include.NON_NULL)
-public class AttachmentMeta {
-    @JsonProperty("sys_id")
-    private String id;
-
-    @JsonProperty("download_link")
-    private String downloadLink;
-
-    @JsonProperty("table_name")
-    private String tableName;
-
-    @JsonProperty("table_sys_id")
-    private String tableSysId;
-
-    @JsonProperty("compressed")
-    private Boolean compressed;
-
-    @JsonProperty("file_name")
-    private String fileName;
-
-    public String getId() {
-        return id;
-    }
-
-    public void setId(String id) {
-        this.id = id;
-    }
-
-    public String getDownloadLink() {
-        return downloadLink;
-    }
-
-    public void setDownloadLink(String downloadLink) {
-        this.downloadLink = downloadLink;
-    }
-
-    public String getTableName() {
-        return tableName;
-    }
-
-    public void setTableName(String tableName) {
-        this.tableName = tableName;
-    }
-
-    public String getTableSysId() {
-        return tableSysId;
-    }
-
-    public void setTableSysId(String tableSysId) {
-        this.tableSysId = tableSysId;
-    }
-
-    public Boolean getCompressed() {
-        return compressed;
-    }
-
-    public void setCompressed(Boolean compressed) {
-        this.compressed = compressed;
-    }
-
-    public String getFileName() {
-        return fileName;
-    }
-
-    public void setFileName(String fileName) {
-        this.fileName = fileName;
-    }
-}

http://git-wip-us.apache.org/repos/asf/camel/blob/109da7c9/components/camel-servicenow/src/test/java/org/apache/camel/component/servicenow/model/Incident.java
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/src/test/java/org/apache/camel/component/servicenow/model/Incident.java b/components/camel-servicenow/src/test/java/org/apache/camel/component/servicenow/model/Incident.java
deleted file mode 100644
index c909413..0000000
--- a/components/camel-servicenow/src/test/java/org/apache/camel/component/servicenow/model/Incident.java
+++ /dev/null
@@ -1,97 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.camel.component.servicenow.model;
-
-import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
-import com.fasterxml.jackson.annotation.JsonInclude;
-import com.fasterxml.jackson.annotation.JsonProperty;
-
-@JsonIgnoreProperties(ignoreUnknown = true)
-@JsonInclude(JsonInclude.Include.NON_NULL)
-public class Incident {
-    @JsonProperty("sys_id")
-    private String id;
-
-    @JsonProperty("number")
-    private String number;
-
-    @JsonProperty("description")
-    private String description;
-
-    @JsonProperty("short_description")
-    private String shortDescription;
-
-    @JsonProperty("severity")
-    private int severity;
-
-    @JsonProperty("impact")
-    private int impact;
-
-
-    public Incident() {
-    }
-
-
-    public String getId() {
-        return id;
-    }
-
-    public void setId(String id) {
-        this.id = id;
-    }
-
-    public String getNumber() {
-        return number;
-    }
-
-    public void setNumber(String number) {
-        this.number = number;
-    }
-
-    public String getDescription() {
-        return description;
-    }
-
-    public void setDescription(String description) {
-        this.description = description;
-    }
-
-    public String getShortDescription() {
-        return shortDescription;
-    }
-
-    public void setShortDescription(String shortDescription) {
-        this.shortDescription = shortDescription;
-    }
-
-    public int getSeverity() {
-        return severity;
-    }
-
-    public void setSeverity(int severity) {
-        this.severity = severity;
-    }
-
-    public int getImpact() {
-        return impact;
-    }
-
-    public void setImpact(int impact) {
-        this.impact = impact;
-    }
-}

http://git-wip-us.apache.org/repos/asf/camel/blob/109da7c9/components/camel-servicenow/src/test/java/org/apache/camel/component/servicenow/model/IncidentWithParms.java
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/src/test/java/org/apache/camel/component/servicenow/model/IncidentWithParms.java b/components/camel-servicenow/src/test/java/org/apache/camel/component/servicenow/model/IncidentWithParms.java
deleted file mode 100644
index 03ff9ff..0000000
--- a/components/camel-servicenow/src/test/java/org/apache/camel/component/servicenow/model/IncidentWithParms.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.camel.component.servicenow.model;
-
-import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
-import com.fasterxml.jackson.annotation.JsonInclude;
-import com.fasterxml.jackson.annotation.JsonProperty;
-import org.apache.camel.component.servicenow.annotations.ServiceNowSysParm;
-
-@ServiceNowSysParm(name = "sysparm_exclude_reference_link", value = "true")
-@ServiceNowSysParm(name = "sysparm_fields", value = "id%2Cnumber%2Ccaller_id")
-@JsonIgnoreProperties(ignoreUnknown = true)
-@JsonInclude(JsonInclude.Include.NON_NULL)
-public class IncidentWithParms {
-    @JsonProperty("sys_id")
-    private String id;
-    @JsonProperty("number")
-    private String number;
-    @JsonProperty("caller_id")
-    private String callerId;
-
-    public IncidentWithParms() {
-    }
-
-
-    public String getId() {
-        return id;
-    }
-
-    public void setId(String id) {
-        this.id = id;
-    }
-
-    public String getNumber() {
-        return number;
-    }
-
-    public void setNumber(String number) {
-        this.number = number;
-    }
-
-    public String getCallerId() {
-        return callerId;
-    }
-
-    public void setCallerId(String callerId) {
-        this.callerId = callerId;
-    }
-}

http://git-wip-us.apache.org/repos/asf/camel/blob/109da7c9/components/camel-servicenow/src/test/java/org/apache/camel/component/servicenow/model/Scorecard.java
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/src/test/java/org/apache/camel/component/servicenow/model/Scorecard.java b/components/camel-servicenow/src/test/java/org/apache/camel/component/servicenow/model/Scorecard.java
deleted file mode 100644
index dabb23e..0000000
--- a/components/camel-servicenow/src/test/java/org/apache/camel/component/servicenow/model/Scorecard.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.camel.component.servicenow.model;
-
-import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
-import com.fasterxml.jackson.annotation.JsonInclude;
-import com.fasterxml.jackson.annotation.JsonProperty;
-
-@JsonIgnoreProperties(ignoreUnknown = true)
-@JsonInclude(JsonInclude.Include.NON_NULL)
-public class Scorecard {
-    @JsonProperty("name")
-    private String name;
-    @JsonProperty("description")
-    private String description;
-
-    public String getName() {
-        return name;
-    }
-
-    public void setName(String name) {
-        this.name = name;
-    }
-
-    public String getDescription() {
-        return description;
-    }
-
-    public void setDescription(String description) {
-        this.description = description;
-    }
-}

http://git-wip-us.apache.org/repos/asf/camel/blob/109da7c9/components/camel-servicenow/src/test/resources/OSGI-INF/blueprint/blueprint-component-auth.xml
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/src/test/resources/OSGI-INF/blueprint/blueprint-component-auth.xml b/components/camel-servicenow/src/test/resources/OSGI-INF/blueprint/blueprint-component-auth.xml
deleted file mode 100644
index 14c4c1f..0000000
--- a/components/camel-servicenow/src/test/resources/OSGI-INF/blueprint/blueprint-component-auth.xml
+++ /dev/null
@@ -1,55 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-
-    Licensed to the Apache Software Foundation (ASF) under one or more
-    contributor license agreements.  See the NOTICE file distributed with
-    this work for additional information regarding copyright ownership.
-    The ASF licenses this file to You under the Apache License, Version 2.0
-    (the "License"); you may not use this file except in compliance with
-    the License.  You may obtain a copy of the License at
-
-         http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
-
--->
-<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
-           xmlns:ext="http://aries.apache.org/blueprint/xmlns/blueprint-ext/v1.0.0">
-
-  <ext:property-placeholder placeholder-prefix="$[" placeholder-suffix="]"/>
-
-  <bean id="servicenow" class="org.apache.camel.component.servicenow.ServiceNowComponent">
-    <property name="userName" value="$[servicenow.username]"/>
-    <property name="password" value="$[servicenow.password]"/>
-  </bean>
-
-  <camelContext xmlns="http://camel.apache.org/schema/blueprint">
-    <route>
-      <from uri="direct:servicenow"/>
-      <multicast>
-        <to uri="direct:route-1"/>
-        <to uri="direct:route-2"/>
-      </multicast>
-    </route>
-
-    <route>
-      <from uri="direct:route-1"/>
-      <to uri="servicenow:{{sys:servicenow.instance}}?excludeReferenceLink=true"/>
-      <to uri="log:org.apache.camel.component.servicenow-1?level=INFO"/>
-      <to uri="mock:servicenow-1"/>
-    </route>
-
-    <route>
-      <from uri="direct:route-2"/>
-      <to uri="servicenow:{{sys:servicenow.instance}}?excludeReferenceLink=false"/>
-      <to uri="log:org.apache.camel.component.servicenow-2?level=INFO"/>
-      <to uri="mock:servicenow-2"/>
-    </route>
-
-  </camelContext>
-
-</blueprint>

http://git-wip-us.apache.org/repos/asf/camel/blob/109da7c9/components/camel-servicenow/src/test/resources/OSGI-INF/blueprint/blueprint-endpoint-auth.xml
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/src/test/resources/OSGI-INF/blueprint/blueprint-endpoint-auth.xml b/components/camel-servicenow/src/test/resources/OSGI-INF/blueprint/blueprint-endpoint-auth.xml
deleted file mode 100644
index f0d1f8b..0000000
--- a/components/camel-servicenow/src/test/resources/OSGI-INF/blueprint/blueprint-endpoint-auth.xml
+++ /dev/null
@@ -1,37 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-
-    Licensed to the Apache Software Foundation (ASF) under one or more
-    contributor license agreements.  See the NOTICE file distributed with
-    this work for additional information regarding copyright ownership.
-    The ASF licenses this file to You under the Apache License, Version 2.0
-    (the "License"); you may not use this file except in compliance with
-    the License.  You may obtain a copy of the License at
-
-         http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
-
--->
-<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
-           xmlns:ext="http://aries.apache.org/blueprint/xmlns/blueprint-ext/v1.0.0">
-
-  <ext:property-placeholder placeholder-prefix="$[" placeholder-suffix="]"/>
-
-  <bean id="servicenow" class="org.apache.camel.component.servicenow.ServiceNowComponent">
-  </bean>
-
-  <camelContext xmlns="http://camel.apache.org/schema/blueprint">
-    <route>
-      <from uri="direct:servicenow"/>
-        <to uri="servicenow:{{sys:servicenow.instance}}?userName={{sys:servicenow.username}}&amp;password={{sys:servicenow.password}}"/>
-        <to uri="log:org.apache.camel.component.servicenow?level=INFO"/>
-        <to uri="mock:servicenow"/>
-    </route>
-  </camelContext>
-
-</blueprint>

http://git-wip-us.apache.org/repos/asf/camel/blob/109da7c9/components/camel-servicenow/src/test/resources/log4j2.properties
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/src/test/resources/log4j2.properties b/components/camel-servicenow/src/test/resources/log4j2.properties
deleted file mode 100644
index edd6b44..0000000
--- a/components/camel-servicenow/src/test/resources/log4j2.properties
+++ /dev/null
@@ -1,43 +0,0 @@
-## ---------------------------------------------------------------------------
-## Licensed to the Apache Software Foundation (ASF) under one or more
-## contributor license agreements.  See the NOTICE file distributed with
-## this work for additional information regarding copyright ownership.
-## The ASF licenses this file to You under the Apache License, Version 2.0
-## (the "License"); you may not use this file except in compliance with
-## the License.  You may obtain a copy of the License at
-##
-##      http://www.apache.org/licenses/LICENSE-2.0
-##
-## Unless required by applicable law or agreed to in writing, software
-## distributed under the License is distributed on an "AS IS" BASIS,
-## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-## See the License for the specific language governing permissions and
-## limitations under the License.
-## ---------------------------------------------------------------------------
-
-appender.file.type = File
-appender.file.name = file
-appender.file.fileName = target/camel-servicenow-test.log
-appender.file.layout.type = PatternLayout
-appender.file.layout.pattern = %d %-5p %c{1} - %m %n
-
-appender.out.type = Console
-appender.out.name = out
-appender.out.layout.type = PatternLayout
-appender.out.layout.pattern = %d{HH:mm:ss.SSS} [%-15.15t] %-30.30c{1} %-5p %m%n
-
-logger.servicenow.name = org.apache.camel.component.servicenow
-logger.servicenow.level = DEBUG
-
-#logger.metadata.name = org.apache.camel.component.servicenow.ServiceNowMetaDataExtensionTest
-#logger.metadata.level = DEBUG
-#logger.metadata.additivity = true
-#logger.metadata.appenderRef.metadata.ref = out
-
-#logger.metadata-ext.name = org.apache.camel.component.servicenow.ServiceNowMetaDataExtension
-#logger.metadata-ext.level = DEBUG
-#logger.metadata-ext.additivity = true
-#logger.metadata-ext.appenderRef.metadata-ext.ref = out
-
-rootLogger.level = INFO
-rootLogger.appenderRef.root.ref = file

http://git-wip-us.apache.org/repos/asf/camel/blob/109da7c9/components/camel-servicenow/src/test/resources/my-content.txt
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/src/test/resources/my-content.txt b/components/camel-servicenow/src/test/resources/my-content.txt
deleted file mode 100644
index 63b8767..0000000
--- a/components/camel-servicenow/src/test/resources/my-content.txt
+++ /dev/null
@@ -1,16 +0,0 @@
-## ---------------------------------------------------------------------------
-## Licensed to the Apache Software Foundation (ASF) under one or more
-## contributor license agreements.  See the NOTICE file distributed with
-## this work for additional information regarding copyright ownership.
-## The ASF licenses this file to You under the Apache License, Version 2.0
-## (the "License"); you may not use this file except in compliance with
-## the License.  You may obtain a copy of the License at
-##
-## http://www.apache.org/licenses/LICENSE-2.0
-##
-## Unless required by applicable law or agreed to in writing, software
-## distributed under the License is distributed on an "AS IS" BASIS,
-## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-## See the License for the specific language governing permissions and
-## limitations under the License.
-## ---------------------------------------------------------------------------
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/camel/blob/109da7c9/parent/pom.xml
----------------------------------------------------------------------
diff --git a/parent/pom.xml b/parent/pom.xml
index a919a5d..f978d4d 100644
--- a/parent/pom.xml
+++ b/parent/pom.xml
@@ -160,6 +160,7 @@
     <commons-net-version>3.6</commons-net-version>
     <commons-pool-version>1.6</commons-pool-version>
     <commons-pool2-version>2.4.2</commons-pool2-version>
+    <commons-text-version>1.1</commons-text-version>
     <commons-vfs2-version>2.0</commons-vfs2-version>
     <compress-lzf-version>1.0.4</compress-lzf-version>
     <consul-client-version>0.16.2</consul-client-version>
@@ -468,6 +469,8 @@
     <maven-jboss-as-maven-plugin-version>7.7.Final</maven-jboss-as-maven-plugin-version>
     <!-- plugin-plugin 3.5 does not work -->
     <maven-plugin-plugin-version>3.4</maven-plugin-plugin-version>
+    <maven-plugin-annotations-version>3.5</maven-plugin-annotations-version>
+    <maven-plugin-testing-harness-version>3.3.0</maven-plugin-testing-harness-version>
     <maven-remote-resources-plugin-version>1.5</maven-remote-resources-plugin-version>
     <!-- resources plugin needed by Camel maven archetypes -->
     <maven-resources-plugin-version>3.0.2</maven-resources-plugin-version>

http://git-wip-us.apache.org/repos/asf/camel/blob/109da7c9/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/PrepareCatalogKarafMojo.java
----------------------------------------------------------------------
diff --git a/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/PrepareCatalogKarafMojo.java b/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/PrepareCatalogKarafMojo.java
index b4235e9..7aeaa714 100644
--- a/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/PrepareCatalogKarafMojo.java
+++ b/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/PrepareCatalogKarafMojo.java
@@ -160,6 +160,8 @@ public class PrepareCatalogKarafMojo extends AbstractMojo {
                             target = new File(dir, "camel-salesforce-component/target/classes");
                         } else if ("camel-linkedin".equals(dir.getName())) {
                             target = new File(dir, "camel-linkedin-component/target/classes");
+                        } else if ("camel-servicenow".equals(dir.getName())) {
+                            target = new File(dir, "camel-servicenow-component/target/classes");
                         }
 
                         findComponentFilesRecursive(target, jsonFiles, componentFiles, new CamelComponentsFileFilter());
@@ -387,6 +389,7 @@ public class PrepareCatalogKarafMojo extends AbstractMojo {
                     boolean special2 = "camel-linkedin".equals(dir.getName())
                         || "camel-olingo2".equals(dir.getName())
                         || "camel-olingo4".equals(dir.getName())
+                        || "camel-servicenow".equals(dir.getName())
                         || "camel-salesforce".equals(dir.getName());
                     if (special || special2) {
                         continue;
@@ -658,4 +661,4 @@ public class PrepareCatalogKarafMojo extends AbstractMojo {
         return answer;
     }
 
-}
\ No newline at end of file
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/109da7c9/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/PrepareCatalogMojo.java
----------------------------------------------------------------------
diff --git a/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/PrepareCatalogMojo.java b/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/PrepareCatalogMojo.java
index 4f6c09b..9154da5 100644
--- a/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/PrepareCatalogMojo.java
+++ b/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/PrepareCatalogMojo.java
@@ -353,6 +353,8 @@ public class PrepareCatalogMojo extends AbstractMojo {
                             target = new File(dir, "camel-olingo4-component/target/classes");
                         } else if ("camel-box".equals(dir.getName())) {
                             target = new File(dir, "camel-box-component/target/classes");
+                        } else if ("camel-servicenow".equals(dir.getName())) {
+                            target = new File(dir, "camel-servicenow-component/target/classes");
                         }
 
                         int before = componentFiles.size();
@@ -795,6 +797,7 @@ public class PrepareCatalogMojo extends AbstractMojo {
                     boolean special2 = "camel-linkedin".equals(dir.getName())
                         || "camel-olingo2".equals(dir.getName())
                         || "camel-olingo4".equals(dir.getName())
+                        || "camel-servicenow".equals(dir.getName())
                         || "camel-salesforce".equals(dir.getName());
                     if (special || special2) {
                         continue;
@@ -971,6 +974,8 @@ public class PrepareCatalogMojo extends AbstractMojo {
                             target = new File(dir, "camel-olingo4-component/src/main/docs");
                         } else if ("camel-box".equals(dir.getName())) {
                             target = new File(dir, "camel-box-component/src/main/docs");
+                        } else if ("camel-servicenow".equals(dir.getName())) {
+                            target = new File(dir, "camel-servicenow-component/src/main/docs");
                         }
 
                         int before = adocFiles.size();
@@ -1096,7 +1101,7 @@ public class PrepareCatalogMojo extends AbstractMojo {
                 component = "ftp";
             } 
             String name = component + "-component";
-            if (!docs.contains(name) && (!component.equalsIgnoreCase("linkedin") && !component.equalsIgnoreCase("salesforce"))) {
+            if (!docs.contains(name) && (!component.equalsIgnoreCase("linkedin") && !component.equalsIgnoreCase("salesforce") && !component.equalsIgnoreCase("servicenow"))) {
                 missing.add(name);
             }
         }
@@ -1624,4 +1629,4 @@ public class PrepareCatalogMojo extends AbstractMojo {
         return false;
     }
 
-}
\ No newline at end of file
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/109da7c9/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/PrepareCatalogSpringBootMojo.java
----------------------------------------------------------------------
diff --git a/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/PrepareCatalogSpringBootMojo.java b/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/PrepareCatalogSpringBootMojo.java
index 6618520..4557e4d 100644
--- a/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/PrepareCatalogSpringBootMojo.java
+++ b/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/PrepareCatalogSpringBootMojo.java
@@ -155,6 +155,8 @@ public class PrepareCatalogSpringBootMojo extends AbstractMojo {
                             target = new File(dir, "camel-salesforce-component/target/classes");
                         } else if ("camel-linkedin".equals(dir.getName())) {
                             target = new File(dir, "camel-linkedin-component/target/classes");
+                        } else if ("camel-servicenow".equals(dir.getName())) {
+                            target = new File(dir, "camel-servicenow-component/target/classes");
                         }
 
 
@@ -414,6 +416,7 @@ public class PrepareCatalogSpringBootMojo extends AbstractMojo {
                     boolean special2 = "camel-linkedin".equals(dir.getName())
                         || "camel-olingo2".equals(dir.getName())
                         || "camel-olingo4".equals(dir.getName())
+                        || "camel-servicenow".equals(dir.getName())
                         || "camel-salesforce".equals(dir.getName());
                     if (special || special2) {
                         continue;

http://git-wip-us.apache.org/repos/asf/camel/blob/109da7c9/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/model/ComponentModel.java
----------------------------------------------------------------------
diff --git a/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/model/ComponentModel.java b/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/model/ComponentModel.java
index e067516..65fd4aa 100644
--- a/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/model/ComponentModel.java
+++ b/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/model/ComponentModel.java
@@ -238,6 +238,8 @@ public class ComponentModel {
             return "camel-olingo4/camel-olingo4-component/src/main/docs";
         } else if ("camel-salesforce".equals(artifactId)) {
             return "camel-salesforce/camel-salesforce-component/src/main/docs";
+        } else if ("camel-servicenow".equals(artifactId)) {
+            return "camel-servicenow/camel-servicenow-component/src/main/docs";
         }
 
         if ("camel-core".equals(artifactId)) {


[11/19] camel git commit: CAMEL-11555: ServiceNow : create a maven plugin to generate models based on table layout

Posted by lb...@apache.org.
http://git-wip-us.apache.org/repos/asf/camel/blob/109da7c9/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/releases/helsinki/HelsinkiServiceNowServiceCatalogProcessor.java
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/releases/helsinki/HelsinkiServiceNowServiceCatalogProcessor.java b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/releases/helsinki/HelsinkiServiceNowServiceCatalogProcessor.java
deleted file mode 100644
index 42b5da3..0000000
--- a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/releases/helsinki/HelsinkiServiceNowServiceCatalogProcessor.java
+++ /dev/null
@@ -1,118 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.camel.component.servicenow.releases.helsinki;
-
-import javax.ws.rs.HttpMethod;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.Response;
-
-import org.apache.camel.Exchange;
-import org.apache.camel.Message;
-import org.apache.camel.component.servicenow.AbstractServiceNowProcessor;
-import org.apache.camel.component.servicenow.ServiceNowEndpoint;
-import org.apache.camel.component.servicenow.ServiceNowParams;
-import org.apache.camel.util.ObjectHelper;
-
-import static org.apache.camel.component.servicenow.ServiceNowConstants.ACTION_RETRIEVE;
-import static org.apache.camel.component.servicenow.ServiceNowConstants.ACTION_SUBJECT_CATEGORIES;
-
-class HelsinkiServiceNowServiceCatalogProcessor extends AbstractServiceNowProcessor {
-
-    HelsinkiServiceNowServiceCatalogProcessor(ServiceNowEndpoint endpoint) throws Exception {
-        super(endpoint);
-
-        addDispatcher(ACTION_RETRIEVE, ACTION_SUBJECT_CATEGORIES, this::retrieveCatalogsCategories);
-        addDispatcher(ACTION_RETRIEVE, this::retrieveCatalogs);
-    }
-
-    /*
-     * This method retrieves a list of catalogs to which the user has access or
-     * a single one if sys_id is defined.
-     *
-     * Method:
-     * - GET
-     *
-     * URL Format:
-     * - /sn_sc/servicecatalog/catalogs
-     * - /sn_sc/servicecatalog/catalogs/{sys_id}
-     */
-    private void retrieveCatalogs(Exchange exchange) throws Exception {
-        final Message in = exchange.getIn();
-        final Class<?> responseModel = getResponseModel(in);
-        final String sysId = getSysID(in);
-        final String apiVersion = getApiVersion(in);
-
-        Response response = ObjectHelper.isEmpty(sysId)
-            ? client.reset()
-                .types(MediaType.APPLICATION_JSON_TYPE)
-                .path("sn_sc")
-                .path(apiVersion)
-                .path("servicecatalog")
-                .path("catalogs")
-                .query(ServiceNowParams.SYSPARM_LIMIT, in)
-                .query(ServiceNowParams.SYSPARM_QUERY, in)
-                .query(ServiceNowParams.SYSPARM_VIEW, in)
-                .query(responseModel)
-                .invoke(HttpMethod.GET)
-            : client.reset()
-                .types(MediaType.APPLICATION_JSON_TYPE)
-                .path("sn_sc")
-                .path(apiVersion)
-                .path("servicecatalog")
-                .path("catalogs")
-                .path(sysId)
-                .query(ServiceNowParams.SYSPARM_VIEW, in)
-                .query(responseModel)
-                .invoke(HttpMethod.GET);
-
-        setBodyAndHeaders(in, responseModel, response);
-    }
-
-    /*
-     * This method retrieves a list of categories for a catalog.
-     *
-     * Method:
-     * - GET
-     *
-     * URL Format:
-     * - /sn_sc/servicecatalog/catalogs/{sys_id}/categories
-     */
-    private void retrieveCatalogsCategories(Exchange exchange) throws Exception {
-        final Message in = exchange.getIn();
-        final Class<?> responseModel = getResponseModel(in);
-        final String sysId = getSysID(in);
-        final String apiVersion = getApiVersion(in);
-
-        Response response = client.reset()
-            .types(MediaType.APPLICATION_JSON_TYPE)
-            .path("sn_sc")
-            .path(apiVersion)
-            .path("servicecatalog")
-            .path("catalogs")
-            .path(ObjectHelper.notNull(sysId, "sysId"))
-            .path("categories")
-            .query(ServiceNowParams.SYSPARM_TOP_LEVEL_ONLY, in)
-            .query(ServiceNowParams.SYSPARM_LIMIT, in)
-            .query(ServiceNowParams.SYSPARM_VIEW, in)
-            .query(ServiceNowParams.SYSPARM_OFFSET, in)
-            .query(responseModel)
-            .invoke(HttpMethod.GET);
-
-        setBodyAndHeaders(in, responseModel, response);
-    }
-}

http://git-wip-us.apache.org/repos/asf/camel/blob/109da7c9/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/releases/helsinki/HelsinkiServiceNowTableProcessor.java
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/releases/helsinki/HelsinkiServiceNowTableProcessor.java b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/releases/helsinki/HelsinkiServiceNowTableProcessor.java
deleted file mode 100644
index 8e62408..0000000
--- a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/releases/helsinki/HelsinkiServiceNowTableProcessor.java
+++ /dev/null
@@ -1,214 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.camel.component.servicenow.releases.helsinki;
-
-import javax.ws.rs.HttpMethod;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.Response;
-
-import org.apache.camel.Exchange;
-import org.apache.camel.Message;
-import org.apache.camel.component.servicenow.AbstractServiceNowProcessor;
-import org.apache.camel.component.servicenow.ServiceNowEndpoint;
-import org.apache.camel.component.servicenow.ServiceNowParams;
-import org.apache.camel.util.ObjectHelper;
-
-import static org.apache.camel.component.servicenow.ServiceNowConstants.ACTION_CREATE;
-import static org.apache.camel.component.servicenow.ServiceNowConstants.ACTION_DELETE;
-import static org.apache.camel.component.servicenow.ServiceNowConstants.ACTION_MODIFY;
-import static org.apache.camel.component.servicenow.ServiceNowConstants.ACTION_RETRIEVE;
-import static org.apache.camel.component.servicenow.ServiceNowConstants.ACTION_UPDATE;
-
-class HelsinkiServiceNowTableProcessor extends AbstractServiceNowProcessor {
-    HelsinkiServiceNowTableProcessor(ServiceNowEndpoint endpoint) throws Exception {
-        super(endpoint);
-
-        addDispatcher(ACTION_RETRIEVE, this::retrieveRecord);
-        addDispatcher(ACTION_CREATE, this::createRecord);
-        addDispatcher(ACTION_MODIFY, this::modifyRecord);
-        addDispatcher(ACTION_DELETE, this::deleteRecord);
-        addDispatcher(ACTION_UPDATE, this::updateRecord);
-    }
-
-    /*
-     * GET
-     * https://instance.service-now.com/api/now/table/{tableName}
-     * https://instance.service-now.com/api/now/table/{tableName}/{sys_id}
-     */
-    private void retrieveRecord(Exchange exchange) throws Exception {
-        final Message in = exchange.getIn();
-        final String tableName = getTableName(in);
-        final String apiVersion = getApiVersion(in);
-        final Class<?> responseModel = getResponseModel(in, tableName);
-        final String sysId = getSysID(in);
-
-        Response response = ObjectHelper.isEmpty(sysId)
-            ? client.reset()
-                .types(MediaType.APPLICATION_JSON_TYPE)
-                .path("now")
-                .path(apiVersion)
-                .path("table")
-                .path(tableName)
-                .query(ServiceNowParams.SYSPARM_QUERY, in)
-                .query(ServiceNowParams.SYSPARM_DISPLAY_VALUE, in)
-                .query(ServiceNowParams.SYSPARM_EXCLUDE_REFERENCE_LINK, in)
-                .query(ServiceNowParams.SYSPARM_SUPPRESS_PAGINATION_HEADER, in)
-                .query(ServiceNowParams.SYSPARM_FIELDS, in)
-                .query(ServiceNowParams.SYSPARM_LIMIT, in)
-                .query(ServiceNowParams.SYSPARM_OFFSET, in)
-                .query(ServiceNowParams.SYSPARM_VIEW, in)
-                .query(responseModel)
-                .invoke(HttpMethod.GET)
-            : client.reset()
-                .types(MediaType.APPLICATION_JSON_TYPE)
-                .path("now")
-                .path(apiVersion)
-                .path("table")
-                .path(tableName)
-                .path(sysId)
-                .query(ServiceNowParams.SYSPARM_DISPLAY_VALUE, in)
-                .query(ServiceNowParams.SYSPARM_EXCLUDE_REFERENCE_LINK, in)
-                .query(ServiceNowParams.SYSPARM_FIELDS, in)
-                .query(ServiceNowParams.SYSPARM_VIEW, in)
-                .query(responseModel)
-                .invoke(HttpMethod.GET);
-
-        setBodyAndHeaders(exchange.getIn(), responseModel, response);
-    }
-
-    /*
-     * POST
-     * https://instance.service-now.com/api/now/table/{tableName}
-     */
-    private void createRecord(Exchange exchange) throws Exception {
-        final Message in = exchange.getIn();
-        final String tableName = getTableName(in);
-        final String apiVersion = getApiVersion(in);
-        final Class<?> requestModel = getRequestModel(in, tableName);
-        final Class<?> responseModel = getResponseModel(in, tableName);
-        final String sysId = getSysID(in);
-
-        validateBody(in, requestModel);
-
-        Response response = client.reset()
-            .types(MediaType.APPLICATION_JSON_TYPE)
-            .path("now")
-            .path(apiVersion)
-            .path("table")
-            .path(tableName)
-            .query(ServiceNowParams.SYSPARM_DISPLAY_VALUE, in)
-            .query(ServiceNowParams.SYSPARM_EXCLUDE_REFERENCE_LINK, in)
-            .query(ServiceNowParams.SYSPARM_FIELDS, in)
-            .query(ServiceNowParams.SYSPARM_INPUT_DISPLAY_VALUE, in)
-            .query(ServiceNowParams.SYSPARM_SUPPRESS_AUTO_SYS_FIELD, in)
-            .query(ServiceNowParams.SYSPARM_VIEW, in)
-            .query(responseModel)
-            .invoke(HttpMethod.POST, in.getMandatoryBody());
-
-        setBodyAndHeaders(exchange.getIn(), responseModel, response);
-    }
-
-    /*
-     * PUT
-     * https://instance.service-now.com/api/now/table/{tableName}/{sys_id}
-     */
-    private void modifyRecord(Exchange exchange) throws Exception {
-        final Message in = exchange.getIn();
-        final String tableName = getTableName(in);
-        final String apiVersion = getApiVersion(in);
-        final Class<?> requestModel = getRequestModel(in, tableName);
-        final Class<?> responseModel = getResponseModel(in, tableName);
-        final String sysId = getSysID(in);
-
-        validateBody(in, requestModel);
-
-        Response response = client.reset()
-            .types(MediaType.APPLICATION_JSON_TYPE)
-            .path("now")
-            .path(apiVersion)
-            .path("table")
-            .path(tableName)
-            .path(ObjectHelper.notNull(sysId, "sysId"))
-            .query(ServiceNowParams.SYSPARM_DISPLAY_VALUE, in)
-            .query(ServiceNowParams.SYSPARM_EXCLUDE_REFERENCE_LINK, in)
-            .query(ServiceNowParams.SYSPARM_FIELDS, in)
-            .query(ServiceNowParams.SYSPARM_INPUT_DISPLAY_VALUE, in)
-            .query(ServiceNowParams.SYSPARM_SUPPRESS_AUTO_SYS_FIELD, in)
-            .query(ServiceNowParams.SYSPARM_VIEW, in)
-            .query(responseModel)
-            .invoke(HttpMethod.PUT, in.getMandatoryBody());
-
-        setBodyAndHeaders(exchange.getIn(), responseModel, response);
-    }
-
-    /*
-     * DELETE
-     * https://instance.service-now.com/api/now/table/{tableName}/{sys_id}
-     */
-    private void deleteRecord(Exchange exchange) throws Exception {
-        final Message in = exchange.getIn();
-        final String tableName = getTableName(in);
-        final String apiVersion = getApiVersion(in);
-        final Class<?> responseModel = getResponseModel(in, tableName);
-        final String sysId = getSysID(in);
-
-        Response response = client.reset()
-            .types(MediaType.APPLICATION_JSON_TYPE)
-            .path("now")
-            .path(apiVersion)
-            .path("table")
-            .path(tableName)
-            .path(ObjectHelper.notNull(sysId, "sysId"))
-            .query(responseModel)
-            .invoke(HttpMethod.DELETE, null);
-
-        setBodyAndHeaders(exchange.getIn(), responseModel, response);
-    }
-
-    /*
-     * PATCH
-     * instance://instance.service-now.com/api/now/table/{tableName}/{sys_id}
-     */
-    private void updateRecord(Exchange exchange) throws Exception {
-        final Message in = exchange.getIn();
-        final String tableName = getTableName(in);
-        final String apiVersion = getApiVersion(in);
-        final Class<?> requestModel = getRequestModel(in, tableName);
-        final Class<?> responseModel = getResponseModel(in, tableName);
-        final String sysId = getSysID(in);
-
-        validateBody(in, requestModel);
-
-        Response response = client.reset()
-            .types(MediaType.APPLICATION_JSON_TYPE)
-            .path("now")
-            .path(apiVersion)
-            .path("table")
-            .path(tableName)
-            .path(ObjectHelper.notNull(sysId, "sysId"))
-            .query(ServiceNowParams.SYSPARM_DISPLAY_VALUE, in)
-            .query(ServiceNowParams.SYSPARM_EXCLUDE_REFERENCE_LINK, in)
-            .query(ServiceNowParams.SYSPARM_FIELDS, in)
-            .query(ServiceNowParams.SYSPARM_INPUT_DISPLAY_VALUE, in)
-            .query(ServiceNowParams.SYSPARM_SUPPRESS_AUTO_SYS_FIELD, in)
-            .query(ServiceNowParams.SYSPARM_VIEW, in)
-            .query(responseModel)
-            .invoke("PATCH", in.getMandatoryBody());
-
-        setBodyAndHeaders(exchange.getIn(), responseModel, response);
-    }
-}

http://git-wip-us.apache.org/repos/asf/camel/blob/109da7c9/components/camel-servicenow/src/main/resources/META-INF/LICENSE.txt
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/src/main/resources/META-INF/LICENSE.txt b/components/camel-servicenow/src/main/resources/META-INF/LICENSE.txt
deleted file mode 100644
index 6b0b127..0000000
--- a/components/camel-servicenow/src/main/resources/META-INF/LICENSE.txt
+++ /dev/null
@@ -1,203 +0,0 @@
-
-                                 Apache License
-                           Version 2.0, January 2004
-                        http://www.apache.org/licenses/
-
-   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
-   1. Definitions.
-
-      "License" shall mean the terms and conditions for use, reproduction,
-      and distribution as defined by Sections 1 through 9 of this document.
-
-      "Licensor" shall mean the copyright owner or entity authorized by
-      the copyright owner that is granting the License.
-
-      "Legal Entity" shall mean the union of the acting entity and all
-      other entities that control, are controlled by, or are under common
-      control with that entity. For the purposes of this definition,
-      "control" means (i) the power, direct or indirect, to cause the
-      direction or management of such entity, whether by contract or
-      otherwise, or (ii) ownership of fifty percent (50%) or more of the
-      outstanding shares, or (iii) beneficial ownership of such entity.
-
-      "You" (or "Your") shall mean an individual or Legal Entity
-      exercising permissions granted by this License.
-
-      "Source" form shall mean the preferred form for making modifications,
-      including but not limited to software source code, documentation
-      source, and configuration files.
-
-      "Object" form shall mean any form resulting from mechanical
-      transformation or translation of a Source form, including but
-      not limited to compiled object code, generated documentation,
-      and conversions to other media types.
-
-      "Work" shall mean the work of authorship, whether in Source or
-      Object form, made available under the License, as indicated by a
-      copyright notice that is included in or attached to the work
-      (an example is provided in the Appendix below).
-
-      "Derivative Works" shall mean any work, whether in Source or Object
-      form, that is based on (or derived from) the Work and for which the
-      editorial revisions, annotations, elaborations, or other modifications
-      represent, as a whole, an original work of authorship. For the purposes
-      of this License, Derivative Works shall not include works that remain
-      separable from, or merely link (or bind by name) to the interfaces of,
-      the Work and Derivative Works thereof.
-
-      "Contribution" shall mean any work of authorship, including
-      the original version of the Work and any modifications or additions
-      to that Work or Derivative Works thereof, that is intentionally
-      submitted to Licensor for inclusion in the Work by the copyright owner
-      or by an individual or Legal Entity authorized to submit on behalf of
-      the copyright owner. For the purposes of this definition, "submitted"
-      means any form of electronic, verbal, or written communication sent
-      to the Licensor or its representatives, including but not limited to
-      communication on electronic mailing lists, source code control systems,
-      and issue tracking systems that are managed by, or on behalf of, the
-      Licensor for the purpose of discussing and improving the Work, but
-      excluding communication that is conspicuously marked or otherwise
-      designated in writing by the copyright owner as "Not a Contribution."
-
-      "Contributor" shall mean Licensor and any individual or Legal Entity
-      on behalf of whom a Contribution has been received by Licensor and
-      subsequently incorporated within the Work.
-
-   2. Grant of Copyright License. Subject to the terms and conditions of
-      this License, each Contributor hereby grants to You a perpetual,
-      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
-      copyright license to reproduce, prepare Derivative Works of,
-      publicly display, publicly perform, sublicense, and distribute the
-      Work and such Derivative Works in Source or Object form.
-
-   3. Grant of Patent License. Subject to the terms and conditions of
-      this License, each Contributor hereby grants to You a perpetual,
-      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
-      (except as stated in this section) patent license to make, have made,
-      use, offer to sell, sell, import, and otherwise transfer the Work,
-      where such license applies only to those patent claims licensable
-      by such Contributor that are necessarily infringed by their
-      Contribution(s) alone or by combination of their Contribution(s)
-      with the Work to which such Contribution(s) was submitted. If You
-      institute patent litigation against any entity (including a
-      cross-claim or counterclaim in a lawsuit) alleging that the Work
-      or a Contribution incorporated within the Work constitutes direct
-      or contributory patent infringement, then any patent licenses
-      granted to You under this License for that Work shall terminate
-      as of the date such litigation is filed.
-
-   4. Redistribution. You may reproduce and distribute copies of the
-      Work or Derivative Works thereof in any medium, with or without
-      modifications, and in Source or Object form, provided that You
-      meet the following conditions:
-
-      (a) You must give any other recipients of the Work or
-          Derivative Works a copy of this License; and
-
-      (b) You must cause any modified files to carry prominent notices
-          stating that You changed the files; and
-
-      (c) You must retain, in the Source form of any Derivative Works
-          that You distribute, all copyright, patent, trademark, and
-          attribution notices from the Source form of the Work,
-          excluding those notices that do not pertain to any part of
-          the Derivative Works; and
-
-      (d) If the Work includes a "NOTICE" text file as part of its
-          distribution, then any Derivative Works that You distribute must
-          include a readable copy of the attribution notices contained
-          within such NOTICE file, excluding those notices that do not
-          pertain to any part of the Derivative Works, in at least one
-          of the following places: within a NOTICE text file distributed
-          as part of the Derivative Works; within the Source form or
-          documentation, if provided along with the Derivative Works; or,
-          within a display generated by the Derivative Works, if and
-          wherever such third-party notices normally appear. The contents
-          of the NOTICE file are for informational purposes only and
-          do not modify the License. You may add Your own attribution
-          notices within Derivative Works that You distribute, alongside
-          or as an addendum to the NOTICE text from the Work, provided
-          that such additional attribution notices cannot be construed
-          as modifying the License.
-
-      You may add Your own copyright statement to Your modifications and
-      may provide additional or different license terms and conditions
-      for use, reproduction, or distribution of Your modifications, or
-      for any such Derivative Works as a whole, provided Your use,
-      reproduction, and distribution of the Work otherwise complies with
-      the conditions stated in this License.
-
-   5. Submission of Contributions. Unless You explicitly state otherwise,
-      any Contribution intentionally submitted for inclusion in the Work
-      by You to the Licensor shall be under the terms and conditions of
-      this License, without any additional terms or conditions.
-      Notwithstanding the above, nothing herein shall supersede or modify
-      the terms of any separate license agreement you may have executed
-      with Licensor regarding such Contributions.
-
-   6. Trademarks. This License does not grant permission to use the trade
-      names, trademarks, service marks, or product names of the Licensor,
-      except as required for reasonable and customary use in describing the
-      origin of the Work and reproducing the content of the NOTICE file.
-
-   7. Disclaimer of Warranty. Unless required by applicable law or
-      agreed to in writing, Licensor provides the Work (and each
-      Contributor provides its Contributions) on an "AS IS" BASIS,
-      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-      implied, including, without limitation, any warranties or conditions
-      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
-      PARTICULAR PURPOSE. You are solely responsible for determining the
-      appropriateness of using or redistributing the Work and assume any
-      risks associated with Your exercise of permissions under this License.
-
-   8. Limitation of Liability. In no event and under no legal theory,
-      whether in tort (including negligence), contract, or otherwise,
-      unless required by applicable law (such as deliberate and grossly
-      negligent acts) or agreed to in writing, shall any Contributor be
-      liable to You for damages, including any direct, indirect, special,
-      incidental, or consequential damages of any character arising as a
-      result of this License or out of the use or inability to use the
-      Work (including but not limited to damages for loss of goodwill,
-      work stoppage, computer failure or malfunction, or any and all
-      other commercial damages or losses), even if such Contributor
-      has been advised of the possibility of such damages.
-
-   9. Accepting Warranty or Additional Liability. While redistributing
-      the Work or Derivative Works thereof, You may choose to offer,
-      and charge a fee for, acceptance of support, warranty, indemnity,
-      or other liability obligations and/or rights consistent with this
-      License. However, in accepting such obligations, You may act only
-      on Your own behalf and on Your sole responsibility, not on behalf
-      of any other Contributor, and only if You agree to indemnify,
-      defend, and hold each Contributor harmless for any liability
-      incurred by, or claims asserted against, such Contributor by reason
-      of your accepting any such warranty or additional liability.
-
-   END OF TERMS AND CONDITIONS
-
-   APPENDIX: How to apply the Apache License to your work.
-
-      To apply the Apache License to your work, attach the following
-      boilerplate notice, with the fields enclosed by brackets "[]"
-      replaced with your own identifying information. (Don't include
-      the brackets!)  The text should be enclosed in the appropriate
-      comment syntax for the file format. We also recommend that a
-      file or class name and description of purpose be included on the
-      same "printed page" as the copyright notice for easier
-      identification within third-party archives.
-
-   Copyright [yyyy] [name of copyright owner]
-
-   Licensed 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.
-

http://git-wip-us.apache.org/repos/asf/camel/blob/109da7c9/components/camel-servicenow/src/main/resources/META-INF/NOTICE.txt
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/src/main/resources/META-INF/NOTICE.txt b/components/camel-servicenow/src/main/resources/META-INF/NOTICE.txt
deleted file mode 100644
index 2e215bf..0000000
--- a/components/camel-servicenow/src/main/resources/META-INF/NOTICE.txt
+++ /dev/null
@@ -1,11 +0,0 @@
-   =========================================================================
-   ==  NOTICE file corresponding to the section 4 d of                    ==
-   ==  the Apache License, Version 2.0,                                   ==
-   ==  in this case for the Apache Camel distribution.                    ==
-   =========================================================================
-
-   This product includes software developed by
-   The Apache Software Foundation (http://www.apache.org/).
-
-   Please read the different LICENSE files present in the licenses directory of
-   this distribution.

http://git-wip-us.apache.org/repos/asf/camel/blob/109da7c9/components/camel-servicenow/src/main/resources/META-INF/services/org/apache/camel/component/servicenow
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/src/main/resources/META-INF/services/org/apache/camel/component/servicenow b/components/camel-servicenow/src/main/resources/META-INF/services/org/apache/camel/component/servicenow
deleted file mode 100644
index 38858aa..0000000
--- a/components/camel-servicenow/src/main/resources/META-INF/services/org/apache/camel/component/servicenow
+++ /dev/null
@@ -1,18 +0,0 @@
-#
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License.  You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-class=org.apache.camel.component.servicenow.ServiceNowComponent

http://git-wip-us.apache.org/repos/asf/camel/blob/109da7c9/components/camel-servicenow/src/test/java/org/apache/camel/component/servicenow/ServiceNowAttachmentTest.java
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/src/test/java/org/apache/camel/component/servicenow/ServiceNowAttachmentTest.java b/components/camel-servicenow/src/test/java/org/apache/camel/component/servicenow/ServiceNowAttachmentTest.java
deleted file mode 100644
index 18772d2..0000000
--- a/components/camel-servicenow/src/test/java/org/apache/camel/component/servicenow/ServiceNowAttachmentTest.java
+++ /dev/null
@@ -1,129 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.camel.component.servicenow;
-
-import java.io.InputStream;
-import java.util.List;
-import java.util.Map;
-import java.util.UUID;
-
-import org.apache.camel.Exchange;
-import org.apache.camel.Produce;
-import org.apache.camel.ProducerTemplate;
-import org.apache.camel.builder.RouteBuilder;
-import org.apache.camel.component.servicenow.model.AttachmentMeta;
-import org.junit.Test;
-
-import static org.apache.camel.util.ResourceHelper.resolveResourceAsInputStream;
-
-public class ServiceNowAttachmentTest extends ServiceNowTestSupport {
-    @Produce(uri = "direct:servicenow")
-    ProducerTemplate template;
-
-    @Test
-    public void testAttachment() throws Exception {
-        List<AttachmentMeta> attachmentMetaList = template.requestBodyAndHeaders(
-            "direct:servicenow",
-            null,
-            kvBuilder()
-                .put(ServiceNowConstants.RESOURCE, ServiceNowConstants.RESOURCE_ATTACHMENT)
-                .put(ServiceNowConstants.ACTION, ServiceNowConstants.ACTION_RETRIEVE)
-                .put(ServiceNowConstants.MODEL, AttachmentMeta.class)
-                .put(ServiceNowParams.SYSPARM_QUERY, "content_type=application/octet-stream")
-                .put(ServiceNowParams.SYSPARM_LIMIT, 1)
-                .build(),
-            List.class
-        );
-
-        assertFalse(attachmentMetaList.isEmpty());
-
-        Exchange getExistingResult = template.send(
-            "direct:servicenow",
-            e -> {
-                e.getIn().setHeader(ServiceNowConstants.RESOURCE, ServiceNowConstants.RESOURCE_ATTACHMENT);
-                e.getIn().setHeader(ServiceNowConstants.ACTION, ServiceNowConstants.ACTION_CONTENT);
-                e.getIn().setHeader(ServiceNowParams.PARAM_SYS_ID.getHeader(), attachmentMetaList.get(0).getId());
-            }
-        );
-
-        assertNotNull(getExistingResult.getIn().getHeader(ServiceNowConstants.CONTENT_META));
-        assertNotNull(getExistingResult.getIn().getBody());
-        assertTrue(getExistingResult.getIn().getBody() instanceof InputStream);
-
-        Map<String, String> contentMeta = getExistingResult.getIn().getHeader(ServiceNowConstants.CONTENT_META, Map.class);
-        assertEquals(contentMeta.get("file_name"), attachmentMetaList.get(0).getFileName());
-        assertEquals(contentMeta.get("table_name"), attachmentMetaList.get(0).getTableName());
-        assertEquals(contentMeta.get("sys_id"), attachmentMetaList.get(0).getId());
-
-        Exchange putResult = template.send(
-            "direct:servicenow",
-            e -> {
-                e.getIn().setHeader(ServiceNowConstants.RESOURCE, ServiceNowConstants.RESOURCE_ATTACHMENT);
-                e.getIn().setHeader(ServiceNowConstants.ACTION, ServiceNowConstants.ACTION_UPLOAD);
-                e.getIn().setHeader(ServiceNowConstants.MODEL, AttachmentMeta.class);
-                e.getIn().setHeader(ServiceNowConstants.CONTENT_TYPE, "application/octet-stream");
-                e.getIn().setHeader(ServiceNowParams.PARAM_FILE_NAME.getHeader(), UUID.randomUUID().toString());
-                e.getIn().setHeader(ServiceNowParams.PARAM_TABLE_NAME.getHeader(), attachmentMetaList.get(0).getTableName());
-                e.getIn().setHeader(ServiceNowParams.PARAM_TABLE_SYS_ID.getHeader(), attachmentMetaList.get(0).getTableSysId());
-                e.getIn().setBody(resolveResourceAsInputStream(e.getContext().getClassResolver(), "classpath:my-content.txt"));
-            }
-        );
-
-        Exchange getCreatedResult = template.send(
-            "direct:servicenow",
-            e -> {
-                e.getIn().setHeader(ServiceNowConstants.RESOURCE, ServiceNowConstants.RESOURCE_ATTACHMENT);
-                e.getIn().setHeader(ServiceNowConstants.ACTION, ServiceNowConstants.ACTION_CONTENT);
-                e.getIn().setHeader(ServiceNowParams.PARAM_SYS_ID.getHeader(), putResult.getIn().getBody(AttachmentMeta.class).getId());
-            }
-        );
-
-        assertNotNull(getCreatedResult.getIn().getHeader(ServiceNowConstants.CONTENT_META));
-        assertNotNull(getCreatedResult.getIn().getBody());
-        assertTrue(getCreatedResult.getIn().getBody() instanceof InputStream);
-
-        Exchange deleteResult = template.send(
-            "direct:servicenow",
-            e -> {
-                e.getIn().setHeader(ServiceNowConstants.RESOURCE, ServiceNowConstants.RESOURCE_ATTACHMENT);
-                e.getIn().setHeader(ServiceNowConstants.ACTION, ServiceNowConstants.ACTION_DELETE);
-                e.getIn().setHeader(ServiceNowParams.PARAM_SYS_ID.getHeader(), putResult.getIn().getBody(AttachmentMeta.class).getId());
-            }
-        );
-
-        if (deleteResult.getException() != null) {
-            throw deleteResult.getException();
-        }
-    }
-
-    // *************************************************************************
-    //
-    // *************************************************************************
-
-    @Override
-    protected RouteBuilder createRouteBuilder() throws Exception {
-        return new RouteBuilder() {
-            public void configure() {
-                from("direct:servicenow")
-                    .to("servicenow:{{env:SERVICENOW_INSTANCE}}")
-                    .to("log:org.apache.camel.component.servicenow?level=INFO&showAll=true")
-                    .to("mock:servicenow");
-            }
-        };
-    }
-}

http://git-wip-us.apache.org/repos/asf/camel/blob/109da7c9/components/camel-servicenow/src/test/java/org/apache/camel/component/servicenow/ServiceNowBlueprintComponentAuthTest.java
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/src/test/java/org/apache/camel/component/servicenow/ServiceNowBlueprintComponentAuthTest.java b/components/camel-servicenow/src/test/java/org/apache/camel/component/servicenow/ServiceNowBlueprintComponentAuthTest.java
deleted file mode 100644
index c3b524a..0000000
--- a/components/camel-servicenow/src/test/java/org/apache/camel/component/servicenow/ServiceNowBlueprintComponentAuthTest.java
+++ /dev/null
@@ -1,67 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.camel.component.servicenow;
-
-import java.util.List;
-
-import org.apache.camel.Exchange;
-import org.apache.camel.component.mock.MockEndpoint;
-import org.apache.camel.component.servicenow.model.Incident;
-import org.apache.camel.test.blueprint.CamelBlueprintTestSupport;
-import org.junit.Test;
-
-public class ServiceNowBlueprintComponentAuthTest extends CamelBlueprintTestSupport {
-    @Override
-    protected String getBlueprintDescriptor() {
-        return "OSGI-INF/blueprint/blueprint-component-auth.xml";
-    }
-
-    @Test
-    public void testAuth() throws Exception {
-        MockEndpoint mock1 = getMockEndpoint("mock:servicenow-1");
-        mock1.expectedMessageCount(1);
-        MockEndpoint mock2 = getMockEndpoint("mock:servicenow-2");
-        mock2.expectedMessageCount(1);
-
-        template().sendBodyAndHeaders(
-            "direct:servicenow",
-            null,
-            ServiceNowTestSupport.kvBuilder()
-                .put(ServiceNowConstants.RESOURCE, "table")
-                .put(ServiceNowConstants.ACTION, ServiceNowConstants.ACTION_RETRIEVE)
-                .put(ServiceNowParams.SYSPARM_LIMIT, 10)
-                .put(ServiceNowParams.PARAM_TABLE_NAME, "incident")
-                .build()
-        );
-
-        mock1.assertIsSatisfied();
-        mock2.assertIsSatisfied();
-
-        validate(mock1.getExchanges().get(0));
-        validate(mock2.getExchanges().get(0));
-    }
-
-    private void validate(Exchange exchange) {
-        List<Incident> items = exchange.getIn().getBody(List.class);
-
-        assertNotNull(items);
-        assertTrue(items.size() <= 10);
-        assertNotNull(exchange.getIn().getHeader(ServiceNowConstants.OFFSET_FIRST));
-        assertNotNull(exchange.getIn().getHeader(ServiceNowConstants.OFFSET_NEXT));
-        assertNotNull(exchange.getIn().getHeader(ServiceNowConstants.OFFSET_LAST));
-    }
-}

http://git-wip-us.apache.org/repos/asf/camel/blob/109da7c9/components/camel-servicenow/src/test/java/org/apache/camel/component/servicenow/ServiceNowBlueprintEndpointAuthTest.java
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/src/test/java/org/apache/camel/component/servicenow/ServiceNowBlueprintEndpointAuthTest.java b/components/camel-servicenow/src/test/java/org/apache/camel/component/servicenow/ServiceNowBlueprintEndpointAuthTest.java
deleted file mode 100644
index 581404c..0000000
--- a/components/camel-servicenow/src/test/java/org/apache/camel/component/servicenow/ServiceNowBlueprintEndpointAuthTest.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.camel.component.servicenow;
-
-import java.util.List;
-
-import org.apache.camel.Exchange;
-import org.apache.camel.component.mock.MockEndpoint;
-import org.apache.camel.component.servicenow.model.Incident;
-import org.apache.camel.test.blueprint.CamelBlueprintTestSupport;
-import org.junit.Test;
-
-public class ServiceNowBlueprintEndpointAuthTest extends CamelBlueprintTestSupport {
-    @Override
-    protected String getBlueprintDescriptor() {
-        return "OSGI-INF/blueprint/blueprint-endpoint-auth.xml";
-    }
-
-    @Test
-    public void testAuth() throws Exception {
-        MockEndpoint mock = getMockEndpoint("mock:servicenow");
-        mock.expectedMessageCount(1);
-
-        template().sendBodyAndHeaders(
-            "direct:servicenow",
-            null,
-            ServiceNowTestSupport.kvBuilder()
-                .put(ServiceNowConstants.RESOURCE, "table")
-                .put(ServiceNowConstants.ACTION, ServiceNowConstants.ACTION_RETRIEVE)
-                .put(ServiceNowParams.SYSPARM_LIMIT, 10)
-                .put(ServiceNowParams.PARAM_TABLE_NAME, "incident")
-                .build()
-        );
-
-        mock.assertIsSatisfied();
-
-        Exchange exchange = mock.getExchanges().get(0);
-        List<Incident> items = exchange.getIn().getBody(List.class);
-
-        assertNotNull(items);
-        assertTrue(items.size() <= 10);
-        assertNotNull(exchange.getIn().getHeader(ServiceNowConstants.OFFSET_FIRST));
-        assertNotNull(exchange.getIn().getHeader(ServiceNowConstants.OFFSET_NEXT));
-        assertNotNull(exchange.getIn().getHeader(ServiceNowConstants.OFFSET_LAST));
-    }
-}

http://git-wip-us.apache.org/repos/asf/camel/blob/109da7c9/components/camel-servicenow/src/test/java/org/apache/camel/component/servicenow/ServiceNowComponentVerifierExtensionTest.java
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/src/test/java/org/apache/camel/component/servicenow/ServiceNowComponentVerifierExtensionTest.java b/components/camel-servicenow/src/test/java/org/apache/camel/component/servicenow/ServiceNowComponentVerifierExtensionTest.java
deleted file mode 100644
index a06d503..0000000
--- a/components/camel-servicenow/src/test/java/org/apache/camel/component/servicenow/ServiceNowComponentVerifierExtensionTest.java
+++ /dev/null
@@ -1,151 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.camel.component.servicenow;
-
-import java.util.Map;
-import javax.ws.rs.ProcessingException;
-
-import org.apache.camel.Component;
-import org.apache.camel.component.extension.ComponentVerifierExtension;
-import org.junit.Assert;
-import org.junit.Test;
-
-public class ServiceNowComponentVerifierExtensionTest extends ServiceNowTestSupport {
-    public ServiceNowComponentVerifierExtensionTest() {
-        super(false);
-    }
-
-    @Override
-    public boolean isUseRouteBuilder() {
-        return false;
-    }
-
-    protected ComponentVerifierExtension getExtension() {
-        Component component = context().getComponent("servicenow");
-        ComponentVerifierExtension verifier = component.getExtension(ComponentVerifierExtension.class).orElseThrow(IllegalStateException::new);
-
-        return verifier;
-    }
-
-    // *********************************
-    // Parameters validation
-    // *********************************
-
-    @Test
-    public void testParameter() {
-        Map<String, Object> parameters = getParameters();
-        ComponentVerifierExtension.Result result = getExtension().verify(ComponentVerifierExtension.Scope.PARAMETERS, parameters);
-
-        Assert.assertEquals(ComponentVerifierExtension.Result.Status.OK, result.getStatus());
-    }
-
-    @Test
-    public void testMissingMandatoryParameter() {
-        Map<String, Object> parameters = getParameters();
-        parameters.remove("instanceName");
-        ComponentVerifierExtension.Result result = getExtension().verify(ComponentVerifierExtension.Scope.PARAMETERS, parameters);
-
-        Assert.assertEquals(ComponentVerifierExtension.Result.Status.ERROR, result.getStatus());
-        Assert.assertEquals(1, result.getErrors().size());
-        Assert.assertEquals(ComponentVerifierExtension.VerificationError.StandardCode.MISSING_PARAMETER, result.getErrors().get(0).getCode());
-        Assert.assertEquals("instanceName", result.getErrors().get(0).getParameterKeys().iterator().next());
-    }
-
-    @Test
-    public void testMissingMandatoryAuthenticationParameter() {
-        Map<String, Object> parameters = getParameters();
-        parameters.remove("userName");
-        ComponentVerifierExtension.Result result = getExtension().verify(ComponentVerifierExtension.Scope.PARAMETERS, parameters);
-
-        Assert.assertEquals(ComponentVerifierExtension.Result.Status.ERROR, result.getStatus());
-        Assert.assertEquals(1, result.getErrors().size());
-        Assert.assertEquals(ComponentVerifierExtension.VerificationError.StandardCode.MISSING_PARAMETER, result.getErrors().get(0).getCode());
-        Assert.assertEquals("userName", result.getErrors().get(0).getParameterKeys().iterator().next());
-    }
-
-    // *********************************
-    // Connectivity validation
-    // *********************************
-
-    @Test
-    public void testConnectivity() {
-        Map<String, Object> parameters = getParameters();
-        ComponentVerifierExtension.Result result = getExtension().verify(ComponentVerifierExtension.Scope.CONNECTIVITY, parameters);
-
-        Assert.assertEquals(ComponentVerifierExtension.Result.Status.OK, result.getStatus());
-    }
-
-    @Test
-    public void testConnectivityOnCustomTable() {
-        Map<String, Object> parameters = getParameters();
-        parameters.put("table", "ticket");
-
-        ComponentVerifierExtension.Result result = getExtension().verify(ComponentVerifierExtension.Scope.CONNECTIVITY, parameters);
-
-        Assert.assertEquals(ComponentVerifierExtension.Result.Status.OK, result.getStatus());
-    }
-
-    @Test
-    public void testConnectivityWithWrongInstance() {
-        Map<String, Object> parameters = getParameters();
-        parameters.put("instanceName", "unknown-instance");
-
-        ComponentVerifierExtension.Result result = getExtension().verify(ComponentVerifierExtension.Scope.CONNECTIVITY, parameters);
-
-        Assert.assertEquals(ComponentVerifierExtension.Result.Status.ERROR, result.getStatus());
-        Assert.assertEquals(1, result.getErrors().size());
-        Assert.assertEquals(ComponentVerifierExtension.VerificationError.StandardCode.EXCEPTION, result.getErrors().get(0).getCode());
-        Assert.assertNotNull(result.getErrors().get(0).getDetails().get(ComponentVerifierExtension.VerificationError.ExceptionAttribute.EXCEPTION_INSTANCE));
-        Assert.assertTrue(result.getErrors().get(0).getDetails().get(ComponentVerifierExtension.VerificationError.ExceptionAttribute.EXCEPTION_INSTANCE) instanceof ProcessingException);
-    }
-
-    @Test
-    public void testConnectivityWithWrongTable() {
-        Map<String, Object> parameters = getParameters();
-        parameters.put("table", "unknown");
-
-        ComponentVerifierExtension.Result result = getExtension().verify(ComponentVerifierExtension.Scope.CONNECTIVITY, parameters);
-
-        Assert.assertEquals(ComponentVerifierExtension.Result.Status.ERROR, result.getStatus());
-        Assert.assertEquals(1, result.getErrors().size());
-        Assert.assertEquals(ComponentVerifierExtension.VerificationError.StandardCode.EXCEPTION, result.getErrors().get(0).getCode());
-        Assert.assertNotNull(result.getErrors().get(0).getDetails().get(ComponentVerifierExtension.VerificationError.ExceptionAttribute.EXCEPTION_INSTANCE));
-        Assert.assertEquals(400, result.getErrors().get(0).getDetails().get(ComponentVerifierExtension.VerificationError.HttpAttribute.HTTP_CODE));
-        Assert.assertTrue(result.getErrors().get(0).getDetails().get(ComponentVerifierExtension.VerificationError.ExceptionAttribute.EXCEPTION_INSTANCE) instanceof ServiceNowException);
-    }
-
-    @Test
-    public void testConnectivityWithWrongAuthentication() {
-        Map<String, Object> parameters = getParameters();
-        parameters.put("userName", "unknown-user");
-        parameters.remove("oauthClientId");
-        parameters.remove("oauthClientSecret");
-
-        ComponentVerifierExtension.Result result = getExtension().verify(ComponentVerifierExtension.Scope.CONNECTIVITY, parameters);
-
-        Assert.assertEquals(ComponentVerifierExtension.Result.Status.ERROR, result.getStatus());
-        Assert.assertEquals(1, result.getErrors().size());
-        Assert.assertEquals(ComponentVerifierExtension.VerificationError.StandardCode.AUTHENTICATION, result.getErrors().get(0).getCode());
-        Assert.assertNotNull(result.getErrors().get(0).getDetails().get(ComponentVerifierExtension.VerificationError.ExceptionAttribute.EXCEPTION_INSTANCE));
-        Assert.assertEquals(401, result.getErrors().get(0).getDetails().get(ComponentVerifierExtension.VerificationError.HttpAttribute.HTTP_CODE));
-        Assert.assertTrue(result.getErrors().get(0).getDetails().get(ComponentVerifierExtension.VerificationError.ExceptionAttribute.EXCEPTION_INSTANCE) instanceof ServiceNowException);
-        Assert.assertTrue(result.getErrors().get(0).getParameterKeys().contains("userName"));
-        Assert.assertTrue(result.getErrors().get(0).getParameterKeys().contains("password"));
-        Assert.assertTrue(result.getErrors().get(0).getParameterKeys().contains("oauthClientId"));
-        Assert.assertTrue(result.getErrors().get(0).getParameterKeys().contains("oauthClientSecret"));
-    }
-}

http://git-wip-us.apache.org/repos/asf/camel/blob/109da7c9/components/camel-servicenow/src/test/java/org/apache/camel/component/servicenow/ServiceNowComponentVerifierTest.java
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/src/test/java/org/apache/camel/component/servicenow/ServiceNowComponentVerifierTest.java b/components/camel-servicenow/src/test/java/org/apache/camel/component/servicenow/ServiceNowComponentVerifierTest.java
deleted file mode 100644
index 120346a..0000000
--- a/components/camel-servicenow/src/test/java/org/apache/camel/component/servicenow/ServiceNowComponentVerifierTest.java
+++ /dev/null
@@ -1,147 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.camel.component.servicenow;
-
-import java.util.Map;
-import javax.ws.rs.ProcessingException;
-
-import org.apache.camel.ComponentVerifier;
-import org.junit.Assert;
-import org.junit.Test;
-
-public class ServiceNowComponentVerifierTest extends ServiceNowTestSupport {
-    public ServiceNowComponentVerifierTest() {
-        super(false);
-    }
-
-    @Override
-    public boolean isUseRouteBuilder() {
-        return false;
-    }
-
-    protected ComponentVerifier getVerifier() {
-        return context().getComponent("servicenow", ServiceNowComponent.class).getVerifier();
-    }
-
-    // *********************************
-    // Parameters validation
-    // *********************************
-
-    @Test
-    public void testParameter() {
-        Map<String, Object> parameters = getParameters();
-        ComponentVerifier.Result result = getVerifier().verify(ComponentVerifier.Scope.PARAMETERS, parameters);
-
-        Assert.assertEquals(ComponentVerifier.Result.Status.OK, result.getStatus());
-    }
-
-    @Test
-    public void testMissingMandatoryParameter() {
-        Map<String, Object> parameters = getParameters();
-        parameters.remove("instanceName");
-        ComponentVerifier.Result result = getVerifier().verify(ComponentVerifier.Scope.PARAMETERS, parameters);
-
-        Assert.assertEquals(ComponentVerifier.Result.Status.ERROR, result.getStatus());
-        Assert.assertEquals(1, result.getErrors().size());
-        Assert.assertEquals(ComponentVerifier.VerificationError.StandardCode.MISSING_PARAMETER, result.getErrors().get(0).getCode());
-        Assert.assertEquals("instanceName", result.getErrors().get(0).getParameterKeys().iterator().next());
-    }
-
-    @Test
-    public void testMissingMandatoryAuthenticationParameter() {
-        Map<String, Object> parameters = getParameters();
-        parameters.remove("userName");
-        ComponentVerifier.Result result = getVerifier().verify(ComponentVerifier.Scope.PARAMETERS, parameters);
-
-        Assert.assertEquals(ComponentVerifier.Result.Status.ERROR, result.getStatus());
-        Assert.assertEquals(1, result.getErrors().size());
-        Assert.assertEquals(ComponentVerifier.VerificationError.StandardCode.MISSING_PARAMETER, result.getErrors().get(0).getCode());
-        Assert.assertEquals("userName", result.getErrors().get(0).getParameterKeys().iterator().next());
-    }
-
-    // *********************************
-    // Connectivity validation
-    // *********************************
-
-    @Test
-    public void testConnectivity() {
-        Map<String, Object> parameters = getParameters();
-        ComponentVerifier.Result result = getVerifier().verify(ComponentVerifier.Scope.CONNECTIVITY, parameters);
-
-        Assert.assertEquals(ComponentVerifier.Result.Status.OK, result.getStatus());
-    }
-
-    @Test
-    public void testConnectivityOnCustomTable() {
-        Map<String, Object> parameters = getParameters();
-        parameters.put("table", "ticket");
-
-        ComponentVerifier.Result result = getVerifier().verify(ComponentVerifier.Scope.CONNECTIVITY, parameters);
-
-        Assert.assertEquals(ComponentVerifier.Result.Status.OK, result.getStatus());
-    }
-
-    @Test
-    public void testConnectivityWithWrongInstance() {
-        Map<String, Object> parameters = getParameters();
-        parameters.put("instanceName", "unknown-instance");
-
-        ComponentVerifier.Result result = getVerifier().verify(ComponentVerifier.Scope.CONNECTIVITY, parameters);
-
-        Assert.assertEquals(ComponentVerifier.Result.Status.ERROR, result.getStatus());
-        Assert.assertEquals(1, result.getErrors().size());
-        Assert.assertEquals(ComponentVerifier.VerificationError.StandardCode.EXCEPTION, result.getErrors().get(0).getCode());
-        Assert.assertNotNull(result.getErrors().get(0).getDetails().get(ComponentVerifier.VerificationError.ExceptionAttribute.EXCEPTION_INSTANCE));
-        Assert.assertTrue(result.getErrors().get(0).getDetails().get(ComponentVerifier.VerificationError.ExceptionAttribute.EXCEPTION_INSTANCE) instanceof ProcessingException);
-    }
-
-    @Test
-    public void testConnectivityWithWrongTable() {
-        Map<String, Object> parameters = getParameters();
-        parameters.put("table", "unknown");
-
-        ComponentVerifier.Result result = getVerifier().verify(ComponentVerifier.Scope.CONNECTIVITY, parameters);
-
-        Assert.assertEquals(ComponentVerifier.Result.Status.ERROR, result.getStatus());
-        Assert.assertEquals(1, result.getErrors().size());
-        Assert.assertEquals(ComponentVerifier.VerificationError.StandardCode.EXCEPTION, result.getErrors().get(0).getCode());
-        Assert.assertNotNull(result.getErrors().get(0).getDetails().get(ComponentVerifier.VerificationError.ExceptionAttribute.EXCEPTION_INSTANCE));
-        Assert.assertEquals(400, result.getErrors().get(0).getDetails().get(ComponentVerifier.VerificationError.HttpAttribute.HTTP_CODE));
-        Assert.assertTrue(result.getErrors().get(0).getDetails().get(ComponentVerifier.VerificationError.ExceptionAttribute.EXCEPTION_INSTANCE) instanceof ServiceNowException);
-    }
-
-    @Test
-    public void testConnectivityWithWrongAuthentication() {
-        Map<String, Object> parameters = getParameters();
-        parameters.put("userName", "unknown-user");
-        parameters.remove("oauthClientId");
-        parameters.remove("oauthClientSecret");
-
-        ComponentVerifier.Result result = getVerifier().verify(ComponentVerifier.Scope.CONNECTIVITY, parameters);
-
-        Assert.assertEquals(ComponentVerifier.Result.Status.ERROR, result.getStatus());
-        Assert.assertEquals(1, result.getErrors().size());
-        Assert.assertEquals(ComponentVerifier.VerificationError.StandardCode.AUTHENTICATION, result.getErrors().get(0).getCode());
-        Assert.assertNotNull(result.getErrors().get(0).getDetails().get(ComponentVerifier.VerificationError.ExceptionAttribute.EXCEPTION_INSTANCE));
-        Assert.assertEquals(401, result.getErrors().get(0).getDetails().get(ComponentVerifier.VerificationError.HttpAttribute.HTTP_CODE));
-        Assert.assertTrue(result.getErrors().get(0).getDetails().get(ComponentVerifier.VerificationError.ExceptionAttribute.EXCEPTION_INSTANCE) instanceof ServiceNowException);
-        Assert.assertTrue(result.getErrors().get(0).getParameterKeys().contains("userName"));
-        Assert.assertTrue(result.getErrors().get(0).getParameterKeys().contains("password"));
-        Assert.assertTrue(result.getErrors().get(0).getParameterKeys().contains("oauthClientId"));
-        Assert.assertTrue(result.getErrors().get(0).getParameterKeys().contains("oauthClientSecret"));
-    }
-}

http://git-wip-us.apache.org/repos/asf/camel/blob/109da7c9/components/camel-servicenow/src/test/java/org/apache/camel/component/servicenow/ServiceNowImportSetTest.java
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/src/test/java/org/apache/camel/component/servicenow/ServiceNowImportSetTest.java b/components/camel-servicenow/src/test/java/org/apache/camel/component/servicenow/ServiceNowImportSetTest.java
deleted file mode 100644
index dd524bc..0000000
--- a/components/camel-servicenow/src/test/java/org/apache/camel/component/servicenow/ServiceNowImportSetTest.java
+++ /dev/null
@@ -1,147 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.camel.component.servicenow;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-import java.util.UUID;
-
-import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
-import com.fasterxml.jackson.annotation.JsonInclude;
-import com.fasterxml.jackson.annotation.JsonProperty;
-import org.apache.camel.Message;
-import org.apache.camel.builder.RouteBuilder;
-import org.apache.camel.component.mock.MockEndpoint;
-import org.apache.camel.component.servicenow.model.ImportSetResult;
-import org.apache.camel.component.servicenow.model.Incident;
-import org.junit.Ignore;
-import org.junit.Test;
-
-/**
- * To set-up ServiceNow for this tests:
- *
- * 1. Create a new web service named u_test_imp_incident targeting incident table
- * 2. Create a mapping (automatic)
- */
-@Ignore
-public class ServiceNowImportSetTest extends ServiceNowTestSupport {
-
-    @Test
-    public void testIncidentImport() throws Exception {
-        MockEndpoint mock = getMockEndpoint("mock:servicenow");
-
-        mock.reset();
-        mock.expectedMessageCount(1);
-        mock.expectedHeaderReceived(ServiceNowConstants.RESPONSE_TYPE, ArrayList.class);
-
-        IncidentImportRequest incident = new IncidentImportRequest();
-        incident.description = UUID.randomUUID().toString();
-        incident.correlationId = UUID.randomUUID().toString();
-
-        template().sendBodyAndHeaders(
-            "direct:servicenow",
-            incident,
-            kvBuilder()
-                .put(ServiceNowConstants.RESOURCE, ServiceNowConstants.RESOURCE_IMPORT)
-                .put(ServiceNowConstants.ACTION, ServiceNowConstants.ACTION_CREATE)
-                .put(ServiceNowConstants.REQUEST_MODEL, IncidentImportRequest.class)
-                .put(ServiceNowConstants.RESPONSE_MODEL, ImportSetResult.class)
-                .put(ServiceNowParams.PARAM_TABLE_NAME, "u_test_imp_incident")
-                .build()
-        );
-
-        mock.assertIsSatisfied();
-
-        Message in =  mock.getExchanges().get(0).getIn();
-
-        // Meta data
-        Map<String, String> meta = in.getHeader(ServiceNowConstants.RESPONSE_META, Map.class);
-        assertNotNull(meta);
-        assertEquals("u_test_imp_incident", meta.get("staging_table"));
-
-        // Incidents
-        List<ImportSetResult> responses = in.getBody(List.class);
-        assertNotNull(responses);
-        assertEquals(1, responses.size());
-        assertEquals("inserted", responses.get(0).getStatus());
-        assertEquals("test_imp_incident", responses.get(0).getTransformMap());
-        assertEquals("incident", responses.get(0).getTable());
-    }
-
-    @Test
-    public void testIncidentImportWithRetrieve() throws Exception {
-        MockEndpoint mock = getMockEndpoint("mock:servicenow");
-
-        mock.reset();
-        mock.expectedMessageCount(1);
-        mock.expectedHeaderReceived(ServiceNowConstants.RESPONSE_TYPE, Incident.class);
-
-        IncidentImportRequest incident = new IncidentImportRequest();
-        incident.description = UUID.randomUUID().toString();
-
-        template().sendBodyAndHeaders(
-            "direct:servicenow",
-            incident,
-            kvBuilder()
-                .put(ServiceNowConstants.RESOURCE, ServiceNowConstants.RESOURCE_IMPORT)
-                .put(ServiceNowConstants.ACTION, ServiceNowConstants.ACTION_CREATE)
-                .put(ServiceNowConstants.REQUEST_MODEL, IncidentImportRequest.class)
-                .put(ServiceNowConstants.RESPONSE_MODEL, Incident.class)
-                .put(ServiceNowConstants.RETRIEVE_TARGET_RECORD, true)
-                .put(ServiceNowParams.PARAM_TABLE_NAME, "u_test_imp_incident")
-                .build()
-        );
-
-        mock.assertIsSatisfied();
-
-        Incident response = mock.getExchanges().get(0).getIn().getBody(Incident.class);
-        assertNotNull(response);
-        assertEquals(incident.description, response.getDescription());
-        assertNotNull(response.getNumber());
-        assertNotNull(response.getId());
-    }
-
-    // *************************************************************************
-    //
-    // *************************************************************************
-
-    @Override
-    protected RouteBuilder createRouteBuilder() throws Exception {
-        return new RouteBuilder() {
-            public void configure() {
-                from("direct:servicenow")
-                    .to("servicenow:{{env:SERVICENOW_INSTANCE}}")
-                    .to("log:org.apache.camel.component.servicenow?level=INFO&showAll=true")
-                    .to("mock:servicenow");
-            }
-        };
-    }
-
-    // *************************************************************************
-    //
-    // *************************************************************************
-
-    @JsonIgnoreProperties(ignoreUnknown = true)
-    @JsonInclude(JsonInclude.Include.NON_NULL)
-    private static final class IncidentImportRequest {
-        @JsonProperty("description")
-        public String description;
-        @JsonProperty("correlation_id")
-        public String correlationId;
-    }
-}

http://git-wip-us.apache.org/repos/asf/camel/blob/109da7c9/components/camel-servicenow/src/test/java/org/apache/camel/component/servicenow/ServiceNowMetaDataExtensionTest.java
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/src/test/java/org/apache/camel/component/servicenow/ServiceNowMetaDataExtensionTest.java b/components/camel-servicenow/src/test/java/org/apache/camel/component/servicenow/ServiceNowMetaDataExtensionTest.java
deleted file mode 100644
index e99cb56..0000000
--- a/components/camel-servicenow/src/test/java/org/apache/camel/component/servicenow/ServiceNowMetaDataExtensionTest.java
+++ /dev/null
@@ -1,87 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.camel.component.servicenow;
-
-import java.util.Map;
-
-import com.fasterxml.jackson.databind.JsonNode;
-import org.apache.camel.component.extension.MetaDataExtension;
-import org.junit.Assert;
-import org.junit.Test;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class ServiceNowMetaDataExtensionTest extends ServiceNowTestSupport {
-    private static final Logger LOGGER = LoggerFactory.getLogger(ServiceNowMetaDataExtensionTest.class);
-
-    public ServiceNowMetaDataExtensionTest() {
-        super(false);
-    }
-
-    @Override
-    public boolean isUseRouteBuilder() {
-        return false;
-    }
-
-    protected ServiceNowComponent getComponent() {
-        return context().getComponent("servicenow", ServiceNowComponent.class);
-    }
-
-    protected MetaDataExtension getExtension() {
-        return getComponent().getExtension(MetaDataExtension.class).orElseThrow(IllegalStateException::new);
-    }
-
-    // *********************************
-    //
-    // *********************************
-
-    @Test
-    public void testMetaData() throws Exception {
-        Map<String, Object> parameters = getParameters();
-        parameters.put("objectType", "table");
-        parameters.put("objectName", "incident");
-        //parameters.put("object.sys_user.fields", "first_name,last_name");
-        //parameters.put("object.incident.fields", "caller_id,severity,resolved_at,sys_id");
-        //parameters.put("object.incident.fields", "^sys_.*$");
-        //parameters.put("object.task.fields", "");
-
-        MetaDataExtension.MetaData result = getExtension().meta(parameters).orElseThrow(IllegalStateException::new);
-
-        Assert.assertEquals("application/schema+json", result.getAttribute(MetaDataExtension.MetaData.CONTENT_TYPE));
-        Assert.assertEquals(JsonNode.class, result.getAttribute(MetaDataExtension.MetaData.JAVA_TYPE));
-        Assert.assertTrue(result.getPayload(JsonNode.class).hasNonNull("definitions"));
-        Assert.assertTrue(result.getPayload(JsonNode.class).get("definitions").hasNonNull("guid"));
-        Assert.assertTrue(result.getPayload(JsonNode.class).get("definitions").hasNonNull("date"));
-        Assert.assertTrue(result.getPayload(JsonNode.class).get("definitions").hasNonNull("time"));
-        Assert.assertTrue(result.getPayload(JsonNode.class).get("definitions").hasNonNull("date-time"));
-        Assert.assertTrue(result.getPayload(JsonNode.class).hasNonNull("properties"));
-
-        //LOGGER.info(
-        //    new ObjectMapper().writerWithDefaultPrettyPrinter().writeValueAsString(result.getPayload())
-        //);
-    }
-
-
-    @Test(expected = UnsupportedOperationException.class)
-    public void testMInvalidObjectType() throws Exception {
-        Map<String, Object> parameters = getParameters();
-        parameters.put("objectType", "test");
-        parameters.put("objectName", "incident");
-
-        getExtension().meta(parameters);
-    }
-}

http://git-wip-us.apache.org/repos/asf/camel/blob/109da7c9/components/camel-servicenow/src/test/java/org/apache/camel/component/servicenow/ServiceNowScorecardTest.java
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/src/test/java/org/apache/camel/component/servicenow/ServiceNowScorecardTest.java b/components/camel-servicenow/src/test/java/org/apache/camel/component/servicenow/ServiceNowScorecardTest.java
deleted file mode 100644
index 429bec2..0000000
--- a/components/camel-servicenow/src/test/java/org/apache/camel/component/servicenow/ServiceNowScorecardTest.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.camel.component.servicenow;
-
-import java.util.List;
-
-import org.apache.camel.Produce;
-import org.apache.camel.ProducerTemplate;
-import org.apache.camel.builder.RouteBuilder;
-import org.apache.camel.component.servicenow.model.Scorecard;
-import org.junit.Test;
-
-public class ServiceNowScorecardTest extends ServiceNowTestSupport {
-    @Produce(uri = "direct:servicenow")
-    ProducerTemplate template;
-
-    @Test
-    public void testScorecard() throws Exception {
-        List<Scorecard> scorecardList = template.requestBodyAndHeaders(
-            "direct:servicenow",
-            null,
-            kvBuilder()
-                .put(ServiceNowConstants.RESOURCE, ServiceNowConstants.RESOURCE_SCORECARDS)
-                .put(ServiceNowConstants.ACTION, ServiceNowConstants.ACTION_RETRIEVE)
-                .put(ServiceNowConstants.ACTION_SUBJECT, ServiceNowConstants.ACTION_SUBJECT_PERFORMANCE_ANALYTICS)
-                .put(ServiceNowConstants.MODEL, Scorecard.class)
-                .build(),
-            List.class
-        );
-
-        assertFalse(scorecardList.isEmpty());
-    }
-
-    // *************************************************************************
-    //
-    // *************************************************************************
-
-    @Override
-    protected RouteBuilder createRouteBuilder() throws Exception {
-        return new RouteBuilder() {
-            public void configure() {
-                from("direct:servicenow")
-                    .to("servicenow:{{env:SERVICENOW_INSTANCE}}")
-                    .to("log:org.apache.camel.component.servicenow?level=INFO&showAll=true")
-                    .to("mock:servicenow");
-            }
-        };
-    }
-}

http://git-wip-us.apache.org/repos/asf/camel/blob/109da7c9/components/camel-servicenow/src/test/java/org/apache/camel/component/servicenow/ServiceNowServiceCatalogTest.java
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/src/test/java/org/apache/camel/component/servicenow/ServiceNowServiceCatalogTest.java b/components/camel-servicenow/src/test/java/org/apache/camel/component/servicenow/ServiceNowServiceCatalogTest.java
deleted file mode 100644
index 9562be8..0000000
--- a/components/camel-servicenow/src/test/java/org/apache/camel/component/servicenow/ServiceNowServiceCatalogTest.java
+++ /dev/null
@@ -1,93 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.camel.component.servicenow;
-
-import java.util.List;
-import java.util.Map;
-
-import org.apache.camel.CamelExecutionException;
-import org.apache.camel.Produce;
-import org.apache.camel.ProducerTemplate;
-import org.apache.camel.builder.RouteBuilder;
-import org.junit.Test;
-
-public class ServiceNowServiceCatalogTest extends ServiceNowTestSupport {
-    @Produce(uri = "direct:servicenow")
-    ProducerTemplate template;
-
-    @Test
-    public void testRetrieveServiceCatalogsAndCategories() throws Exception {
-        List<Map> result1 = template.requestBodyAndHeaders(
-            "direct:servicenow",
-            null,
-            kvBuilder()
-                .put(ServiceNowConstants.RESOURCE, ServiceNowConstants.RESOURCE_SERVICE_CATALOG)
-                .put(ServiceNowConstants.ACTION, ServiceNowConstants.ACTION_RETRIEVE)
-                .build(),
-            List.class
-        );
-
-        assertFalse(result1.isEmpty());
-
-        List<Map> result2 = template.requestBodyAndHeaders(
-            "direct:servicenow",
-            null,
-            kvBuilder()
-                .put(ServiceNowConstants.RESOURCE, ServiceNowConstants.RESOURCE_SERVICE_CATALOG)
-                .put(ServiceNowConstants.ACTION, ServiceNowConstants.ACTION_RETRIEVE)
-                .put(ServiceNowConstants.ACTION_SUBJECT, ServiceNowConstants.ACTION_SUBJECT_CATEGORIES)
-                .put(ServiceNowParams.PARAM_SYS_ID, result1.get(0).get("sys_id"))
-                .build(),
-            List.class
-        );
-
-        assertFalse(result2.isEmpty());
-    }
-
-    @Test(expected = CamelExecutionException.class)
-    public void testWrongSubject() throws Exception {
-        List<Map> result = template.requestBodyAndHeaders(
-            "direct:servicenow",
-            null,
-            kvBuilder()
-                .put(ServiceNowConstants.RESOURCE, ServiceNowConstants.RESOURCE_SERVICE_CATALOG)
-                .put(ServiceNowConstants.ACTION, ServiceNowConstants.ACTION_RETRIEVE)
-                .put(ServiceNowConstants.ACTION_SUBJECT, "Invalid")
-                .build(),
-            List.class
-        );
-
-        assertFalse(result.isEmpty());
-    }
-
-    // *************************************************************************
-    //
-    // *************************************************************************
-
-    @Override
-    protected RouteBuilder createRouteBuilder() throws Exception {
-        return new RouteBuilder() {
-            public void configure() {
-                from("direct:servicenow")
-                    .to("servicenow:{{env:SERVICENOW_INSTANCE}}")
-                    .to("log:org.apache.camel.component.servicenow?level=INFO&showAll=true")
-                    .to("mock:servicenow");
-            }
-        };
-    }
-}


[18/19] camel git commit: CAMEL-11555: ServiceNow : create a maven plugin to generate models based on table layout

Posted by lb...@apache.org.
http://git-wip-us.apache.org/repos/asf/camel/blob/109da7c9/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/ServiceNowConfiguration.java
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/ServiceNowConfiguration.java b/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/ServiceNowConfiguration.java
new file mode 100644
index 0000000..bc46bcb
--- /dev/null
+++ b/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/ServiceNowConfiguration.java
@@ -0,0 +1,689 @@
+/**
+ * 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.servicenow;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.databind.DeserializationFeature;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+import org.apache.camel.RuntimeCamelException;
+import org.apache.camel.spi.Metadata;
+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;
+import org.apache.cxf.configuration.security.ProxyAuthorizationPolicy;
+import org.apache.cxf.transports.http.configuration.HTTPClientPolicy;
+
+@UriParams
+public class ServiceNowConfiguration implements Cloneable {
+
+    private static final ObjectMapper MAPPER = new ObjectMapper()
+        .configure(
+            DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES,
+            false)
+        .setSerializationInclusion(
+            JsonInclude.Include.NON_NULL
+        );
+
+    @UriParam(label = "security", secret = true)
+    @Metadata(required = "true")
+    private String userName;
+    @UriParam(label = "security", secret = true)
+    @Metadata(required = "true")
+    private String password;
+    @UriParam(label = "security", secret = true)
+    private String oauthClientId;
+    @UriParam(label = "security", secret = true)
+    private String oauthClientSecret;
+    @UriParam(label = "security", secret = true)
+    private String oauthTokenUrl;
+    @UriParam(label = "security")
+    private String apiUrl;
+    @UriParam(label = "advanced")
+    private String apiVersion;
+    @UriParam
+    private String resource;
+    @UriParam
+    private String table;
+    @UriParam
+    private Boolean excludeReferenceLink = false;
+    @UriParam
+    private Boolean suppressAutoSysField = false;
+    @UriParam
+    private Boolean includeScores = false;
+    @UriParam
+    private Boolean includeAggregates = false;
+    @UriParam
+    private Boolean includeAvailableBreakdowns = false;
+    @UriParam
+    private Boolean includeAvailableAggregates = false;
+    @UriParam
+    private Boolean includeScoreNotes = false;
+    @UriParam
+    private Boolean topLevelOnly;
+    @UriParam
+    private Boolean favorites;
+    @UriParam(label = "advanced", defaultValue = "false")
+    private Boolean retrieveTargetRecordOnImport = false;
+    @UriParam
+    private Boolean key;
+    @UriParam
+    private Boolean target;
+    @UriParam(defaultValue = "true", enums = "false,true,all")
+    private String display = "true";
+    @UriParam(defaultValue = "10")
+    private Integer perPage = 10;
+    @UriParam(enums = "value,change,changeperc,gap,gapperc,duedate,name,order,default,group,indicator_group,frequency,target,date,trend,bullet,direction")
+    private String sortBy;
+    @UriParam(enums = "asc,desc")
+    private String sortDir;
+    @UriParam
+    private Boolean suppressPaginationHeader = false;
+    @UriParam(defaultValue = "false", enums = "false,true,all")
+    private String displayValue = "false";
+    @UriParam
+    private Boolean inputDisplayValue = false;
+    @UriParam(prefix = "model.", multiValue = true, javaType = "java.lang.String", description = "Defines both request and response models")
+    private transient Map<String, Class<?>> models; // field not in use as its a shortcut for both requestModels/responseModels
+    @UriParam(prefix = "request-model.", multiValue = true, javaType = "java.lang.String")
+    private Map<String, Class<?>> requestModels;
+    @UriParam(prefix = "response-model.", multiValue = true, javaType = "java.lang.String")
+    private Map<String, Class<?>> responseModels;
+    @UriParam(label = "advanced")
+    private ObjectMapper mapper = MAPPER;
+    @UriParam(defaultValue = "HELSINKI", enums = "FUJI,GENEVA,HELSINKI")
+    private ServiceNowRelease release = ServiceNowRelease.HELSINKI;
+    @UriParam(label = "security")
+    private SSLContextParameters sslContextParameters;
+    @UriParam(label = "advanced")
+    private HTTPClientPolicy httpClientPolicy;
+    @UriParam(label = "advanced")
+    private ProxyAuthorizationPolicy proxyAuthorizationPolicy;
+    @UriParam(label = "proxy")
+    private String proxyHost;
+    @UriParam(label = "proxy")
+    private Integer proxyPort;
+    @UriParam(label = "proxy,security")
+    private String proxyUserName;
+    @UriParam(label = "proxy,security")
+    private String proxyPassword;
+
+    public String getUserName() {
+        return userName;
+    }
+
+    public String getApiUrl() {
+        return apiUrl;
+    }
+
+    /**
+     * The ServiceNow REST API url
+     */
+    public void setApiUrl(String apiUrl) {
+        this.apiUrl = apiUrl;
+    }
+
+    public boolean hasApiUrl() {
+        return apiUrl != null;
+    }
+
+    public String getApiVersion() {
+        return apiVersion;
+    }
+
+    /**
+     * The ServiceNow REST API version, default latest
+     */
+    public void setApiVersion(String apiVersion) {
+        this.apiVersion = apiVersion;
+    }
+
+    /**
+     * ServiceNow user account name, MUST be provided
+     */
+    public void setUserName(String userName) {
+        this.userName = userName;
+    }
+
+    public String getPassword() {
+        return password;
+    }
+
+    /**
+     * ServiceNow account password, MUST be provided
+     */
+    public void setPassword(String password) {
+        this.password = password;
+    }
+
+    public String getOauthClientId() {
+        return oauthClientId;
+    }
+
+    /**
+     * OAuth2 ClientID
+     */
+    public void setOauthClientId(String oauthClientId) {
+        this.oauthClientId = oauthClientId;
+    }
+
+    public String getOauthClientSecret() {
+        return oauthClientSecret;
+    }
+
+    /**
+     * OAuth2 ClientSecret
+     */
+    public void setOauthClientSecret(String oauthClientSecret) {
+        this.oauthClientSecret = oauthClientSecret;
+    }
+
+    public String getOauthTokenUrl() {
+        return oauthTokenUrl;
+    }
+
+    public boolean hasOauthTokenUrl() {
+        return oauthTokenUrl != null;
+    }
+
+    /**
+     * OAuth token Url
+     */
+    public void setOauthTokenUrl(String oauthTokenUrl) {
+        this.oauthTokenUrl = oauthTokenUrl;
+    }
+
+    public boolean hasBasicAuthentication() {
+        return ObjectHelper.isNotEmpty(userName)
+            && ObjectHelper.isNotEmpty(password);
+    }
+
+    public boolean hasOAuthAuthentication() {
+        return ObjectHelper.isNotEmpty(userName)
+            && ObjectHelper.isNotEmpty(password)
+            && ObjectHelper.isNotEmpty(oauthClientId)
+            && ObjectHelper.isNotEmpty(oauthClientSecret);
+    }
+
+    public String getResource() {
+        return resource;
+    }
+
+    /**
+     * The default resource, can be overridden by header CamelServiceNowResource
+     */
+    public void setResource(String resource) {
+        this.resource = resource;
+    }
+
+    public String getTable() {
+        return table;
+    }
+
+    /**
+     * The default table, can be overridden by header CamelServiceNowTable
+     */
+    public void setTable(String table) {
+        this.table = table;
+    }
+
+    public Boolean getExcludeReferenceLink() {
+        return excludeReferenceLink;
+    }
+
+    /**
+     * True to exclude Table API links for reference fields (default: false)
+     */
+    public void setExcludeReferenceLink(Boolean excludeReferenceLink) {
+        this.excludeReferenceLink = excludeReferenceLink;
+    }
+
+    public Boolean getSuppressAutoSysField() {
+        return suppressAutoSysField;
+    }
+
+    /**
+     * True to suppress auto generation of system fields (default: false)
+     */
+    public void setSuppressAutoSysField(Boolean suppressAutoSysField) {
+        this.suppressAutoSysField = suppressAutoSysField;
+    }
+
+    public Boolean getSuppressPaginationHeader() {
+        return suppressPaginationHeader;
+    }
+
+    /**
+     * Set this value to true to remove the Link header from the response. The
+     * Link header allows you to request additional pages of data when the number
+     * of records matching your query exceeds the query limit
+     */
+    public void setSuppressPaginationHeader(Boolean suppressPaginationHeader) {
+        this.suppressPaginationHeader = suppressPaginationHeader;
+    }
+
+    public Boolean getIncludeScores() {
+        return includeScores;
+    }
+
+    /**
+     * Set this parameter to true to return all scores for a scorecard. If a value
+     * is not specified, this parameter defaults to false and returns only the most
+     * recent score value.
+     */
+    public void setIncludeScores(Boolean includeScores) {
+        this.includeScores = includeScores;
+    }
+
+    public Boolean getIncludeAggregates() {
+        return includeAggregates;
+    }
+
+    /**
+     * Set this parameter to true to always return all available aggregates for
+     * an indicator, including when an aggregate has already been applied. If a
+     * value is not specified, this parameter defaults to false and returns no
+     * aggregates.
+     */
+    public void setIncludeAggregates(Boolean includeAggregates) {
+        this.includeAggregates = includeAggregates;
+    }
+
+    public Boolean getIncludeAvailableBreakdowns() {
+        return includeAvailableBreakdowns;
+    }
+
+    /**
+     * Set this parameter to true to return all available breakdowns for an indicator.
+     * If a value is not specified, this parameter defaults to false and returns
+     * no breakdowns.
+     */
+    public void setIncludeAvailableBreakdowns(Boolean includeAvailableBreakdowns) {
+        this.includeAvailableBreakdowns = includeAvailableBreakdowns;
+    }
+
+    public Boolean getIncludeAvailableAggregates() {
+        return includeAvailableAggregates;
+    }
+
+    /**
+     * Set this parameter to true to return all available aggregates for an indicator
+     * when no aggregate has been applied. If a value is not specified, this parameter
+     * defaults to false and returns no aggregates.
+     */
+    public void setIncludeAvailableAggregates(Boolean includeAvailableAggregates) {
+        this.includeAvailableAggregates = includeAvailableAggregates;
+    }
+
+    public Boolean getIncludeScoreNotes() {
+        return includeScoreNotes;
+    }
+
+    /**
+     * Set this parameter to true to return all notes associated with the score.
+     * The note element contains the note text as well as the author and timestamp
+     * when the note was added.
+     */
+    public void setIncludeScoreNotes(Boolean includeScoreNotes) {
+        this.includeScoreNotes = includeScoreNotes;
+    }
+
+    public Boolean getFavorites() {
+        return favorites;
+    }
+
+    /**
+     * Set this parameter to true to return only scorecards that are favorites of
+     * the querying user.
+     */
+    public void setFavorites(Boolean favorites) {
+        this.favorites = favorites;
+    }
+
+    public Boolean getRetrieveTargetRecordOnImport() {
+        return retrieveTargetRecordOnImport;
+    }
+
+    /**
+     * Set this parameter to true to retrieve the target record when using import
+     * set api. The import set result is then replaced by the target record
+     */
+    public void setRetrieveTargetRecordOnImport(Boolean retrieveTargetRecordOnImport) {
+        this.retrieveTargetRecordOnImport = retrieveTargetRecordOnImport;
+    }
+
+    public Boolean getKey() {
+        return key;
+    }
+
+    /**
+     * Set this parameter to true to return only scorecards for key indicators.
+     */
+    public void setKey(Boolean key) {
+        this.key = key;
+    }
+
+    public Boolean getTarget() {
+        return target;
+    }
+
+    /**
+     * Set this parameter to true to return only scorecards that have a target.
+     */
+    public void setTarget(Boolean target) {
+        this.target = target;
+    }
+
+    public String getDisplay() {
+        return display;
+    }
+
+    /**
+     * Set this parameter to true to return only scorecards where the indicator
+     * Display field is selected. Set this parameter to all to return scorecards
+     * with any Display field value. This parameter is true by default.
+     */
+    public void setDisplay(String display) {
+        this.display = display;
+    }
+
+    public Integer getPerPage() {
+        return perPage;
+    }
+
+    /**
+     * Enter the maximum number of scorecards each query can return. By default
+     * this value is 10, and the maximum is 100.
+     */
+    public void setPerPage(Integer perPage) {
+        this.perPage = perPage;
+    }
+
+    public String getSortBy() {
+        return sortBy;
+    }
+
+    /**
+     * Specify the value to use when sorting results. By default, queries sort
+     * records by value.
+     */
+    public void setSortBy(String sortBy) {
+        this.sortBy = sortBy;
+    }
+
+    public String getSortDir() {
+        return sortDir;
+    }
+
+    /**
+     * Specify the sort direction, ascending or descending. By default, queries
+     * sort records in descending order. Use sysparm_sortdir=asc to sort in
+     * ascending order.
+     */
+    public void setSortDir(String sortDir) {
+        this.sortDir = sortDir;
+    }
+
+    public String getDisplayValue() {
+        return displayValue;
+    }
+
+    /**
+     * Return the display value (true), actual value (false), or both (all) for
+     * reference fields (default: false)
+     */
+    public void setDisplayValue(String displayValue) {
+        this.displayValue = displayValue;
+    }
+
+    public Boolean getInputDisplayValue() {
+        return inputDisplayValue;
+    }
+
+    /**
+     * True to set raw value of input fields (default: false)
+     */
+    public void setInputDisplayValue(Boolean inputDisplayValue) {
+        this.inputDisplayValue = inputDisplayValue;
+    }
+
+    public Map<String, Class<?>> getRequestModels() {
+        return requestModels;
+    }
+
+    /**
+     * Sets Jackson's ObjectMapper to use for request/reply
+     */
+    public void setMapper(ObjectMapper mapper) {
+        this.mapper = mapper;
+    }
+
+    public ObjectMapper getMapper() {
+        return mapper;
+    }
+
+    public boolean hasMapper() {
+        return mapper != null;
+    }
+
+    /**
+     * The ServiceNow release to target, default to Helsinki
+     *
+     * See https://docs.servicenow.com
+     */
+    public void setRelease(ServiceNowRelease release) {
+        this.release = release;
+    }
+
+    public ServiceNowRelease getRelease() {
+        return release;
+    }
+
+    public Boolean getTopLevelOnly() {
+        return topLevelOnly;
+    }
+
+    /**
+     * Gets only those categories whose parent is a catalog.
+     */
+    public void setTopLevelOnly(Boolean topLevelOnly) {
+        this.topLevelOnly = topLevelOnly;
+    }
+
+    public SSLContextParameters getSslContextParameters() {
+        return sslContextParameters;
+    }
+
+    /**
+     * To configure security using SSLContextParameters. See http://camel.apache.org/camel-configuration-utilities.html
+     */
+    public void setSslContextParameters(SSLContextParameters sslContextParameters) {
+        this.sslContextParameters = sslContextParameters;
+    }
+
+    public HTTPClientPolicy getHttpClientPolicy() {
+        return httpClientPolicy;
+    }
+
+    /**
+     * To configure http-client
+     */
+    public void setHttpClientPolicy(HTTPClientPolicy httpClientPolicy) {
+        this.httpClientPolicy = httpClientPolicy;
+    }
+
+    public ProxyAuthorizationPolicy getProxyAuthorizationPolicy() {
+        return proxyAuthorizationPolicy;
+    }
+
+    /**
+     * To configure proxy authentication
+     */
+    public void setProxyAuthorizationPolicy(ProxyAuthorizationPolicy proxyAuthorizationPolicy) {
+        this.proxyAuthorizationPolicy = proxyAuthorizationPolicy;
+    }
+
+    public String getProxyHost() {
+        return proxyHost;
+    }
+
+    /**
+     * The proxy host name
+     */
+    public void setProxyHost(String proxyHost) {
+        this.proxyHost = proxyHost;
+    }
+
+    public Integer getProxyPort() {
+        return proxyPort;
+    }
+
+    /**
+     * The proxy port number
+     */
+    public void setProxyPort(Integer proxyPort) {
+        this.proxyPort = proxyPort;
+    }
+
+    public String getProxyUserName() {
+        return proxyUserName;
+    }
+
+    /**
+     * Username for proxy authentication
+     */
+    public void setProxyUserName(String proxyUserName) {
+        this.proxyUserName = proxyUserName;
+    }
+
+    public String getProxyPassword() {
+        return proxyPassword;
+    }
+
+    /**
+     * Password for proxy authentication
+     */
+    public void setProxyPassword(String proxyPassword) {
+        this.proxyPassword = proxyPassword;
+    }
+
+    // *************************************************
+    //
+    // *************************************************
+
+    public void setModels(Map<String, Class<?>> models) {
+        setRequestModels(models);
+        setResponseModels(models);
+    }
+
+    public void addModel(String name, Class<?> type) {
+        addRequestModel(name, type);
+        addResponseModel(name, type);
+    }
+
+    // *************************************************
+    // Request model
+    // *************************************************
+
+    /**
+     * Defines the request model
+     */
+    public void setRequestModels(Map<String, Class<?>> models) {
+        if (this.requestModels == null) {
+            this.requestModels = new HashMap<>();
+        }
+
+        this.requestModels.clear();
+        this.requestModels.putAll(models);
+    }
+
+    public void addRequestModel(String name, Class<?> type) {
+        if (this.requestModels == null) {
+            this.requestModels = new HashMap<>();
+        }
+
+        this.requestModels.put(name, type);
+    }
+
+    public Class<?> getRequestModel(String name) {
+        return getRequestModel(name, null);
+    }
+
+    public Class<?> getRequestModel(String name, Class<?> defaultType) {
+        Class<?> model = defaultType;
+
+        if (this.requestModels != null && this.requestModels.containsKey(name)) {
+            model = this.requestModels.get(name);
+        }
+
+        return model;
+    }
+
+    // *************************************************
+    // Response model
+    // *************************************************
+
+    /**
+     * Defines the response model
+     */
+    public void setResponseModels(Map<String, Class<?>> models) {
+        if (this.responseModels == null) {
+            this.responseModels = new HashMap<>();
+        }
+
+        this.responseModels.putAll(models);
+    }
+
+    public void addResponseModel(String name, Class<?> type) {
+        if (this.responseModels == null) {
+            this.responseModels = new HashMap<>();
+        }
+
+        this.responseModels.clear();
+        this.responseModels.put(name, type);
+    }
+
+    public Class<?> getResponseModel(String name) {
+        return getResponseModel(name, null);
+    }
+
+    public Class<?> getResponseModel(String name, Class<?> defaultType) {
+        Class<?> model = defaultType;
+
+        if (this.responseModels != null && this.responseModels.containsKey(name)) {
+            model = this.responseModels.get(name);
+        }
+
+        return model;
+    }
+
+    // *************************************************
+    //
+    // *************************************************
+
+    public ServiceNowConfiguration copy() {
+        try {
+            return (ServiceNowConfiguration)super.clone();
+        } catch (CloneNotSupportedException e) {
+            throw new RuntimeCamelException(e);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/109da7c9/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
new file mode 100644
index 0000000..b967bbe
--- /dev/null
+++ b/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/ServiceNowConstants.java
@@ -0,0 +1,80 @@
+/**
+ * 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.servicenow;
+
+public final class ServiceNowConstants {
+    public static final String CAMEL_HEADER_PREFIX = "CamelServiceNow";
+
+    public static final String RESOURCE = "CamelServiceNowResource";
+    public static final String ACTION = "CamelServiceNowAction";
+    public static final String ACTION_SUBJECT = "CamelServiceNowActionSubject";
+    public static final String MODEL = "CamelServiceNowModel";
+    public static final String REQUEST_MODEL = "CamelServiceNowRequestModel";
+    public static final String RESPONSE_MODEL = "CamelServiceNowResponseModel";
+    public static final String OFFSET_NEXT = "CamelServiceNowOffsetNext";
+    public static final String OFFSET_PREV = "CamelServiceNowOffsetPrev";
+    public static final String OFFSET_FIRST = "CamelServiceNowOffsetFirst";
+    public static final String OFFSET_LAST = "CamelServiceNowOffsetLast";
+    public static final String CONTENT_TYPE = "CamelServiceNowContentType";
+    public static final String CONTENT_ENCODING = "CamelServiceNowContentEncoding";
+    public static final String CONTENT_META = "CamelServiceNowContentMeta";
+    public static final String RESPONSE_META = "CamelServiceNowResponseMeta";
+    public static final String API_VERSION = "CamelServiceNowApiVersion";
+    public static final String RESPONSE_TYPE = "CamelServiceNowResponseType";
+    public static final String RETRIEVE_TARGET_RECORD = "CamelServiceNowRetrieveTargetRecord";
+
+    public static final String ATTACHMENT_META_HEADER = "X-Attachment-Metadata";
+
+    public static final String RESOURCE_TABLE = "table";
+    public static final String RESOURCE_AGGREGATE = "aggregate";
+    public static final String RESOURCE_IMPORT = "import";
+    public static final String RESOURCE_ATTACHMENT = "attachment";
+    public static final String RESOURCE_SCORECARDS = "scorecards";
+    public static final String RESOURCE_MISC = "misc";
+    public static final String RESOURCE_SERVICE_CATALOG = "service_catalog";
+    public static final String RESOURCE_SERVICE_CATALOG_ITEMS = "service_catalog_items";
+    public static final String RESOURCE_SERVICE_CATALOG_CARTS = "service_catalog_cart";
+    public static final String RESOURCE_SERVICE_CATALOG_CATEGORIES = "service_catalog_categories";
+
+    public static final String ACTION_RETRIEVE = "retrieve";
+    public static final String ACTION_CONTENT = "content";
+    public static final String ACTION_CREATE = "create";
+    public static final String ACTION_MODIFY = "modify";
+    public static final String ACTION_DELETE = "delete";
+    public static final String ACTION_UPDATE = "update";
+    public static final String ACTION_UPLOAD = "upload";
+
+    public static final String ACTION_SUBJECT_CATEGORIES = "categories";
+    public static final String ACTION_SUBJECT_CART = "cart";
+    public static final String ACTION_SUBJECT_PRODUCER = "producer";
+    public static final String ACTION_SUBJECT_GUIDE = "guide";
+    public static final String ACTION_SUBJECT_SUBMIT_GUIDE = "submit_guide";
+    public static final String ACTION_SUBJECT_CHECKOUT_GUIDE = "checkout_guide";
+    public static final String ACTION_SUBJECT_PERFORMANCE_ANALYTICS = "performance_analytics";
+    public static final String ACTION_SUBJECT_USER_ROLE_INHERITANCE = "user_role_inheritance";
+    public static final String ACTION_SUBJECT_IDENTIFY_RECONCILE = "identify_reconcile";
+    public static final String ACTION_SUBJECT_DELIVERY_ADDRESS = "delivery_address";
+    public static final String ACTION_SUBJECT_CHECKOUT = "checkout";
+
+    public static final String LINK_NEXT = "next";
+    public static final String LINK_PREV = "prev";
+    public static final String LINK_FIRST = "first";
+    public static final String LINK_LAST = "last";
+
+    private ServiceNowConstants() {
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/109da7c9/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/ServiceNowDispatcher.java
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/ServiceNowDispatcher.java b/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/ServiceNowDispatcher.java
new file mode 100644
index 0000000..e3a0473
--- /dev/null
+++ b/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/ServiceNowDispatcher.java
@@ -0,0 +1,55 @@
+/**
+ * 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.servicenow;
+
+import java.util.function.Predicate;
+
+import org.apache.camel.Exchange;
+import org.apache.camel.Message;
+import org.apache.camel.Processor;
+import org.apache.camel.util.ObjectHelper;
+
+public class ServiceNowDispatcher {
+    private final Predicate<Exchange> predicate;
+    private final Processor delegate;
+
+    public ServiceNowDispatcher(Predicate<Exchange> predicate, Processor delegate) {
+        this.predicate = ObjectHelper.notNull(predicate, "predicate");
+        this.delegate = ObjectHelper.notNull(delegate, "delegate");
+    }
+
+    public boolean match(Exchange exchange) {
+        return predicate.test(exchange);
+    }
+
+    public void process(Exchange exchange) throws Exception {
+        delegate.process(exchange);
+    }
+
+    // ********************
+    // Helpers
+    // ********************
+
+    public static ServiceNowDispatcher on(final String action, final String subject, final Processor delegate) {
+        return new ServiceNowDispatcher(e -> matches(e.getIn(), action, subject), delegate);
+    }
+
+    public static boolean matches(Message in, String action, final String subject) {
+        return ObjectHelper.equal(action, in.getHeader(ServiceNowConstants.ACTION, String.class), true)
+            && ObjectHelper.equal(subject, in.getHeader(ServiceNowConstants.ACTION_SUBJECT, String.class), true);
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/109da7c9/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/ServiceNowEndpoint.java
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/ServiceNowEndpoint.java b/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/ServiceNowEndpoint.java
new file mode 100644
index 0000000..dcf3563
--- /dev/null
+++ b/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/ServiceNowEndpoint.java
@@ -0,0 +1,80 @@
+/**
+ * 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.servicenow;
+
+import org.apache.camel.Consumer;
+import org.apache.camel.Processor;
+import org.apache.camel.Producer;
+import org.apache.camel.impl.DefaultEndpoint;
+import org.apache.camel.spi.Metadata;
+import org.apache.camel.spi.UriEndpoint;
+import org.apache.camel.spi.UriParam;
+import org.apache.camel.spi.UriPath;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * The servicenow component is used to integrate Camel with <a href="http://www.servicenow.com/">ServiceNow</a> cloud services.
+ */
+@UriEndpoint(firstVersion = "2.18.0", scheme = "servicenow", title = "ServiceNow", syntax = "servicenow:instanceName", producerOnly = true, label = "api,cloud,management")
+public class ServiceNowEndpoint extends DefaultEndpoint {
+    private static final Logger LOGGER = LoggerFactory.getLogger(ServiceNowEndpoint.class);
+
+    @UriPath(description = "The ServiceNow instance name")
+    @Metadata(required = "true")
+    private final String instanceName;
+
+    @UriParam
+    private final ServiceNowConfiguration configuration;
+
+    public ServiceNowEndpoint(String uri, ServiceNowComponent component, ServiceNowConfiguration configuration, String instanceName) throws Exception {
+        super(uri, component);
+
+        this.configuration = configuration;
+        this.instanceName = instanceName;
+    }
+
+    @Override
+    public Producer createProducer() throws Exception {
+        ServiceNowProducer producer = configuration.getRelease().get(this);
+        LOGGER.info("Producer for ServiceNow Rel. {} = {}/{}",
+            configuration.getRelease().name(),
+            producer.getRelease().name(),
+            producer.getClass().getName()
+        );
+
+        return producer;
+    }
+
+    @Override
+    public Consumer createConsumer(Processor processor) throws Exception {
+        throw new UnsupportedOperationException("Consumer is not supported");
+    }
+
+    @Override
+    public boolean isSingleton() {
+        return true;
+    }
+
+    public ServiceNowConfiguration getConfiguration() {
+        return configuration;
+    }
+
+    public String getInstanceName() {
+        return instanceName;
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/109da7c9/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/ServiceNowException.java
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/ServiceNowException.java b/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/ServiceNowException.java
new file mode 100644
index 0000000..6a5e0a9
--- /dev/null
+++ b/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/ServiceNowException.java
@@ -0,0 +1,69 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.servicenow;
+
+import java.util.Collections;
+import java.util.Map;
+
+import org.apache.camel.CamelException;
+
+public class ServiceNowException extends CamelException {
+    private final Integer code;
+    private final String status;
+    private final String detail;
+    private final Map<Object, Object> attributes;
+
+    public ServiceNowException(Integer code, String status, String message, String detail) {
+        super(message);
+        this.code = code;
+        this.status = status;
+        this.detail = detail;
+        this.attributes = Collections.emptyMap();
+    }
+
+    public ServiceNowException(Integer code, Map<Object, Object> attributes) {
+        super(String.format("Status (%d)", code));
+        this.code = code;
+        this.status = null;
+        this.detail = null;
+        this.attributes = Collections.unmodifiableMap(attributes);
+    }
+
+    public Integer getCode() {
+        return code;
+    }
+
+    public String getStatus() {
+        return status;
+    }
+
+    public String getDetail() {
+        return detail;
+    }
+
+    public Map<Object, Object> getAttributes() {
+        return attributes;
+    }
+
+    @Override
+    public String toString() {
+        return getMessage() != null
+            ? "" + this.status + ": " + getMessage()
+            : super.toString();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/109da7c9/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/ServiceNowExceptionModel.java
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/ServiceNowExceptionModel.java b/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/ServiceNowExceptionModel.java
new file mode 100644
index 0000000..a881d4a
--- /dev/null
+++ b/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/ServiceNowExceptionModel.java
@@ -0,0 +1,43 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.servicenow;
+
+import java.util.Map;
+
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+@JsonIgnoreProperties(ignoreUnknown = true)
+public final class ServiceNowExceptionModel {
+    private final String status;
+    private final Map<String, String> error;
+
+    public ServiceNowExceptionModel(
+        @JsonProperty("status") String status,
+        @JsonProperty("error") Map<String, String> error) {
+        this.status = status;
+        this.error = error;
+    }
+
+    public String getStatus() {
+        return status;
+    }
+
+    public Map<String, String> getError() {
+        return error;
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/109da7c9/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/ServiceNowHelper.java
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/ServiceNowHelper.java b/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/ServiceNowHelper.java
new file mode 100644
index 0000000..2d9b70e
--- /dev/null
+++ b/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/ServiceNowHelper.java
@@ -0,0 +1,95 @@
+/**
+ * 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.servicenow;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.function.BiConsumer;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.Response;
+
+import org.apache.camel.util.StringHelper;
+import org.apache.camel.util.URISupport;
+
+public final class ServiceNowHelper {
+    private ServiceNowHelper() {
+    }
+
+    public static void findOffsets(Response response, BiConsumer<String, Object> consumer) throws Exception {
+        List<String> links = response.getStringHeaders().get(HttpHeaders.LINK);
+        if (links != null) {
+            for (String link : links) {
+                String[] parts = link.split(";");
+                if (parts.length != 2) {
+                    continue;
+                }
+
+                // Sanitize parts
+                String uri = StringHelper.between(parts[0], "<", ">");
+                String rel = StringHelper.removeQuotes(StringHelper.after(parts[1], "="));
+
+                Map<String, Object> query = URISupport.parseQuery(uri);
+                Object offset = query.get(ServiceNowParams.SYSPARM_OFFSET.getId());
+
+                if (offset != null) {
+                    switch (rel) {
+                    case ServiceNowConstants.LINK_FIRST:
+                        consumer.accept(ServiceNowConstants.OFFSET_FIRST, offset);
+                        break;
+                    case ServiceNowConstants.LINK_LAST:
+                        consumer.accept(ServiceNowConstants.OFFSET_LAST, offset);
+                        break;
+                    case ServiceNowConstants.LINK_NEXT:
+                        consumer.accept(ServiceNowConstants.OFFSET_NEXT, offset);
+                        break;
+                    case ServiceNowConstants.LINK_PREV:
+                        consumer.accept(ServiceNowConstants.OFFSET_PREV, offset);
+                        break;
+                    default:
+                        break;
+                    }
+                }
+            }
+        }
+    }
+
+    public static Optional<String> findOffset(Response response, String type) throws Exception {
+        List<String> links = response.getStringHeaders().get(HttpHeaders.LINK);
+        if (links != null) {
+            for (String link : links) {
+                String[] parts = link.split(";");
+                if (parts.length != 2) {
+                    continue;
+                }
+
+                // Sanitize parts
+                String uri = StringHelper.between(parts[0], "<", ">");
+                String rel = StringHelper.removeQuotes(StringHelper.after(parts[1], "="));
+
+                Map<String, Object> query = URISupport.parseQuery(uri);
+                Object offset = query.get(ServiceNowParams.SYSPARM_OFFSET.getId());
+
+                if (offset != null && type.equals(rel)) {
+                    return Optional.of(offset.toString());
+                }
+            }
+        }
+
+        return Optional.empty();
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/109da7c9/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/ServiceNowMetaDataExtension.java
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/ServiceNowMetaDataExtension.java b/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/ServiceNowMetaDataExtension.java
new file mode 100644
index 0000000..b946438
--- /dev/null
+++ b/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/ServiceNowMetaDataExtension.java
@@ -0,0 +1,478 @@
+/**
+ * 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.servicenow;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.Stack;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import java.util.function.Consumer;
+import java.util.regex.Pattern;
+import java.util.stream.Stream;
+import javax.ws.rs.HttpMethod;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import org.apache.camel.RuntimeCamelException;
+import org.apache.camel.component.extension.MetaDataExtension;
+import org.apache.camel.component.extension.metadata.AbstractMetaDataExtension;
+import org.apache.camel.component.extension.metadata.MetaDataBuilder;
+import org.apache.camel.component.servicenow.model.DictionaryEntry;
+import org.apache.camel.util.IntrospectionSupport;
+import org.apache.camel.util.ObjectHelper;
+import org.apache.camel.util.StringHelper;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * An implementation of the MetaData extension {@link MetaDataExtension} that
+ * retrieve information about ServiceNow objects as Json Schema as per draft-04
+ * specs.
+ */
+final class ServiceNowMetaDataExtension extends AbstractMetaDataExtension {
+    private static final Logger LOGGER = LoggerFactory.getLogger(ServiceNowMetaDataExtension.class);
+    private final ConcurrentMap<String, String> properties;
+
+    ServiceNowMetaDataExtension() {
+        this.properties = new ConcurrentHashMap<>();
+    }
+
+    @Override
+    public Optional<MetaDataExtension.MetaData> meta(Map<String, Object> parameters) {
+        try {
+            final MetaContext context = new MetaContext(parameters);
+
+            if (!ObjectHelper.equalIgnoreCase(context.getObjectType(), "table")) {
+                throw new UnsupportedOperationException("Unsupported object type <" + context.getObjectType() + ">");
+            }
+
+            return tableMeta(context);
+
+        } catch (UnsupportedOperationException e) {
+            throw e;
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    private Optional<MetaDataExtension.MetaData> tableMeta(MetaContext context) {
+        try {
+            final List<String> names = getObjectHierarchy(context);
+            final ObjectNode root = context.getConfiguration().getMapper().createObjectNode();
+            final String baseUrn = (String)context.getParameters().getOrDefault("baseUrn", "org:apache:camel:component:servicenow");
+
+            if (names.isEmpty()) {
+                return Optional.empty();
+            }
+
+            // Schema
+            root.put("$schema", "http://json-schema.org/draft-04/schema#");
+            root.put("id", String.format("urn:jsonschema:%s:%s)", baseUrn, context.getObjectName()));
+            root.put("type", "object");
+            root.put("additionalProperties", false);
+
+            // Schema sections
+            root.putObject("properties");
+            root.putArray("required");
+            root.putObject("definitions");
+
+            loadProperties(context);
+            registerDefinitions(context, root);
+
+            for (String name : names) {
+                context.getStack().push(name);
+
+                LOGGER.debug("Load dictionary <{}>", context.getStack());
+                loadDictionary(context, name, root);
+                context.getStack().pop();
+            }
+
+            return Optional.of(
+                MetaDataBuilder.on(getCamelContext())
+                    .withAttribute(MetaData.CONTENT_TYPE, "application/schema+json")
+                    .withAttribute(MetaData.JAVA_TYPE, JsonNode.class)
+                    .withPayload(root)
+                    .build()
+            );
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    // ********************************
+    // Properties
+    // ********************************
+
+    private synchronized void loadProperties(MetaContext context) {
+        if (!properties.isEmpty()) {
+            return;
+        }
+
+        try {
+            String offset = "0";
+
+            while (true) {
+                Response response = context.getClient().reset()
+                    .types(MediaType.APPLICATION_JSON_TYPE)
+                    .path("now")
+                    .path(context.getConfiguration().getApiVersion())
+                    .path("table")
+                    .path("sys_properties")
+                    .query("sysparm_exclude_reference_link", "true")
+                    .query("sysparm_fields", "name%2Cvalue")
+                    .query("sysparm_offset", offset)
+                    .query("sysparm_query", "name=glide.sys.date_format^ORname=glide.sys.time_format")
+                    .invoke(HttpMethod.GET);
+
+                findResultNode(response).ifPresent(node -> processResult(node, n -> {
+                    if (n.hasNonNull("name") && n.hasNonNull("value")) {
+                        properties.put(
+                            n.findValue("name").asText(),
+                            n.findValue("value").asText()
+                        );
+                    }
+                }));
+
+                Optional<String> next = ServiceNowHelper.findOffset(response, ServiceNowConstants.LINK_NEXT);
+                if (next.isPresent()) {
+                    offset = next.get();
+                } else {
+                    break;
+                }
+            }
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    // ********************************
+    // Definitions
+    // ********************************
+
+    private void registerDefinitions(MetaContext context, ObjectNode root) {
+        final ObjectNode definitions = (ObjectNode)root.get("definitions");
+
+        // Global Unique ID
+        definitions.putObject("guid")
+            .put("type", "string")
+            .put("pattern", "^[a-fA-F0-9]{32}");
+
+        // Date/Time
+        String dateFormat = properties.getOrDefault("glide.sys.date_format", "yyyy-MM-dd");
+        String timeFormat = properties.getOrDefault("glide.sys.time_format", "HH:mm:ss");
+
+        definitions.putObject("date")
+            .put("type", "string")
+            .put("format", dateFormat);
+        definitions.putObject("time")
+            .put("type", "string")
+            .put("format", timeFormat);
+        definitions.putObject("date-time")
+            .put("type", "string")
+            .put("format", dateFormat + " " + timeFormat);
+    }
+
+    // ********************************
+    // Dictionary
+    // ********************************
+
+    private void loadDictionary(MetaContext context, String name, ObjectNode root) throws Exception {
+        String offset = "0";
+
+        while (true) {
+            Response response = context.getClient().reset()
+                .types(MediaType.APPLICATION_JSON_TYPE)
+                .path("now")
+                .path(context.getConfiguration().getApiVersion())
+                .path("table")
+                .path("sys_dictionary")
+                .query("sysparm_display_value", "false")
+                .queryF("sysparm_query", "name=%s", name)
+                .query("sysparm_offset", offset)
+                .invoke(HttpMethod.GET);
+
+            findResultNode(response).ifPresent(node -> processResult(node, n -> {
+                processDictionaryNode(context, root, n);
+            }));
+
+            Optional<String> next = ServiceNowHelper.findOffset(response, ServiceNowConstants.LINK_NEXT);
+            if (next.isPresent()) {
+                offset = next.get();
+            } else {
+                break;
+            }
+        }
+    }
+
+    private void processDictionaryNode(MetaContext context, ObjectNode root, JsonNode node) {
+        if (node.hasNonNull("element")) {
+            final String id = node.get("element").asText();
+
+            if (ObjectHelper.isNotEmpty(id)) {
+                String includeKey = "object." + context.getObjectName() + ".fields";
+                String excludeKey = "object." + context.getObjectName() + ".fields.exclude.pattern";
+                String fields = (String)context.getParameters().get(includeKey);
+                String exclude = (String)context.getParameters().get(excludeKey);
+
+                boolean included = true;
+
+                if (ObjectHelper.isNotEmpty(fields) && ObjectHelper.isNotEmpty(exclude)) {
+                    boolean isIncluded = Stream.of(fields.split(",")).map(StringHelper::trimToNull).filter(Objects::nonNull).anyMatch(id::equalsIgnoreCase);
+                    boolean isExcluded = Pattern.compile(exclude).matcher(id).matches();
+
+                    // if both include/exclude list is provided check if the
+                    // fields ie either explicit included or not excluded.
+                    //
+                    // This is useful if you want to exclude all the i.e. sys_
+                    // fields but want some i.e. the sys_id to be included
+                    included = isIncluded || !isExcluded;
+                } else if (ObjectHelper.isNotEmpty(fields)) {
+                    // Only include fields that are explicit included
+                    included = Stream.of(fields.split(",")).map(StringHelper::trimToNull).filter(Objects::nonNull).anyMatch(id::equalsIgnoreCase);
+                } else if (ObjectHelper.isNotEmpty(exclude)) {
+                    // Only include fields non excluded
+                    included = !Pattern.compile(exclude).matcher(id).matches();
+                }
+
+                if (!included) {
+                    return;
+                }
+
+                context.getStack().push(id);
+                LOGGER.debug("Load dictionary element <{}>", context.getStack());
+
+                try {
+                    final DictionaryEntry entry = context.getConfiguration().getMapper().treeToValue(node, DictionaryEntry.class);
+                    final ObjectNode property = ((ObjectNode)root.get("properties")).putObject(id);
+
+                    // Add custom fields for code generation, json schema
+                    // validators are not supposed to use this extensions.
+                    final ObjectNode servicenow = property.putObject("servicenow");
+
+                    // the internal type
+                    servicenow.put("internal_type", entry.getInternalType().getValue());
+
+                    switch (entry.getInternalType().getValue()) {
+                    case "integer":
+                        property.put("type", "integer");
+                        break;
+                    case "float":
+                        property.put("type", "number");
+                        break;
+                    case "boolean":
+                        property.put("type", "boolean");
+                        break;
+                    case "guid":
+                    case "GUID":
+                        property.put("$ref", "#/definitions/guid");
+                        break;
+                    case "glide_date":
+                        property.put("$ref", "#/definitions/date");
+                        break;
+                    case "due_date":
+                    case "glide_date_time":
+                    case "glide_time":
+                    case "glide_duration":
+                        property.put("$ref", "#/definitions/date-time");
+                        break;
+                    case "reference":
+                        property.put("$ref", "#/definitions/guid");
+
+                        if (entry.getReference().getValue() != null) {
+                            // the referenced object type
+                            servicenow.put("sys_db_object", entry.getReference().getValue());
+                        }
+
+                        break;
+                    default:
+                        property.put("type", "string");
+
+                        if (entry.getMaxLength() != null) {
+                            property.put("maxLength", entry.getMaxLength());
+                        }
+                        break;
+                    }
+
+                    if (entry.isMandatory()) {
+                        ArrayNode required = (ArrayNode)root.get("required");
+                        if (required == null) {
+                            required = root.putArray("required");
+                        }
+
+                        required.add(id);
+                    }
+
+                } catch (JsonProcessingException e) {
+                    throw new RuntimeCamelException(e);
+                } finally {
+
+                    context.getStack().pop();
+                }
+            }
+        }
+    }
+
+    // *************************************
+    // Helpers
+    // *************************************
+
+    private List<String> getObjectHierarchy(MetaContext context) throws Exception {
+        List<String> hierarchy = new ArrayList<>();
+        String query = String.format("name=%s", context.getObjectName());
+
+        while (true) {
+            Optional<JsonNode> response = context.getClient().reset()
+                .types(MediaType.APPLICATION_JSON_TYPE)
+                .path("now")
+                .path(context.getConfiguration().getApiVersion())
+                .path("table")
+                .path("sys_db_object")
+                .query("sysparm_exclude_reference_link", "true")
+                .query("sysparm_fields", "name%2Csuper_class")
+                .query("sysparm_query", query)
+                .trasform(HttpMethod.GET, this::findResultNode);
+
+            if (response.isPresent()) {
+                JsonNode node = response.get();
+                JsonNode nameNode = node.findValue("name");
+                JsonNode classNode = node.findValue("super_class");
+
+                if (nameNode != null && classNode != null) {
+                    query = String.format("sys_id=%s", classNode.textValue());
+                    hierarchy.add(0, nameNode.textValue());
+                } else {
+                    break;
+                }
+            } else {
+                break;
+            }
+        }
+
+        return hierarchy;
+    }
+
+    private void processResult(JsonNode node, Consumer<JsonNode> consumer) {
+        if (node.isArray()) {
+            Iterator<JsonNode> it = node.elements();
+            while (it.hasNext()) {
+                consumer.accept(it.next());
+            }
+        } else {
+            consumer.accept(node);
+        }
+    }
+
+    private Optional<JsonNode> findResultNode(Response response) {
+        if (ObjectHelper.isNotEmpty(response.getHeaderString(HttpHeaders.CONTENT_TYPE))) {
+            JsonNode root = response.readEntity(JsonNode.class);
+            if (root != null) {
+                Iterator<Map.Entry<String, JsonNode>> fields = root.fields();
+                while (fields.hasNext()) {
+                    final Map.Entry<String, JsonNode> entry = fields.next();
+                    final String key = entry.getKey();
+                    final JsonNode node = entry.getValue();
+
+                    if (ObjectHelper.equal("result", key, true)) {
+                        return Optional.of(node);
+                    }
+                }
+            }
+        }
+
+        return Optional.empty();
+    }
+
+    // *********************************
+    // Context class
+    // *********************************
+
+    private final class MetaContext {
+        private final Map<String, Object> parameters;
+        private final ServiceNowConfiguration configuration;
+        private final ServiceNowClient client;
+        private final String instanceName;
+        private final String objectName;
+        private final String objectType;
+        private final Stack<String> stack;
+
+        MetaContext(Map<String, Object> parameters) throws Exception {
+            this.parameters = parameters;
+            this.configuration = getComponent(ServiceNowComponent.class).getConfiguration().copy();
+            this.stack = new Stack<>();
+
+            IntrospectionSupport.setProperties(configuration, new HashMap<>(parameters));
+
+            this.instanceName = (String)parameters.getOrDefault("instanceName", getComponent(ServiceNowComponent.class).getInstanceName());
+            this.objectType = (String)parameters.getOrDefault("objectType", "table");
+            this.objectName = (String)parameters.getOrDefault("objectName", configuration.getTable());
+
+            ObjectHelper.notNull(instanceName, "instanceName");
+            ObjectHelper.notNull(objectName, "objectName");
+            ObjectHelper.notNull(objectType, "objectType");
+
+            // 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));
+            }
+
+            this.client = new ServiceNowClient(getCamelContext(), configuration);
+        }
+
+        public Map<String, Object> getParameters() {
+            return parameters;
+        }
+
+        public ServiceNowConfiguration getConfiguration() {
+            return configuration;
+        }
+
+        public ServiceNowClient getClient() {
+            return client;
+        }
+
+        public String getInstanceName() {
+            return instanceName;
+        }
+
+        public String getObjectType() {
+            return objectType;
+        }
+
+        public String getObjectName() {
+            return objectName;
+        }
+
+        public Stack<String> getStack() {
+            return stack;
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/109da7c9/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/ServiceNowParam.java
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/ServiceNowParam.java b/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/ServiceNowParam.java
new file mode 100644
index 0000000..5353753
--- /dev/null
+++ b/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/ServiceNowParam.java
@@ -0,0 +1,28 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.servicenow;
+
+import org.apache.camel.Message;
+
+public interface ServiceNowParam {
+    String getId();
+    String getHeader();
+    Class<?> getType();
+    Object getDefaultValue(ServiceNowConfiguration configuration);
+    Object getHeaderValue(Message message);
+    Object getHeaderValue(Message message, ServiceNowConfiguration configuration);
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/109da7c9/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/ServiceNowParams.java
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/ServiceNowParams.java b/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/ServiceNowParams.java
new file mode 100644
index 0000000..75f16f9
--- /dev/null
+++ b/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/ServiceNowParams.java
@@ -0,0 +1,123 @@
+/**
+ * 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.servicenow;
+
+import java.util.function.Function;
+
+import org.apache.camel.Message;
+import org.apache.camel.util.ObjectHelper;
+
+public enum ServiceNowParams implements ServiceNowParam {
+    PARAM_SYS_ID("sys_id", "CamelServiceNowSysId", String.class),
+    PARAM_USER_SYS_ID("user_sysid", "CamelServiceNowUserSysId", String.class),
+    PARAM_USER_ID("user_id", "CamelServiceNowUserId", String.class),
+    PARAM_CART_ITEM_ID("cart_item_id", "CamelServiceNowCartItemId", String.class),
+    PARAM_FILE_NAME("file_name", "CamelServiceNowFileName", String.class),
+    PARAM_TABLE_NAME("table_name", "CamelServiceNowTable", String.class),
+    PARAM_TABLE_SYS_ID("table_sys_id", "CamelServiceNowTableSysId", String.class),
+    PARAM_ENCRYPTION_CONTEXT("encryption_context", "CamelServiceNowEncryptionContext", String.class),
+    SYSPARM_CATEGORY("sysparm_category", "CamelServiceNowCategory", String.class),
+    SYSPARM_TYPE("sysparm_type", "CamelServiceNowType", String.class),
+    SYSPARM_CATALOG("sysparm_catalog", "CamelServiceNowCatalog", String.class),
+    SYSPARM_QUERY("sysparm_query", "CamelServiceNowQuery", String.class),
+    SYSPARM_DISPLAY_VALUE("sysparm_display_value", "CamelServiceNowDisplayValue", String.class, ServiceNowConfiguration::getDisplayValue),
+    SYSPARM_INPUT_DISPLAY_VALUE("sysparm_input_display_value", "CamelServiceNowInputDisplayValue", Boolean.class, ServiceNowConfiguration::getInputDisplayValue),
+    SYSPARM_EXCLUDE_REFERENCE_LINK("sysparm_exclude_reference_link", "CamelServiceNowExcludeReferenceLink", Boolean.class, ServiceNowConfiguration::getExcludeReferenceLink),
+    SYSPARM_FIELDS("sysparm_fields", "CamelServiceNowFields", String.class),
+    SYSPARM_LIMIT("sysparm_limit", "CamelServiceNowLimit", Integer.class),
+    SYSPARM_TEXT("sysparm_text", "CamelServiceNowText", String.class),
+    SYSPARM_OFFSET("sysparm_offset", "CamelServiceNowOffset", Integer.class),
+    SYSPARM_VIEW("sysparm_view", "CamelServiceNowView", String.class),
+    SYSPARM_SUPPRESS_AUTO_SYS_FIELD("sysparm_suppress_auto_sys_field", "CamelServiceNowSuppressAutoSysField", Boolean.class, ServiceNowConfiguration::getSuppressAutoSysField),
+    SYSPARM_SUPPRESS_PAGINATION_HEADER("sysparm_suppress_pagination_header", "CamelServiceNowSuppressPaginationHeader", Boolean.class, ServiceNowConfiguration::getSuppressPaginationHeader),
+    SYSPARM_MIN_FIELDS("sysparm_min_fields", "CamelServiceNowMinFields", String.class),
+    SYSPARM_MAX_FIELDS("sysparm_max_fields", "CamelServiceNowMaxFields", String.class),
+    SYSPARM_SUM_FIELDS("sysparm_sum_fields", "CamelServiceNowSumFields", String.class),
+    SYSPARM_AVG_FIELDS("sysparm_avg_fields", "CamelServiceNowAvgFields", String.class),
+    SYSPARM_COUNT("sysparm_count", "CamelServiceNowCount", Boolean.class),
+    SYSPARM_GROUP_BY("sysparm_group_by", "CamelServiceNowGroupBy", String.class),
+    SYSPARM_ORDER_BY("sysparm_order_by", "CamelServiceNowOrderBy", String.class),
+    SYSPARM_HAVING("sysparm_having", "CamelServiceNowHaving", String.class),
+    SYSPARM_UUID("sysparm_uuid", "CamelServiceNowUUID", String.class),
+    SYSPARM_BREAKDOWN("sysparm_breakdown", "CamelServiceNowBreakdown", String.class),
+    SYSPARM_INCLUDE_SCORES("sysparm_include_scores", "CamelServiceNowIncludeScores", Boolean.class, ServiceNowConfiguration::getIncludeScores),
+    SYSPARM_INCLUDE_SCORE_NOTES("sysparm_include_score_notes", "CamelServiceNowIncludeScoreNotes", Boolean.class, ServiceNowConfiguration::getIncludeScoreNotes),
+    SYSPARM_INCLUDE_AGGREGATES("sysparm_include_aggregates", "CamelServiceNowIncludeAggregates", Boolean.class, ServiceNowConfiguration::getIncludeAggregates),
+    SYSPARM_INCLUDE_AVAILABLE_BREAKDOWNS("sysparm_include_available_breakdowns", "CamelServiceNowIncludeAvailableBreakdowns", Boolean.class, ServiceNowConfiguration::getIncludeAvailableBreakdowns),
+    SYSPARM_INCLUDE_AVAILABLE_AGGREGATES("sysparm_include_available_aggregates", "CamelServiceNowIncludeAvailableAggregates", Boolean.class, ServiceNowConfiguration::getIncludeAvailableAggregates),
+    SYSPARM_FAVORITES("sysparm_favorites", "CamelServiceNowFavorites", Boolean.class, ServiceNowConfiguration::getFavorites),
+    SYSPARM_KEY("sysparm_key", "CamelServiceNowKey", Boolean.class, ServiceNowConfiguration::getKey),
+    SYSPARM_TARGET("sysparm_target", "CamelServiceNowTarget", Boolean.class, ServiceNowConfiguration::getTarget),
+    SYSPARM_DISPLAY("sysparm_display", "CamelServiceNowDisplay", String.class, ServiceNowConfiguration::getDisplay),
+    SYSPARM_PER_PAGE("sysparm_per_page", "CamelServiceNowPerPage", Integer.class, ServiceNowConfiguration::getPerPage),
+    SYSPARM_SORT_BY("sysparm_sortby", "CamelServiceNowSortBy", String.class, ServiceNowConfiguration::getSortBy),
+    SYSPARM_SORT_DIR("sysparm_sortdir", "CamelServiceNowSortDir", String.class, ServiceNowConfiguration::getSortDir),
+    SYSPARM_CONTAINS("sysparm_contains", "CamelServiceNowContains", String.class),
+    SYSPARM_TAGS("sysparm_tags", "CamelServiceNowTags", String.class),
+    SYSPARM_PAGE("sysparm_page", "CamelServiceNowPage", String.class),
+    SYSPARM_ELEMENTS_FILTER("sysparm_elements_filter", "CamelServiceNowElementsFilter", String.class),
+    SYSPARM_BREAKDOWN_RELATION("sysparm_breakdown_relation", "CamelServiceNowBreakdownRelation", String.class),
+    SYSPARM_DATA_SOURCE("sysparm_data_source", "CamelServiceNowDataSource", String.class),
+    SYSPARM_TOP_LEVEL_ONLY("sysparm_top_level_only", "CamelServiceNowTopLevelOnly", Boolean.class, ServiceNowConfiguration::getTopLevelOnly);
+
+    private final String id;
+    private final String header;
+    private final Class<?> type;
+    private final Function<ServiceNowConfiguration, ?> defaultValueSupplier;
+
+    ServiceNowParams(String id, String header, Class<?> type) {
+        this(id, header, type, null);
+    }
+
+    ServiceNowParams(String id, String header, Class<?> type, Function<ServiceNowConfiguration, ?> defaultValueSupplier) {
+        ObjectHelper.notNull(id, "ServiceNowSysParam (id)");
+        ObjectHelper.notNull(header, "ServiceNowSysParam (header)");
+        ObjectHelper.notNull(type, "ServiceNowSysParam (type)");
+
+        this.id = id;
+        this.header = header.startsWith(ServiceNowConstants.CAMEL_HEADER_PREFIX)
+            ? header
+            : ServiceNowConstants.CAMEL_HEADER_PREFIX + ObjectHelper.capitalize(header);
+
+        this.type = type;
+        this.defaultValueSupplier = defaultValueSupplier;
+    }
+
+    public String getId() {
+        return id;
+    }
+
+    public String getHeader() {
+        return header;
+    }
+
+    public Class<?> getType() {
+        return type;
+    }
+
+    public Object getDefaultValue(ServiceNowConfiguration configuration) {
+        return defaultValueSupplier != null ? defaultValueSupplier.apply(configuration) : null;
+    }
+
+    public Object getHeaderValue(Message message) {
+        return message.getHeader(header, type);
+    }
+
+    public Object getHeaderValue(Message message, ServiceNowConfiguration configuration) {
+        return message.getHeader(header, getDefaultValue(configuration), type);
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/109da7c9/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/ServiceNowProducer.java
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/ServiceNowProducer.java b/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/ServiceNowProducer.java
new file mode 100644
index 0000000..67e08bb
--- /dev/null
+++ b/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/ServiceNowProducer.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.
+ */
+package org.apache.camel.component.servicenow;
+
+import org.apache.camel.Producer;
+
+public interface ServiceNowProducer extends Producer {
+    ServiceNowRelease getRelease();
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/109da7c9/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/ServiceNowProducerSupplier.java
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/ServiceNowProducerSupplier.java b/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/ServiceNowProducerSupplier.java
new file mode 100644
index 0000000..d339417
--- /dev/null
+++ b/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/ServiceNowProducerSupplier.java
@@ -0,0 +1,22 @@
+/**
+ * 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.servicenow;
+
+public interface ServiceNowProducerSupplier {
+    ServiceNowProducer get(ServiceNowEndpoint endpoint) throws Exception;
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/109da7c9/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/ServiceNowRelease.java
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/ServiceNowRelease.java b/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/ServiceNowRelease.java
new file mode 100644
index 0000000..d546215
--- /dev/null
+++ b/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/ServiceNowRelease.java
@@ -0,0 +1,41 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.servicenow;
+
+import org.apache.camel.component.servicenow.releases.fuji.FujiServiceNowProducer;
+import org.apache.camel.component.servicenow.releases.helsinki.HelsinkiServiceNowProducer;
+
+public enum ServiceNowRelease implements ServiceNowProducerSupplier {
+    FUJI {
+        @Override
+        public ServiceNowProducer get(ServiceNowEndpoint endpoint) throws Exception {
+            return new FujiServiceNowProducer(endpoint);
+        }
+    },
+    GENEVA {
+        @Override
+        public ServiceNowProducer get(ServiceNowEndpoint endpoint) throws Exception {
+            return null;
+        }
+    },
+    HELSINKI {
+        @Override
+        public ServiceNowProducer get(ServiceNowEndpoint endpoint) throws Exception {
+            return new HelsinkiServiceNowProducer(endpoint);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/109da7c9/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/annotations/ServiceNowSysParm.java
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/annotations/ServiceNowSysParm.java b/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/annotations/ServiceNowSysParm.java
new file mode 100644
index 0000000..361e741
--- /dev/null
+++ b/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/annotations/ServiceNowSysParm.java
@@ -0,0 +1,32 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.servicenow.annotations;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Repeatable;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Target({ElementType.TYPE})
+@Retention(RetentionPolicy.RUNTIME)
+@Repeatable(ServiceNowSysParms.class)
+public @interface ServiceNowSysParm {
+    String name();
+
+    String value();
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/109da7c9/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/annotations/ServiceNowSysParms.java
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/annotations/ServiceNowSysParms.java b/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/annotations/ServiceNowSysParms.java
new file mode 100644
index 0000000..236ba8b
--- /dev/null
+++ b/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/annotations/ServiceNowSysParms.java
@@ -0,0 +1,28 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.servicenow.annotations;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Target({ElementType.TYPE})
+@Retention(RetentionPolicy.RUNTIME)
+public @interface ServiceNowSysParms {
+    ServiceNowSysParm[] value();
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/109da7c9/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
new file mode 100644
index 0000000..4689455
--- /dev/null
+++ b/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/auth/AuthenticationRequestFilter.java
@@ -0,0 +1,56 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.servicenow.auth;
+
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.util.Base64;
+import javax.annotation.Priority;
+import javax.ws.rs.Priorities;
+import javax.ws.rs.client.ClientRequestContext;
+import javax.ws.rs.client.ClientRequestFilter;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.ext.Provider;
+
+import org.apache.camel.component.servicenow.ServiceNowConfiguration;
+
+
+@Provider
+@Priority(Priorities.AUTHENTICATION)
+public final class AuthenticationRequestFilter implements ClientRequestFilter {
+    private final OAuthToken authToken;
+    private final String authString;
+
+    public AuthenticationRequestFilter(ServiceNowConfiguration conf) throws IOException {
+        this.authToken = conf.hasOAuthAuthentication() ? new OAuthToken(conf) : null;
+        this.authString = conf.hasBasicAuthentication() ? getBasicAuthenticationString(conf) : null;
+    }
+
+    @Override
+    public void filter(ClientRequestContext requestContext) throws IOException {
+        if (authToken != null) {
+            requestContext.getHeaders().add(HttpHeaders.AUTHORIZATION, authToken.getAuthString());
+        } else if (authString != null) {
+            requestContext.getHeaders().add(HttpHeaders.AUTHORIZATION, authString);
+        }
+    }
+
+    private static String getBasicAuthenticationString(ServiceNowConfiguration conf) {
+        String userAndPassword = conf.getUserName() + ":" + conf.getPassword();
+        return "Basic " + Base64.getEncoder().encodeToString(userAndPassword.getBytes(StandardCharsets.UTF_8));
+    }
+}


[09/19] camel git commit: CAMEL-11560: ServiceNow : allow to expand reference types in import_set response

Posted by lb...@apache.org.
CAMEL-11560: ServiceNow : allow to expand reference types in import_set response


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

Branch: refs/heads/master
Commit: 80e25c4997bf1334ce44fa5fd78b2e19ed8bf992
Parents: 05aa433
Author: lburgazzoli <lb...@gmail.com>
Authored: Wed Aug 2 14:30:56 2017 +0200
Committer: lburgazzoli <lb...@gmail.com>
Committed: Fri Aug 4 18:09:05 2017 +0200

----------------------------------------------------------------------
 .../src/main/docs/servicenow-component.adoc     |  3 +-
 .../servicenow/AbstractServiceNowProcessor.java | 20 +++--
 .../servicenow/ServiceNowConfiguration.java     | 14 +++
 .../servicenow/ServiceNowConstants.java         |  1 +
 .../servicenow/model/ImportSetResponse.java     | 57 ++++++++++++
 .../servicenow/model/ImportSetResult.java       | 83 +++++++++++++++++
 .../fuji/FujiServiceNowImportSetProcessor.java  |  5 ++
 .../HelsinkiServiceNowImportSetProcessor.java   | 73 +++++++++++++--
 .../servicenow/ServiceNowImportSetTest.java     | 95 +++++++++++---------
 .../ServiceNowComponentConfiguration.java       | 15 ++++
 10 files changed, 308 insertions(+), 58 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/camel/blob/80e25c49/components/camel-servicenow/src/main/docs/servicenow-component.adoc
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/src/main/docs/servicenow-component.adoc b/components/camel-servicenow/src/main/docs/servicenow-component.adoc
index af9bc01..197ebd9 100644
--- a/components/camel-servicenow/src/main/docs/servicenow-component.adoc
+++ b/components/camel-servicenow/src/main/docs/servicenow-component.adoc
@@ -66,7 +66,7 @@ with the following path and query parameters:
 | **instanceName** | *Required* The ServiceNow instance name |  | String
 |=======================================================================
 
-#### Query Parameters (40 parameters):
+#### Query Parameters (41 parameters):
 
 [width="100%",cols="2,5,^1,2",options="header"]
 |=======================================================================
@@ -99,6 +99,7 @@ with the following path and query parameters:
 | **httpClientPolicy** (advanced) | To configure http-client |  | HTTPClientPolicy
 | **mapper** (advanced) | Sets Jackson's ObjectMapper to use for request/reply |  | ObjectMapper
 | **proxyAuthorizationPolicy** (advanced) | To configure proxy authentication |  | ProxyAuthorization Policy
+| **retrieveTargetRecordOn Import** (advanced) | Set this parameter to true to retrieve the target record when using import set api. The import set result is then replaced by the target record | false | Boolean
 | **synchronous** (advanced) | Sets whether synchronous processing should be strictly used or Camel is allowed to use asynchronous processing (if supported). | false | boolean
 | **proxyHost** (proxy) | The proxy host name |  | String
 | **proxyPort** (proxy) | The proxy port number |  | Integer

http://git-wip-us.apache.org/repos/asf/camel/blob/80e25c49/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/AbstractServiceNowProcessor.java
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/AbstractServiceNowProcessor.java b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/AbstractServiceNowProcessor.java
index ab2d824..1ae25af 100644
--- a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/AbstractServiceNowProcessor.java
+++ b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/AbstractServiceNowProcessor.java
@@ -235,9 +235,13 @@ public abstract class AbstractServiceNowProcessor implements Processor {
     }
 
     protected Class<?> getRequestModel(Message message, String modelName) {
-        Class<?> model = message.getHeader(ServiceNowConstants.REQUEST_MODEL, Class.class);
-        if (model == null) {
-            model = message.getHeader(ServiceNowConstants.MODEL, Class.class);
+        Class<?> model = null;
+
+        if (message != null) {
+            model = message.getHeader(ServiceNowConstants.REQUEST_MODEL, Class.class);
+            if (model == null) {
+                model = message.getHeader(ServiceNowConstants.MODEL, Class.class);
+            }
         }
 
         return model != null
@@ -250,9 +254,13 @@ public abstract class AbstractServiceNowProcessor implements Processor {
     }
 
     protected Class<?> getResponseModel(Message message, String modelName) {
-        Class<?> model = message.getHeader(ServiceNowConstants.RESPONSE_MODEL, Class.class);
-        if (model == null) {
-            model = message.getHeader(ServiceNowConstants.MODEL, Class.class);
+        Class<?> model = null;
+
+        if (message != null) {
+            model = message.getHeader(ServiceNowConstants.RESPONSE_MODEL, Class.class);
+            if (model == null) {
+                model = message.getHeader(ServiceNowConstants.MODEL, Class.class);
+            }
         }
 
         return model != null

http://git-wip-us.apache.org/repos/asf/camel/blob/80e25c49/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowConfiguration.java
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowConfiguration.java b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowConfiguration.java
index d16b31e..bc46bcb 100644
--- a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowConfiguration.java
+++ b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowConfiguration.java
@@ -81,6 +81,8 @@ public class ServiceNowConfiguration implements Cloneable {
     private Boolean topLevelOnly;
     @UriParam
     private Boolean favorites;
+    @UriParam(label = "advanced", defaultValue = "false")
+    private Boolean retrieveTargetRecordOnImport = false;
     @UriParam
     private Boolean key;
     @UriParam
@@ -356,6 +358,18 @@ public class ServiceNowConfiguration implements Cloneable {
         this.favorites = favorites;
     }
 
+    public Boolean getRetrieveTargetRecordOnImport() {
+        return retrieveTargetRecordOnImport;
+    }
+
+    /**
+     * Set this parameter to true to retrieve the target record when using import
+     * set api. The import set result is then replaced by the target record
+     */
+    public void setRetrieveTargetRecordOnImport(Boolean retrieveTargetRecordOnImport) {
+        this.retrieveTargetRecordOnImport = retrieveTargetRecordOnImport;
+    }
+
     public Boolean getKey() {
         return key;
     }

http://git-wip-us.apache.org/repos/asf/camel/blob/80e25c49/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowConstants.java
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowConstants.java b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowConstants.java
index 0f4b7ad..b967bbe 100644
--- a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowConstants.java
+++ b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowConstants.java
@@ -35,6 +35,7 @@ public final class ServiceNowConstants {
     public static final String RESPONSE_META = "CamelServiceNowResponseMeta";
     public static final String API_VERSION = "CamelServiceNowApiVersion";
     public static final String RESPONSE_TYPE = "CamelServiceNowResponseType";
+    public static final String RETRIEVE_TARGET_RECORD = "CamelServiceNowRetrieveTargetRecord";
 
     public static final String ATTACHMENT_META_HEADER = "X-Attachment-Metadata";
 

http://git-wip-us.apache.org/repos/asf/camel/blob/80e25c49/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/model/ImportSetResponse.java
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/model/ImportSetResponse.java b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/model/ImportSetResponse.java
new file mode 100644
index 0000000..348dd8d
--- /dev/null
+++ b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/model/ImportSetResponse.java
@@ -0,0 +1,57 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.servicenow.model;
+
+import java.util.Collections;
+import java.util.List;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import org.apache.camel.component.servicenow.annotations.ServiceNowSysParm;
+
+@ServiceNowSysParm(name = "sysparm_exclude_reference_link", value = "true")
+@JsonIgnoreProperties(ignoreUnknown = true)
+@JsonInclude(JsonInclude.Include.NON_NULL)
+public class ImportSetResponse {
+    private final String importSet;
+    private final String stagingTable;
+    private final List<ImportSetResult> results;
+
+    @JsonCreator
+    public ImportSetResponse(
+        @JsonProperty("import_set") String importSet,
+        @JsonProperty("staging_table") String stagingTable,
+        @JsonProperty("result") List<ImportSetResult> results) {
+        this.importSet = importSet;
+        this.stagingTable = stagingTable;
+        this.results = results == null ? Collections.emptyList() : results;
+    }
+
+    public String getImportSet() {
+        return importSet;
+    }
+
+    public String getStagingTable() {
+        return stagingTable;
+    }
+
+    public List<ImportSetResult> getResults() {
+        return results;
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/80e25c49/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/model/ImportSetResult.java
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/model/ImportSetResult.java b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/model/ImportSetResult.java
new file mode 100644
index 0000000..e5962e0
--- /dev/null
+++ b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/model/ImportSetResult.java
@@ -0,0 +1,83 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.servicenow.model;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import org.apache.camel.component.servicenow.annotations.ServiceNowSysParm;
+
+@ServiceNowSysParm(name = "sysparm_exclude_reference_link", value = "true")
+@JsonIgnoreProperties(ignoreUnknown = true)
+@JsonInclude(JsonInclude.Include.NON_NULL)
+public class ImportSetResult {
+    private final String transformMap;
+    private final String table;
+    private final String displayName;
+    private final String displayValue;
+    private final String recordLink;
+    private final String status;
+    private final String sysId;
+
+    @JsonCreator
+    public ImportSetResult(
+        @JsonProperty(value = "transform_map") String transformMap,
+        @JsonProperty(value = "table", required = true) String table,
+        @JsonProperty(value = "display_name") String displayName,
+        @JsonProperty(value = "display_value") String displayValue,
+        @JsonProperty(value = "record_link") String recordLink,
+        @JsonProperty(value = "status", required = true) String status,
+        @JsonProperty(value = "sys_id", required = true) String sysId) {
+
+        this.transformMap = transformMap;
+        this.table = table;
+        this.displayName = displayName;
+        this.displayValue = displayValue;
+        this.recordLink = recordLink;
+        this.status = status;
+        this.sysId = sysId;
+    }
+
+    public String getTransformMap() {
+        return transformMap;
+    }
+
+    public String getTable() {
+        return table;
+    }
+
+    public String getDisplayName() {
+        return displayName;
+    }
+
+    public String getDisplayValue() {
+        return displayValue;
+    }
+
+    public String getRecordLink() {
+        return recordLink;
+    }
+
+    public String getStatus() {
+        return status;
+    }
+
+    public String getSysId() {
+        return sysId;
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/80e25c49/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/releases/fuji/FujiServiceNowImportSetProcessor.java
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/releases/fuji/FujiServiceNowImportSetProcessor.java b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/releases/fuji/FujiServiceNowImportSetProcessor.java
index 4bace68..2080045 100644
--- a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/releases/fuji/FujiServiceNowImportSetProcessor.java
+++ b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/releases/fuji/FujiServiceNowImportSetProcessor.java
@@ -68,7 +68,12 @@ class FujiServiceNowImportSetProcessor extends FujiServiceNowProcessor {
      * https://instance.service-now.com/api/now/import/{tableName}
      */
     private Response createRecord(Message in, Class<?> requestModel, Class<?> responseModel, String apiVersion, String tableName) throws Exception {
+        if (in.getHeader(ServiceNowConstants.RETRIEVE_TARGET_RECORD, config::getRetrieveTargetRecordOnImport, Boolean.class)) {
+            throw new UnsupportedOperationException("RetrieveTargetRecordOnImport is supported from Helsinky");
+        }
+
         validateBody(in, requestModel);
+
         return client.reset()
             .types(MediaType.APPLICATION_JSON_TYPE)
             .path("now")

http://git-wip-us.apache.org/repos/asf/camel/blob/80e25c49/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/releases/helsinki/HelsinkiServiceNowImportSetProcessor.java
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/releases/helsinki/HelsinkiServiceNowImportSetProcessor.java b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/releases/helsinki/HelsinkiServiceNowImportSetProcessor.java
index c49f228..feb5d47 100644
--- a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/releases/helsinki/HelsinkiServiceNowImportSetProcessor.java
+++ b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/releases/helsinki/HelsinkiServiceNowImportSetProcessor.java
@@ -17,13 +17,18 @@
 package org.apache.camel.component.servicenow.releases.helsinki;
 
 import javax.ws.rs.HttpMethod;
+import javax.ws.rs.core.HttpHeaders;
 import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Response;
 
 import org.apache.camel.Exchange;
 import org.apache.camel.Message;
 import org.apache.camel.component.servicenow.AbstractServiceNowProcessor;
+import org.apache.camel.component.servicenow.ServiceNowConstants;
 import org.apache.camel.component.servicenow.ServiceNowEndpoint;
+import org.apache.camel.component.servicenow.ServiceNowParams;
+import org.apache.camel.component.servicenow.model.ImportSetResponse;
+import org.apache.camel.component.servicenow.model.ImportSetResult;
 import org.apache.camel.util.ObjectHelper;
 
 import static org.apache.camel.component.servicenow.ServiceNowConstants.ACTION_CREATE;
@@ -71,17 +76,67 @@ class HelsinkiServiceNowImportSetProcessor extends AbstractServiceNowProcessor {
         final String tableName = getTableName(in);
         final String apiVersion = getApiVersion(in);
         final Class<?> requestModel = getRequestModel(in, tableName);
-        final Class<?> responseModel = getResponseModel(in, tableName);
+        final boolean retrieve = in.getHeader(ServiceNowConstants.RETRIEVE_TARGET_RECORD, config::getRetrieveTargetRecordOnImport, Boolean.class);
+
+        Class<?> responseModel = getResponseModel(in, tableName);
+        Response response;
 
         validateBody(in, requestModel);
-        Response response = client.reset()
-            .types(MediaType.APPLICATION_JSON_TYPE)
-            .path("now")
-            .path(apiVersion)
-            .path("import")
-            .path(tableName)
-            .query(responseModel)
-            .invoke(HttpMethod.POST, in.getMandatoryBody());
+
+        if (retrieve) {
+            // If the endpoint is configured to retrieve the target record, the
+            // import response model is ignored and the response is ImportSetResponse
+
+            response = client.reset()
+                .types(MediaType.APPLICATION_JSON_TYPE)
+                .path("now")
+                .path(apiVersion)
+                .path("import")
+                .path(tableName)
+                .invoke(HttpMethod.POST, in.getMandatoryBody());
+
+            if (ObjectHelper.isNotEmpty(response.getHeaderString(HttpHeaders.CONTENT_TYPE))) {
+                for (ImportSetResult result : response.readEntity(ImportSetResponse.class).getResults()) {
+                    final String status = result.getStatus();
+                    final String table = result.getTable();
+                    final String sysId = result.getSysId();
+
+                    if (ObjectHelper.equalIgnoreCase("inserted", status)) {
+
+                        // If the endpoint is configured to retrieve the target
+                        // record, the response model is related to the target
+                        // table
+                        responseModel = getResponseModel(in, table);
+
+                        // Do get the record
+                        response = client.reset()
+                            .types(MediaType.APPLICATION_JSON_TYPE)
+                            .path("now")
+                            .path(apiVersion)
+                            .path("table")
+                            .path(ObjectHelper.notNull(table, "table"))
+                            .path(ObjectHelper.notNull(sysId, "sys_id"))
+                            .query(ServiceNowParams.SYSPARM_DISPLAY_VALUE, in)
+                            .query(ServiceNowParams.SYSPARM_EXCLUDE_REFERENCE_LINK, in)
+                            .query(ServiceNowParams.SYSPARM_FIELDS, in)
+                            .query(ServiceNowParams.SYSPARM_VIEW, in)
+                            .query(responseModel)
+                            .invoke(HttpMethod.GET);
+
+                        break;
+                    }
+                }
+            }
+        } else {
+            response = client.reset()
+                .types(MediaType.APPLICATION_JSON_TYPE)
+                .path("now")
+                .path(apiVersion)
+                .path("import")
+                .path(tableName)
+                .query(responseModel)
+                .invoke(HttpMethod.POST, in.getMandatoryBody());
+        }
 
         setBodyAndHeaders(in, responseModel, response);
     }

http://git-wip-us.apache.org/repos/asf/camel/blob/80e25c49/components/camel-servicenow/src/test/java/org/apache/camel/component/servicenow/ServiceNowImportSetTest.java
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/src/test/java/org/apache/camel/component/servicenow/ServiceNowImportSetTest.java b/components/camel-servicenow/src/test/java/org/apache/camel/component/servicenow/ServiceNowImportSetTest.java
index df924df..dd524bc 100644
--- a/components/camel-servicenow/src/test/java/org/apache/camel/component/servicenow/ServiceNowImportSetTest.java
+++ b/components/camel-servicenow/src/test/java/org/apache/camel/component/servicenow/ServiceNowImportSetTest.java
@@ -16,8 +16,10 @@
  */
 package org.apache.camel.component.servicenow;
 
+import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
+import java.util.UUID;
 
 import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
 import com.fasterxml.jackson.annotation.JsonInclude;
@@ -25,24 +27,16 @@ import com.fasterxml.jackson.annotation.JsonProperty;
 import org.apache.camel.Message;
 import org.apache.camel.builder.RouteBuilder;
 import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.component.servicenow.model.ImportSetResult;
+import org.apache.camel.component.servicenow.model.Incident;
 import org.junit.Ignore;
 import org.junit.Test;
 
 /**
  * To set-up ServiceNow for this tests:
  *
- * 1. Create a new table with
- *   - id has to be set to u_imp_incidents (name does not matter)
- *   - inherit from sys_import_set_row
- *
- * 2. Add a new field to u_imp_incidents
- *   - name short_description
- *   - id should be automatically set to u_short_description
- *
- * 3. Create a new Transform Map
- *   - source table u_imp_incidents
- *   - target table incidents
- *   - Perform auto mapping, if it does not work map each field one by one
+ * 1. Create a new web service named u_test_imp_incident targeting incident table
+ * 2. Create a mapping (automatic)
  */
 @Ignore
 public class ServiceNowImportSetTest extends ServiceNowTestSupport {
@@ -53,10 +47,11 @@ public class ServiceNowImportSetTest extends ServiceNowTestSupport {
 
         mock.reset();
         mock.expectedMessageCount(1);
-        mock.expectedHeaderReceived(ServiceNowConstants.RESPONSE_TYPE, List.class);
+        mock.expectedHeaderReceived(ServiceNowConstants.RESPONSE_TYPE, ArrayList.class);
 
         IncidentImportRequest incident = new IncidentImportRequest();
-        incident.shortDescription = "test";
+        incident.description = UUID.randomUUID().toString();
+        incident.correlationId = UUID.randomUUID().toString();
 
         template().sendBodyAndHeaders(
             "direct:servicenow",
@@ -65,8 +60,8 @@ public class ServiceNowImportSetTest extends ServiceNowTestSupport {
                 .put(ServiceNowConstants.RESOURCE, ServiceNowConstants.RESOURCE_IMPORT)
                 .put(ServiceNowConstants.ACTION, ServiceNowConstants.ACTION_CREATE)
                 .put(ServiceNowConstants.REQUEST_MODEL, IncidentImportRequest.class)
-                .put(ServiceNowConstants.RESPONSE_MODEL, IncidentImportResponse.class)
-                .put(ServiceNowParams.PARAM_TABLE_NAME, "u_imp_incident")
+                .put(ServiceNowConstants.RESPONSE_MODEL, ImportSetResult.class)
+                .put(ServiceNowParams.PARAM_TABLE_NAME, "u_test_imp_incident")
                 .build()
         );
 
@@ -77,15 +72,48 @@ public class ServiceNowImportSetTest extends ServiceNowTestSupport {
         // Meta data
         Map<String, String> meta = in.getHeader(ServiceNowConstants.RESPONSE_META, Map.class);
         assertNotNull(meta);
-        assertEquals("u_imp_incident", meta.get("staging_table"));
+        assertEquals("u_test_imp_incident", meta.get("staging_table"));
 
         // Incidents
-        List<IncidentImportResponse> responses = in.getBody(List.class);
+        List<ImportSetResult> responses = in.getBody(List.class);
         assertNotNull(responses);
         assertEquals(1, responses.size());
-        assertEquals("inserted", responses.get(0).status);
-        assertEquals("imp_incidents", responses.get(0).transformMap);
-        assertEquals("incident", responses.get(0).table);
+        assertEquals("inserted", responses.get(0).getStatus());
+        assertEquals("test_imp_incident", responses.get(0).getTransformMap());
+        assertEquals("incident", responses.get(0).getTable());
+    }
+
+    @Test
+    public void testIncidentImportWithRetrieve() throws Exception {
+        MockEndpoint mock = getMockEndpoint("mock:servicenow");
+
+        mock.reset();
+        mock.expectedMessageCount(1);
+        mock.expectedHeaderReceived(ServiceNowConstants.RESPONSE_TYPE, Incident.class);
+
+        IncidentImportRequest incident = new IncidentImportRequest();
+        incident.description = UUID.randomUUID().toString();
+
+        template().sendBodyAndHeaders(
+            "direct:servicenow",
+            incident,
+            kvBuilder()
+                .put(ServiceNowConstants.RESOURCE, ServiceNowConstants.RESOURCE_IMPORT)
+                .put(ServiceNowConstants.ACTION, ServiceNowConstants.ACTION_CREATE)
+                .put(ServiceNowConstants.REQUEST_MODEL, IncidentImportRequest.class)
+                .put(ServiceNowConstants.RESPONSE_MODEL, Incident.class)
+                .put(ServiceNowConstants.RETRIEVE_TARGET_RECORD, true)
+                .put(ServiceNowParams.PARAM_TABLE_NAME, "u_test_imp_incident")
+                .build()
+        );
+
+        mock.assertIsSatisfied();
+
+        Incident response = mock.getExchanges().get(0).getIn().getBody(Incident.class);
+        assertNotNull(response);
+        assertEquals(incident.description, response.getDescription());
+        assertNotNull(response.getNumber());
+        assertNotNull(response.getId());
     }
 
     // *************************************************************************
@@ -111,26 +139,9 @@ public class ServiceNowImportSetTest extends ServiceNowTestSupport {
     @JsonIgnoreProperties(ignoreUnknown = true)
     @JsonInclude(JsonInclude.Include.NON_NULL)
     private static final class IncidentImportRequest {
-        @JsonProperty("u_short_description")
-        public String shortDescription;
-    }
-
-    @JsonIgnoreProperties(ignoreUnknown = true)
-    @JsonInclude(JsonInclude.Include.NON_NULL)
-    private static final class IncidentImportResponse {
-        @JsonProperty("transform_map")
-        public String transformMap;
-        @JsonProperty("table")
-        public String table;
-        @JsonProperty("display_name")
-        public String displayName;
-        @JsonProperty("display_value")
-        public String displayValue;
-        @JsonProperty("record_link")
-        public String recordLink;
-        @JsonProperty("status")
-        public String status;
-        @JsonProperty("sys_id")
-        public String sysId;
+        @JsonProperty("description")
+        public String description;
+        @JsonProperty("correlation_id")
+        public String correlationId;
     }
 }

http://git-wip-us.apache.org/repos/asf/camel/blob/80e25c49/platforms/spring-boot/components-starter/camel-servicenow-starter/src/main/java/org/apache/camel/component/servicenow/springboot/ServiceNowComponentConfiguration.java
----------------------------------------------------------------------
diff --git a/platforms/spring-boot/components-starter/camel-servicenow-starter/src/main/java/org/apache/camel/component/servicenow/springboot/ServiceNowComponentConfiguration.java b/platforms/spring-boot/components-starter/camel-servicenow-starter/src/main/java/org/apache/camel/component/servicenow/springboot/ServiceNowComponentConfiguration.java
index 56e1a4e..de23938 100644
--- a/platforms/spring-boot/components-starter/camel-servicenow-starter/src/main/java/org/apache/camel/component/servicenow/springboot/ServiceNowComponentConfiguration.java
+++ b/platforms/spring-boot/components-starter/camel-servicenow-starter/src/main/java/org/apache/camel/component/servicenow/springboot/ServiceNowComponentConfiguration.java
@@ -257,6 +257,12 @@ public class ServiceNowComponentConfiguration
          */
         private Boolean favorites;
         /**
+         * Set this parameter to true to retrieve the target record when using
+         * import set api. The import set result is then replaced by the target
+         * record
+         */
+        private Boolean retrieveTargetRecordOnImport = false;
+        /**
          * Set this parameter to true to return only scorecards for key
          * indicators.
          */
@@ -500,6 +506,15 @@ public class ServiceNowComponentConfiguration
             this.favorites = favorites;
         }
 
+        public Boolean getRetrieveTargetRecordOnImport() {
+            return retrieveTargetRecordOnImport;
+        }
+
+        public void setRetrieveTargetRecordOnImport(
+                Boolean retrieveTargetRecordOnImport) {
+            this.retrieveTargetRecordOnImport = retrieveTargetRecordOnImport;
+        }
+
         public Boolean getKey() {
             return key;
         }


[03/19] camel git commit: CAMEL-11550: Component extensions

Posted by lb...@apache.org.
http://git-wip-us.apache.org/repos/asf/camel/blob/42529399/components/camel-salesforce/camel-salesforce-component/src/test/java/org/apache/camel/component/salesforce/SalesforceComponentVerifierExtensionTest.java
----------------------------------------------------------------------
diff --git a/components/camel-salesforce/camel-salesforce-component/src/test/java/org/apache/camel/component/salesforce/SalesforceComponentVerifierExtensionTest.java b/components/camel-salesforce/camel-salesforce-component/src/test/java/org/apache/camel/component/salesforce/SalesforceComponentVerifierExtensionTest.java
new file mode 100644
index 0000000..bf7ed2a
--- /dev/null
+++ b/components/camel-salesforce/camel-salesforce-component/src/test/java/org/apache/camel/component/salesforce/SalesforceComponentVerifierExtensionTest.java
@@ -0,0 +1,183 @@
+/**
+ * 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.salesforce;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.camel.Component;
+import org.apache.camel.ComponentVerifier;
+import org.apache.camel.component.extension.ComponentVerifierExtension;
+import org.apache.camel.component.salesforce.api.SalesforceException;
+import org.apache.camel.test.junit4.CamelTestSupport;
+import org.apache.camel.util.ObjectHelper;
+import org.junit.Assert;
+import org.junit.Assume;
+import org.junit.Test;
+
+public class SalesforceComponentVerifierExtensionTest extends CamelTestSupport {
+    private static final String CLIENT_ID = getSystemPropertyOrEnvVar("salesforce.clientid");
+    private static final String CLIENT_SECRET = getSystemPropertyOrEnvVar("salesforce.clientsecret");
+    private static final String USERNAME = getSystemPropertyOrEnvVar("salesforce.userName");
+    private static final String PASSWORD = getSystemPropertyOrEnvVar("salesforce.password");
+
+    @Override
+    protected void doPreSetup() throws Exception {
+        Assume.assumeNotNull(CLIENT_ID);
+        Assume.assumeNotNull(CLIENT_SECRET);
+        Assume.assumeNotNull(USERNAME);
+        Assume.assumeNotNull(PASSWORD);
+    }
+
+    @Override
+    public boolean isUseRouteBuilder() {
+        return false;
+    }
+
+    // *********************************
+    // Helpers
+    // *********************************
+
+    protected Map<String, Object> getParameters() {
+        HashMap<String, Object> parameters = new HashMap<>();
+        parameters.put("clientId", CLIENT_ID);
+        parameters.put("clientSecret", CLIENT_SECRET);
+        parameters.put("userName", USERNAME);
+        parameters.put("password", PASSWORD);
+
+
+        return parameters;
+    }
+
+    public static String getSystemPropertyOrEnvVar(String systemProperty) {
+        String answer = System.getProperty(systemProperty);
+        if (ObjectHelper.isEmpty(answer)) {
+            String envProperty = systemProperty.toUpperCase().replaceAll("[.-]", "_");
+            answer = System.getenv(envProperty);
+        }
+
+        return answer;
+    }
+
+    protected ComponentVerifierExtension getExtension() {
+        Component component = context().getComponent("salesforce");
+        ComponentVerifierExtension verifier = component.getExtension(ComponentVerifierExtension.class).orElseThrow(IllegalStateException::new);
+
+        return verifier;
+    }
+
+    // *********************************
+    // Parameters validation
+    // *********************************
+
+    @Test
+    public void testUsernamePasswordParameters() {
+        HashMap<String, Object> parameters = new HashMap<>();
+        parameters.put("clientId", "clientId");
+        parameters.put("clientSecret", "clientSecret");
+        parameters.put("userName", "userName");
+        parameters.put("password", "password");
+
+        ComponentVerifierExtension.Result result = getExtension().verify(ComponentVerifierExtension.Scope.PARAMETERS, parameters);
+
+        Assert.assertEquals(ComponentVerifierExtension.Result.Status.OK, result.getStatus());
+    }
+
+    @Test
+    public void testRefreshTokenParameters() {
+        Map<String, Object> parameters = getParameters();
+        parameters.put("clientId", "clientId");
+        parameters.put("clientSecret", "clientSecret");
+        parameters.put("refreshToken", "refreshToken");
+
+        ComponentVerifierExtension.Result result = getExtension().verify(ComponentVerifierExtension.Scope.PARAMETERS, parameters);
+
+        Assert.assertEquals(ComponentVerifierExtension.Result.Status.OK, result.getStatus());
+    }
+
+    @Test
+    public void testWrongParameters() {
+        HashMap<String, Object> parameters = new HashMap<>();
+        parameters.put("clientId", "clientId");
+        parameters.put("clientSecret", "clientSecret");
+        parameters.put("password", "password");
+
+        ComponentVerifierExtension.Result result = getExtension().verify(ComponentVerifierExtension.Scope.PARAMETERS, parameters);
+
+        Assert.assertEquals(ComponentVerifierExtension.Result.Status.ERROR, result.getStatus());
+        Assert.assertEquals(3, result.getErrors().size());
+
+        Assert.assertEquals(ComponentVerifierExtension.VerificationError.StandardCode.INCOMPLETE_PARAMETER_GROUP, result.getErrors().get(0).getCode());
+        Assert.assertEquals(ComponentVerifierExtension.VerificationError.StandardCode.INCOMPLETE_PARAMETER_GROUP, result.getErrors().get(1).getCode());
+        Assert.assertEquals(ComponentVerifierExtension.VerificationError.StandardCode.INCOMPLETE_PARAMETER_GROUP, result.getErrors().get(2).getCode());
+    }
+
+    // *********************************
+    // Connectivity validation
+    // *********************************
+
+    @Test
+    public void testConnectivity() {
+        Map<String, Object> parameters = getParameters();
+        ComponentVerifierExtension.Result result = getExtension().verify(ComponentVerifierExtension.Scope.CONNECTIVITY, parameters);
+
+        Assert.assertEquals(ComponentVerifierExtension.Result.Status.OK, result.getStatus());
+    }
+
+    @Test
+    public void testConnectivityWithWrongUserName() {
+        Map<String, Object> parameters = getParameters();
+        parameters.put("userName", "not-a-salesforce-user");
+
+        ComponentVerifierExtension.Result result = getExtension().verify(ComponentVerifierExtension.Scope.CONNECTIVITY, parameters);
+
+        Assert.assertEquals(ComponentVerifierExtension.Result.Status.ERROR, result.getStatus());
+        Assert.assertEquals(2, result.getErrors().size());
+
+        // Exception
+        Assert.assertEquals(ComponentVerifierExtension.VerificationError.StandardCode.EXCEPTION, result.getErrors().get(0).getCode());
+        Assert.assertNotNull(result.getErrors().get(0).getDetails().get(ComponentVerifierExtension.VerificationError.ExceptionAttribute.EXCEPTION_INSTANCE));
+        Assert.assertTrue(result.getErrors().get(0).getDetails().get(ComponentVerifierExtension.VerificationError.ExceptionAttribute.EXCEPTION_INSTANCE) instanceof SalesforceException);
+        Assert.assertEquals(400, result.getErrors().get(0).getDetails().get(ComponentVerifierExtension.VerificationError.HttpAttribute.HTTP_CODE));
+
+        // Salesforce Error
+        Assert.assertEquals("invalid_grant", result.getErrors().get(1).getDetail("salesforce_code"));
+    }
+
+    @Test
+    public void testConnectivityWithWrongSecrets() {
+        Map<String, Object> parameters = getParameters();
+        parameters.put("clientId", "wrong-client-id");
+        parameters.put("clientSecret", "wrong-client-secret");
+
+        ComponentVerifierExtension.Result result = getExtension().verify(ComponentVerifierExtension.Scope.CONNECTIVITY, parameters);
+
+        Assert.assertEquals(ComponentVerifier.Result.Status.ERROR, result.getStatus());
+
+        Assert.assertEquals(ComponentVerifier.Result.Status.ERROR, result.getStatus());
+        Assert.assertEquals(2, result.getErrors().size());
+
+        // Exception
+        Assert.assertEquals(ComponentVerifierExtension.VerificationError.StandardCode.EXCEPTION, result.getErrors().get(0).getCode());
+        Assert.assertNotNull(result.getErrors().get(0).getDetails().get(ComponentVerifierExtension.VerificationError.ExceptionAttribute.EXCEPTION_INSTANCE));
+        Assert.assertTrue(result.getErrors().get(0).getDetails().get(ComponentVerifierExtension.VerificationError.ExceptionAttribute.EXCEPTION_INSTANCE) instanceof SalesforceException);
+        Assert.assertEquals(400, result.getErrors().get(0).getDetails().get(ComponentVerifier.VerificationError.HttpAttribute.HTTP_CODE));
+
+        // Salesforce Error
+        Assert.assertEquals("invalid_client_id", result.getErrors().get(1).getDetail("salesforce_code"));
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/42529399/components/camel-salesforce/camel-salesforce-component/src/test/java/org/apache/camel/component/salesforce/SalesforceComponentVerifierTest.java
----------------------------------------------------------------------
diff --git a/components/camel-salesforce/camel-salesforce-component/src/test/java/org/apache/camel/component/salesforce/SalesforceComponentVerifierTest.java b/components/camel-salesforce/camel-salesforce-component/src/test/java/org/apache/camel/component/salesforce/SalesforceComponentVerifierTest.java
index dc02d55..8b27265 100644
--- a/components/camel-salesforce/camel-salesforce-component/src/test/java/org/apache/camel/component/salesforce/SalesforceComponentVerifierTest.java
+++ b/components/camel-salesforce/camel-salesforce-component/src/test/java/org/apache/camel/component/salesforce/SalesforceComponentVerifierTest.java
@@ -20,7 +20,6 @@ import java.util.HashMap;
 import java.util.Map;
 
 import org.apache.camel.ComponentVerifier;
-import org.apache.camel.ComponentVerifier.VerificationError;
 import org.apache.camel.component.salesforce.api.SalesforceException;
 import org.apache.camel.test.junit4.CamelTestSupport;
 import org.apache.camel.util.ObjectHelper;
@@ -72,11 +71,9 @@ public class SalesforceComponentVerifierTest extends CamelTestSupport {
         return answer;
     }
 
-    protected SalesforceComponentVerifier getVerifier() {
+    protected ComponentVerifier getVerifier() {
         SalesforceComponent component = context().getComponent("salesforce", SalesforceComponent.class);
-        SalesforceComponentVerifier verifier = (SalesforceComponentVerifier)component.getVerifier();
-
-        return verifier;
+        return component.getVerifier();
     }
 
     // *********************************
@@ -120,9 +117,9 @@ public class SalesforceComponentVerifierTest extends CamelTestSupport {
         Assert.assertEquals(ComponentVerifier.Result.Status.ERROR, result.getStatus());
         Assert.assertEquals(3, result.getErrors().size());
 
-        Assert.assertEquals(VerificationError.StandardCode.INCOMPLETE_PARAMETER_GROUP, result.getErrors().get(0).getCode());
-        Assert.assertEquals(VerificationError.StandardCode.INCOMPLETE_PARAMETER_GROUP, result.getErrors().get(1).getCode());
-        Assert.assertEquals(VerificationError.StandardCode.INCOMPLETE_PARAMETER_GROUP, result.getErrors().get(2).getCode());
+        Assert.assertEquals(ComponentVerifier.VerificationError.StandardCode.INCOMPLETE_PARAMETER_GROUP, result.getErrors().get(0).getCode());
+        Assert.assertEquals(ComponentVerifier.VerificationError.StandardCode.INCOMPLETE_PARAMETER_GROUP, result.getErrors().get(1).getCode());
+        Assert.assertEquals(ComponentVerifier.VerificationError.StandardCode.INCOMPLETE_PARAMETER_GROUP, result.getErrors().get(2).getCode());
     }
 
     // *********************************
@@ -148,10 +145,10 @@ public class SalesforceComponentVerifierTest extends CamelTestSupport {
         Assert.assertEquals(2, result.getErrors().size());
 
         // Exception
-        Assert.assertEquals(VerificationError.StandardCode.EXCEPTION, result.getErrors().get(0).getCode());
-        Assert.assertNotNull(result.getErrors().get(0).getDetails().get(VerificationError.ExceptionAttribute.EXCEPTION_INSTANCE));
-        Assert.assertTrue(result.getErrors().get(0).getDetails().get(VerificationError.ExceptionAttribute.EXCEPTION_INSTANCE) instanceof SalesforceException);
-        Assert.assertEquals(400, result.getErrors().get(0).getDetails().get(VerificationError.HttpAttribute.HTTP_CODE));
+        Assert.assertEquals(ComponentVerifier.VerificationError.StandardCode.EXCEPTION, result.getErrors().get(0).getCode());
+        Assert.assertNotNull(result.getErrors().get(0).getDetails().get(ComponentVerifier.VerificationError.ExceptionAttribute.EXCEPTION_INSTANCE));
+        Assert.assertTrue(result.getErrors().get(0).getDetails().get(ComponentVerifier.VerificationError.ExceptionAttribute.EXCEPTION_INSTANCE) instanceof SalesforceException);
+        Assert.assertEquals(400, result.getErrors().get(0).getDetails().get(ComponentVerifier.VerificationError.HttpAttribute.HTTP_CODE));
 
         // Salesforce Error
         Assert.assertEquals("invalid_grant", result.getErrors().get(1).getDetail("salesforce_code"));
@@ -171,9 +168,9 @@ public class SalesforceComponentVerifierTest extends CamelTestSupport {
         Assert.assertEquals(2, result.getErrors().size());
 
         // Exception
-        Assert.assertEquals(VerificationError.StandardCode.EXCEPTION, result.getErrors().get(0).getCode());
-        Assert.assertNotNull(result.getErrors().get(0).getDetails().get(VerificationError.ExceptionAttribute.EXCEPTION_INSTANCE));
-        Assert.assertTrue(result.getErrors().get(0).getDetails().get(VerificationError.ExceptionAttribute.EXCEPTION_INSTANCE) instanceof SalesforceException);
+        Assert.assertEquals(ComponentVerifier.VerificationError.StandardCode.EXCEPTION, result.getErrors().get(0).getCode());
+        Assert.assertNotNull(result.getErrors().get(0).getDetails().get(ComponentVerifier.VerificationError.ExceptionAttribute.EXCEPTION_INSTANCE));
+        Assert.assertTrue(result.getErrors().get(0).getDetails().get(ComponentVerifier.VerificationError.ExceptionAttribute.EXCEPTION_INSTANCE) instanceof SalesforceException);
         Assert.assertEquals(400, result.getErrors().get(0).getDetails().get(ComponentVerifier.VerificationError.HttpAttribute.HTTP_CODE));
 
         // Salesforce Error

http://git-wip-us.apache.org/repos/asf/camel/blob/42529399/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowComponent.java
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowComponent.java b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowComponent.java
index 8a5ab9e..ff414c8 100644
--- a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowComponent.java
+++ b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowComponent.java
@@ -16,14 +16,19 @@
  */
 package org.apache.camel.component.servicenow;
 
+import java.util.Collection;
+import java.util.Collections;
 import java.util.Map;
+import java.util.Optional;
 
 import org.apache.camel.CamelContext;
 import org.apache.camel.ComponentVerifier;
 import org.apache.camel.Endpoint;
 import org.apache.camel.SSLContextParametersAware;
 import org.apache.camel.VerifiableComponent;
-import org.apache.camel.impl.UriEndpointComponent;
+import org.apache.camel.component.extension.ComponentExtension;
+import org.apache.camel.component.extension.ComponentVerifierExtension;
+import org.apache.camel.impl.DefaultComponent;
 import org.apache.camel.spi.Metadata;
 import org.apache.camel.util.EndpointHelper;
 import org.apache.camel.util.IntrospectionSupport;
@@ -32,7 +37,7 @@ import org.apache.camel.util.IntrospectionSupport;
  * Represents the component that manages {@link ServiceNowEndpoint}.
  */
 @Metadata(label = "verifiers", enums = "parameters,connectivity")
-public class ServiceNowComponent extends UriEndpointComponent implements VerifiableComponent, SSLContextParametersAware {
+public class ServiceNowComponent extends DefaultComponent implements VerifiableComponent, SSLContextParametersAware {
 
     @Metadata(label = "advanced")
     private ServiceNowConfiguration configuration;
@@ -40,7 +45,11 @@ public class ServiceNowComponent extends UriEndpointComponent implements Verifia
     private boolean useGlobalSslContextParameters;
 
     public ServiceNowComponent() {
-        super(ServiceNowEndpoint.class);
+        this.configuration = new ServiceNowConfiguration();
+    }
+
+    public ServiceNowComponent(CamelContext camelContext) {
+        super(camelContext);
 
         this.configuration = new ServiceNowConfiguration();
     }
@@ -183,10 +192,24 @@ public class ServiceNowComponent extends UriEndpointComponent implements Verifia
         this.useGlobalSslContextParameters = useGlobalSslContextParameters;
     }
 
-    /**
-     * TODO: document
-     */
+    @Override
     public ComponentVerifier getVerifier() {
-        return new ServiceNowComponentVerifier(this);
+        return new ServiceNowComponentVerifierExtension(this);
+    }
+
+    @Override
+    public Collection<Class<? extends ComponentExtension>> getExtensionTypes() {
+        return Collections.singletonList(ComponentVerifierExtension.class);
+    }
+
+    @Override
+    public <T extends ComponentExtension> Optional<T> getExtension(Class<T> extensionType) {
+        if (ComponentVerifierExtension.class.isAssignableFrom(extensionType)) {
+            return Optional.of(
+                extensionType.cast(new ServiceNowComponentVerifierExtension(this))
+            );
+        }
+
+        return Optional.empty();
     }
 }

http://git-wip-us.apache.org/repos/asf/camel/blob/42529399/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowComponentVerifier.java
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowComponentVerifier.java b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowComponentVerifier.java
deleted file mode 100644
index 8d4cf9d..0000000
--- a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowComponentVerifier.java
+++ /dev/null
@@ -1,113 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.camel.component.servicenow;
-
-import java.util.Map;
-import javax.ws.rs.HttpMethod;
-import javax.ws.rs.core.MediaType;
-
-import org.apache.camel.ComponentVerifier;
-import org.apache.camel.NoSuchOptionException;
-import org.apache.camel.impl.verifier.DefaultComponentVerifier;
-import org.apache.camel.impl.verifier.ResultBuilder;
-import org.apache.camel.impl.verifier.ResultErrorBuilder;
-
-public class ServiceNowComponentVerifier extends DefaultComponentVerifier {
-    private final ServiceNowComponent component;
-
-    ServiceNowComponentVerifier(ServiceNowComponent component) {
-        super("servicenow", component.getCamelContext());
-
-        this.component = component;
-    }
-
-    // *********************************
-    // Parameters validation
-    // *********************************
-
-    @Override
-    protected Result verifyParameters(Map<String, Object> parameters) {
-        ResultBuilder builder = ResultBuilder.withStatusAndScope(Result.Status.OK, Scope.PARAMETERS);
-
-        // Validate using the catalog
-        super.verifyParametersAgainstCatalog(builder, parameters);
-
-        return builder.build();
-    }
-
-    // *********************************
-    // Connectivity validation
-    // *********************************
-
-    @Override
-    protected Result verifyConnectivity(Map<String, Object> parameters) {
-        // Default is success
-        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));
-            }
-
-            new ServiceNowClient(getCamelContext(), configuration)
-                .types(MediaType.APPLICATION_JSON_TYPE)
-                .path("now")
-                .path(configuration.getApiVersion())
-                .path("table")
-                .path(tableName)
-                .query(ServiceNowParams.SYSPARM_LIMIT.getId(), 1L)
-                .invoke(HttpMethod.GET);
-        } catch (NoSuchOptionException e) {
-            builder.error(
-                ResultErrorBuilder.withMissingOption(e.getOptionName()).build()
-            );
-        } catch (ServiceNowException e) {
-            ResultErrorBuilder errorBuilder = ResultErrorBuilder.withException(e)
-                .detail(VerificationError.HttpAttribute.HTTP_CODE, e.getCode())
-                .detail("servicenow_error_message", e.getMessage())
-                .detail("servicenow_error_status", e.getStatus())
-                .detail("servicenow_error_detail", e.getDetail());
-
-            if (e.getCode() == 401) {
-                errorBuilder.code(VerificationError.StandardCode.AUTHENTICATION);
-                errorBuilder.parameterKey("userName");
-                errorBuilder.parameterKey("password");
-                errorBuilder.parameterKey("oauthClientId");
-                errorBuilder.parameterKey("oauthClientSecret");
-            }
-
-            builder.error(errorBuilder.build());
-        } catch (Exception e) {
-            builder.error(
-                ResultErrorBuilder.withException(e).build()
-            );
-        }
-
-        return builder.build();
-    }
-}

http://git-wip-us.apache.org/repos/asf/camel/blob/42529399/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowComponentVerifierExtension.java
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowComponentVerifierExtension.java b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowComponentVerifierExtension.java
new file mode 100644
index 0000000..96313d2
--- /dev/null
+++ b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowComponentVerifierExtension.java
@@ -0,0 +1,112 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.servicenow;
+
+import java.util.Map;
+import javax.ws.rs.HttpMethod;
+import javax.ws.rs.core.MediaType;
+
+import org.apache.camel.component.extension.verifier.DefaultComponentVerifierExtension;
+import org.apache.camel.component.extension.verifier.NoSuchOptionException;
+import org.apache.camel.component.extension.verifier.ResultBuilder;
+import org.apache.camel.component.extension.verifier.ResultErrorBuilder;
+
+public class ServiceNowComponentVerifierExtension extends DefaultComponentVerifierExtension {
+    private final ServiceNowComponent component;
+
+    ServiceNowComponentVerifierExtension(ServiceNowComponent component) {
+        super("servicenow", component.getCamelContext());
+
+        this.component = component;
+    }
+
+    // *********************************
+    // Parameters validation
+    // *********************************
+
+    @Override
+    protected Result verifyParameters(Map<String, Object> parameters) {
+        ResultBuilder builder = ResultBuilder.withStatusAndScope(Result.Status.OK, Scope.PARAMETERS);
+
+        // Validate using the catalog
+        super.verifyParametersAgainstCatalog(builder, parameters);
+
+        return builder.build();
+    }
+
+    // *********************************
+    // Connectivity validation
+    // *********************************
+
+    @Override
+    protected Result verifyConnectivity(Map<String, Object> parameters) {
+        // Default is success
+        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));
+            }
+
+            new ServiceNowClient(getCamelContext(), configuration)
+                .types(MediaType.APPLICATION_JSON_TYPE)
+                .path("now")
+                .path(configuration.getApiVersion())
+                .path("table")
+                .path(tableName)
+                .query(ServiceNowParams.SYSPARM_LIMIT.getId(), 1L)
+                .invoke(HttpMethod.GET);
+        } catch (NoSuchOptionException e) {
+            builder.error(
+                ResultErrorBuilder.withMissingOption(e.getOptionName()).build()
+            );
+        } catch (ServiceNowException e) {
+            ResultErrorBuilder errorBuilder = ResultErrorBuilder.withException(e)
+                .detail(VerificationError.HttpAttribute.HTTP_CODE, e.getCode())
+                .detail("servicenow_error_message", e.getMessage())
+                .detail("servicenow_error_status", e.getStatus())
+                .detail("servicenow_error_detail", e.getDetail());
+
+            if (e.getCode() == 401) {
+                errorBuilder.code(VerificationError.StandardCode.AUTHENTICATION);
+                errorBuilder.parameterKey("userName");
+                errorBuilder.parameterKey("password");
+                errorBuilder.parameterKey("oauthClientId");
+                errorBuilder.parameterKey("oauthClientSecret");
+            }
+
+            builder.error(errorBuilder.build());
+        } catch (Exception e) {
+            builder.error(
+                ResultErrorBuilder.withException(e).build()
+            );
+        }
+
+        return builder.build();
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/42529399/components/camel-servicenow/src/test/java/org/apache/camel/component/servicenow/ServiceNowComponentVerifierExtensionTest.java
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/src/test/java/org/apache/camel/component/servicenow/ServiceNowComponentVerifierExtensionTest.java b/components/camel-servicenow/src/test/java/org/apache/camel/component/servicenow/ServiceNowComponentVerifierExtensionTest.java
new file mode 100644
index 0000000..a06d503
--- /dev/null
+++ b/components/camel-servicenow/src/test/java/org/apache/camel/component/servicenow/ServiceNowComponentVerifierExtensionTest.java
@@ -0,0 +1,151 @@
+/**
+ * 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.servicenow;
+
+import java.util.Map;
+import javax.ws.rs.ProcessingException;
+
+import org.apache.camel.Component;
+import org.apache.camel.component.extension.ComponentVerifierExtension;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class ServiceNowComponentVerifierExtensionTest extends ServiceNowTestSupport {
+    public ServiceNowComponentVerifierExtensionTest() {
+        super(false);
+    }
+
+    @Override
+    public boolean isUseRouteBuilder() {
+        return false;
+    }
+
+    protected ComponentVerifierExtension getExtension() {
+        Component component = context().getComponent("servicenow");
+        ComponentVerifierExtension verifier = component.getExtension(ComponentVerifierExtension.class).orElseThrow(IllegalStateException::new);
+
+        return verifier;
+    }
+
+    // *********************************
+    // Parameters validation
+    // *********************************
+
+    @Test
+    public void testParameter() {
+        Map<String, Object> parameters = getParameters();
+        ComponentVerifierExtension.Result result = getExtension().verify(ComponentVerifierExtension.Scope.PARAMETERS, parameters);
+
+        Assert.assertEquals(ComponentVerifierExtension.Result.Status.OK, result.getStatus());
+    }
+
+    @Test
+    public void testMissingMandatoryParameter() {
+        Map<String, Object> parameters = getParameters();
+        parameters.remove("instanceName");
+        ComponentVerifierExtension.Result result = getExtension().verify(ComponentVerifierExtension.Scope.PARAMETERS, parameters);
+
+        Assert.assertEquals(ComponentVerifierExtension.Result.Status.ERROR, result.getStatus());
+        Assert.assertEquals(1, result.getErrors().size());
+        Assert.assertEquals(ComponentVerifierExtension.VerificationError.StandardCode.MISSING_PARAMETER, result.getErrors().get(0).getCode());
+        Assert.assertEquals("instanceName", result.getErrors().get(0).getParameterKeys().iterator().next());
+    }
+
+    @Test
+    public void testMissingMandatoryAuthenticationParameter() {
+        Map<String, Object> parameters = getParameters();
+        parameters.remove("userName");
+        ComponentVerifierExtension.Result result = getExtension().verify(ComponentVerifierExtension.Scope.PARAMETERS, parameters);
+
+        Assert.assertEquals(ComponentVerifierExtension.Result.Status.ERROR, result.getStatus());
+        Assert.assertEquals(1, result.getErrors().size());
+        Assert.assertEquals(ComponentVerifierExtension.VerificationError.StandardCode.MISSING_PARAMETER, result.getErrors().get(0).getCode());
+        Assert.assertEquals("userName", result.getErrors().get(0).getParameterKeys().iterator().next());
+    }
+
+    // *********************************
+    // Connectivity validation
+    // *********************************
+
+    @Test
+    public void testConnectivity() {
+        Map<String, Object> parameters = getParameters();
+        ComponentVerifierExtension.Result result = getExtension().verify(ComponentVerifierExtension.Scope.CONNECTIVITY, parameters);
+
+        Assert.assertEquals(ComponentVerifierExtension.Result.Status.OK, result.getStatus());
+    }
+
+    @Test
+    public void testConnectivityOnCustomTable() {
+        Map<String, Object> parameters = getParameters();
+        parameters.put("table", "ticket");
+
+        ComponentVerifierExtension.Result result = getExtension().verify(ComponentVerifierExtension.Scope.CONNECTIVITY, parameters);
+
+        Assert.assertEquals(ComponentVerifierExtension.Result.Status.OK, result.getStatus());
+    }
+
+    @Test
+    public void testConnectivityWithWrongInstance() {
+        Map<String, Object> parameters = getParameters();
+        parameters.put("instanceName", "unknown-instance");
+
+        ComponentVerifierExtension.Result result = getExtension().verify(ComponentVerifierExtension.Scope.CONNECTIVITY, parameters);
+
+        Assert.assertEquals(ComponentVerifierExtension.Result.Status.ERROR, result.getStatus());
+        Assert.assertEquals(1, result.getErrors().size());
+        Assert.assertEquals(ComponentVerifierExtension.VerificationError.StandardCode.EXCEPTION, result.getErrors().get(0).getCode());
+        Assert.assertNotNull(result.getErrors().get(0).getDetails().get(ComponentVerifierExtension.VerificationError.ExceptionAttribute.EXCEPTION_INSTANCE));
+        Assert.assertTrue(result.getErrors().get(0).getDetails().get(ComponentVerifierExtension.VerificationError.ExceptionAttribute.EXCEPTION_INSTANCE) instanceof ProcessingException);
+    }
+
+    @Test
+    public void testConnectivityWithWrongTable() {
+        Map<String, Object> parameters = getParameters();
+        parameters.put("table", "unknown");
+
+        ComponentVerifierExtension.Result result = getExtension().verify(ComponentVerifierExtension.Scope.CONNECTIVITY, parameters);
+
+        Assert.assertEquals(ComponentVerifierExtension.Result.Status.ERROR, result.getStatus());
+        Assert.assertEquals(1, result.getErrors().size());
+        Assert.assertEquals(ComponentVerifierExtension.VerificationError.StandardCode.EXCEPTION, result.getErrors().get(0).getCode());
+        Assert.assertNotNull(result.getErrors().get(0).getDetails().get(ComponentVerifierExtension.VerificationError.ExceptionAttribute.EXCEPTION_INSTANCE));
+        Assert.assertEquals(400, result.getErrors().get(0).getDetails().get(ComponentVerifierExtension.VerificationError.HttpAttribute.HTTP_CODE));
+        Assert.assertTrue(result.getErrors().get(0).getDetails().get(ComponentVerifierExtension.VerificationError.ExceptionAttribute.EXCEPTION_INSTANCE) instanceof ServiceNowException);
+    }
+
+    @Test
+    public void testConnectivityWithWrongAuthentication() {
+        Map<String, Object> parameters = getParameters();
+        parameters.put("userName", "unknown-user");
+        parameters.remove("oauthClientId");
+        parameters.remove("oauthClientSecret");
+
+        ComponentVerifierExtension.Result result = getExtension().verify(ComponentVerifierExtension.Scope.CONNECTIVITY, parameters);
+
+        Assert.assertEquals(ComponentVerifierExtension.Result.Status.ERROR, result.getStatus());
+        Assert.assertEquals(1, result.getErrors().size());
+        Assert.assertEquals(ComponentVerifierExtension.VerificationError.StandardCode.AUTHENTICATION, result.getErrors().get(0).getCode());
+        Assert.assertNotNull(result.getErrors().get(0).getDetails().get(ComponentVerifierExtension.VerificationError.ExceptionAttribute.EXCEPTION_INSTANCE));
+        Assert.assertEquals(401, result.getErrors().get(0).getDetails().get(ComponentVerifierExtension.VerificationError.HttpAttribute.HTTP_CODE));
+        Assert.assertTrue(result.getErrors().get(0).getDetails().get(ComponentVerifierExtension.VerificationError.ExceptionAttribute.EXCEPTION_INSTANCE) instanceof ServiceNowException);
+        Assert.assertTrue(result.getErrors().get(0).getParameterKeys().contains("userName"));
+        Assert.assertTrue(result.getErrors().get(0).getParameterKeys().contains("password"));
+        Assert.assertTrue(result.getErrors().get(0).getParameterKeys().contains("oauthClientId"));
+        Assert.assertTrue(result.getErrors().get(0).getParameterKeys().contains("oauthClientSecret"));
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/42529399/components/camel-servicenow/src/test/java/org/apache/camel/component/servicenow/ServiceNowComponentVerifierTest.java
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/src/test/java/org/apache/camel/component/servicenow/ServiceNowComponentVerifierTest.java b/components/camel-servicenow/src/test/java/org/apache/camel/component/servicenow/ServiceNowComponentVerifierTest.java
index 1fcd5bc..ddb3109 100644
--- a/components/camel-servicenow/src/test/java/org/apache/camel/component/servicenow/ServiceNowComponentVerifierTest.java
+++ b/components/camel-servicenow/src/test/java/org/apache/camel/component/servicenow/ServiceNowComponentVerifierTest.java
@@ -17,11 +17,9 @@
 package org.apache.camel.component.servicenow;
 
 import java.util.Map;
-
 import javax.ws.rs.ProcessingException;
 
 import org.apache.camel.ComponentVerifier;
-import org.apache.camel.ComponentVerifier.VerificationError;
 import org.junit.Assert;
 import org.junit.Test;
 
@@ -35,9 +33,9 @@ public class ServiceNowComponentVerifierTest extends ServiceNowTestSupport {
         return false;
     }
 
-    protected ServiceNowComponentVerifier getVerifier() {
+    protected ServiceNowComponentVerifierExtension getVerifier() {
         ServiceNowComponent component = context().getComponent("servicenow", ServiceNowComponent.class);
-        ServiceNowComponentVerifier verifier = (ServiceNowComponentVerifier)component.getVerifier();
+        ServiceNowComponentVerifierExtension verifier = (ServiceNowComponentVerifierExtension)component.getVerifier();
 
         return verifier;
     }
@@ -62,7 +60,7 @@ public class ServiceNowComponentVerifierTest extends ServiceNowTestSupport {
 
         Assert.assertEquals(ComponentVerifier.Result.Status.ERROR, result.getStatus());
         Assert.assertEquals(1, result.getErrors().size());
-        Assert.assertEquals(VerificationError.StandardCode.MISSING_PARAMETER, result.getErrors().get(0).getCode());
+        Assert.assertEquals(ComponentVerifier.VerificationError.StandardCode.MISSING_PARAMETER, result.getErrors().get(0).getCode());
         Assert.assertEquals("instanceName", result.getErrors().get(0).getParameterKeys().iterator().next());
     }
 
@@ -74,7 +72,7 @@ public class ServiceNowComponentVerifierTest extends ServiceNowTestSupport {
 
         Assert.assertEquals(ComponentVerifier.Result.Status.ERROR, result.getStatus());
         Assert.assertEquals(1, result.getErrors().size());
-        Assert.assertEquals(VerificationError.StandardCode.MISSING_PARAMETER, result.getErrors().get(0).getCode());
+        Assert.assertEquals(ComponentVerifier.VerificationError.StandardCode.MISSING_PARAMETER, result.getErrors().get(0).getCode());
         Assert.assertEquals("userName", result.getErrors().get(0).getParameterKeys().iterator().next());
     }
 
@@ -109,9 +107,9 @@ public class ServiceNowComponentVerifierTest extends ServiceNowTestSupport {
 
         Assert.assertEquals(ComponentVerifier.Result.Status.ERROR, result.getStatus());
         Assert.assertEquals(1, result.getErrors().size());
-        Assert.assertEquals(VerificationError.StandardCode.EXCEPTION, result.getErrors().get(0).getCode());
-        Assert.assertNotNull(result.getErrors().get(0).getDetails().get(VerificationError.ExceptionAttribute.EXCEPTION_INSTANCE));
-        Assert.assertTrue(result.getErrors().get(0).getDetails().get(VerificationError.ExceptionAttribute.EXCEPTION_INSTANCE) instanceof ProcessingException);
+        Assert.assertEquals(ComponentVerifier.VerificationError.StandardCode.EXCEPTION, result.getErrors().get(0).getCode());
+        Assert.assertNotNull(result.getErrors().get(0).getDetails().get(ComponentVerifier.VerificationError.ExceptionAttribute.EXCEPTION_INSTANCE));
+        Assert.assertTrue(result.getErrors().get(0).getDetails().get(ComponentVerifier.VerificationError.ExceptionAttribute.EXCEPTION_INSTANCE) instanceof ProcessingException);
     }
 
     @Test
@@ -123,10 +121,10 @@ public class ServiceNowComponentVerifierTest extends ServiceNowTestSupport {
 
         Assert.assertEquals(ComponentVerifier.Result.Status.ERROR, result.getStatus());
         Assert.assertEquals(1, result.getErrors().size());
-        Assert.assertEquals(VerificationError.StandardCode.EXCEPTION, result.getErrors().get(0).getCode());
-        Assert.assertNotNull(result.getErrors().get(0).getDetails().get(VerificationError.ExceptionAttribute.EXCEPTION_INSTANCE));
-        Assert.assertEquals(400, result.getErrors().get(0).getDetails().get(VerificationError.HttpAttribute.HTTP_CODE));
-        Assert.assertTrue(result.getErrors().get(0).getDetails().get(VerificationError.ExceptionAttribute.EXCEPTION_INSTANCE) instanceof ServiceNowException);
+        Assert.assertEquals(ComponentVerifier.VerificationError.StandardCode.EXCEPTION, result.getErrors().get(0).getCode());
+        Assert.assertNotNull(result.getErrors().get(0).getDetails().get(ComponentVerifier.VerificationError.ExceptionAttribute.EXCEPTION_INSTANCE));
+        Assert.assertEquals(400, result.getErrors().get(0).getDetails().get(ComponentVerifier.VerificationError.HttpAttribute.HTTP_CODE));
+        Assert.assertTrue(result.getErrors().get(0).getDetails().get(ComponentVerifier.VerificationError.ExceptionAttribute.EXCEPTION_INSTANCE) instanceof ServiceNowException);
     }
 
     @Test
@@ -140,10 +138,10 @@ public class ServiceNowComponentVerifierTest extends ServiceNowTestSupport {
 
         Assert.assertEquals(ComponentVerifier.Result.Status.ERROR, result.getStatus());
         Assert.assertEquals(1, result.getErrors().size());
-        Assert.assertEquals(VerificationError.StandardCode.AUTHENTICATION, result.getErrors().get(0).getCode());
-        Assert.assertNotNull(result.getErrors().get(0).getDetails().get(VerificationError.ExceptionAttribute.EXCEPTION_INSTANCE));
-        Assert.assertEquals(401, result.getErrors().get(0).getDetails().get(VerificationError.HttpAttribute.HTTP_CODE));
-        Assert.assertTrue(result.getErrors().get(0).getDetails().get(VerificationError.ExceptionAttribute.EXCEPTION_INSTANCE) instanceof ServiceNowException);
+        Assert.assertEquals(ComponentVerifier.VerificationError.StandardCode.AUTHENTICATION, result.getErrors().get(0).getCode());
+        Assert.assertNotNull(result.getErrors().get(0).getDetails().get(ComponentVerifier.VerificationError.ExceptionAttribute.EXCEPTION_INSTANCE));
+        Assert.assertEquals(401, result.getErrors().get(0).getDetails().get(ComponentVerifier.VerificationError.HttpAttribute.HTTP_CODE));
+        Assert.assertTrue(result.getErrors().get(0).getDetails().get(ComponentVerifier.VerificationError.ExceptionAttribute.EXCEPTION_INSTANCE) instanceof ServiceNowException);
         Assert.assertTrue(result.getErrors().get(0).getParameterKeys().contains("userName"));
         Assert.assertTrue(result.getErrors().get(0).getParameterKeys().contains("password"));
         Assert.assertTrue(result.getErrors().get(0).getParameterKeys().contains("oauthClientId"));

http://git-wip-us.apache.org/repos/asf/camel/blob/42529399/components/camel-twitter/src/main/java/org/apache/camel/component/twitter/AbstractTwitterComponent.java
----------------------------------------------------------------------
diff --git a/components/camel-twitter/src/main/java/org/apache/camel/component/twitter/AbstractTwitterComponent.java b/components/camel-twitter/src/main/java/org/apache/camel/component/twitter/AbstractTwitterComponent.java
index d86f603..552b548 100644
--- a/components/camel-twitter/src/main/java/org/apache/camel/component/twitter/AbstractTwitterComponent.java
+++ b/components/camel-twitter/src/main/java/org/apache/camel/component/twitter/AbstractTwitterComponent.java
@@ -22,6 +22,7 @@ import org.apache.camel.CamelContext;
 import org.apache.camel.ComponentVerifier;
 import org.apache.camel.Endpoint;
 import org.apache.camel.VerifiableComponent;
+import org.apache.camel.component.extension.ComponentVerifierExtension;
 import org.apache.camel.impl.DefaultComponent;
 import org.apache.camel.spi.Metadata;
 
@@ -29,7 +30,6 @@ import org.apache.camel.spi.Metadata;
  * Base Twitter component
  */
 public abstract class AbstractTwitterComponent extends DefaultComponent implements VerifiableComponent {
-
     @Metadata(label = "security", secret = true)
     private String consumerKey;
     @Metadata(label = "security", secret = true)
@@ -47,13 +47,17 @@ public abstract class AbstractTwitterComponent extends DefaultComponent implemen
     @Metadata(label = "proxy")
     private Integer httpProxyPort;
 
-    public AbstractTwitterComponent() {
+    protected AbstractTwitterComponent(String componentVerifierScheme) {
+        this(null, componentVerifierScheme);
     }
 
-    public AbstractTwitterComponent(CamelContext context) {
+    protected AbstractTwitterComponent(CamelContext context, String componentVerifierScheme) {
         super(context);
+
+        registerExtension(() -> new TwitterComponentVerifierExtension(componentVerifierScheme));
     }
 
+    @Override
     protected Endpoint createEndpoint(String uri, String remaining, Map<String, Object> parameters) throws Exception {
         TwitterConfiguration properties = new TwitterConfiguration();
         properties.setConsumerKey(consumerKey);
@@ -162,4 +166,11 @@ public abstract class AbstractTwitterComponent extends DefaultComponent implemen
         return httpProxyPort;
     }
 
+    /**
+     * Get a verifier for the component.
+     */
+    @Override
+    public ComponentVerifier getVerifier() {
+        return (scope, parameters) -> getExtension(ComponentVerifierExtension.class).orElseThrow(UnsupportedOperationException::new).verify(scope, parameters);
+    }
 }

http://git-wip-us.apache.org/repos/asf/camel/blob/42529399/components/camel-twitter/src/main/java/org/apache/camel/component/twitter/DefaultTwitterComponentVerifier.java
----------------------------------------------------------------------
diff --git a/components/camel-twitter/src/main/java/org/apache/camel/component/twitter/DefaultTwitterComponentVerifier.java b/components/camel-twitter/src/main/java/org/apache/camel/component/twitter/DefaultTwitterComponentVerifier.java
deleted file mode 100644
index cdc1d6e..0000000
--- a/components/camel-twitter/src/main/java/org/apache/camel/component/twitter/DefaultTwitterComponentVerifier.java
+++ /dev/null
@@ -1,95 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.camel.component.twitter;
-
-import java.util.Map;
-
-import org.apache.camel.ComponentVerifier;
-import org.apache.camel.impl.verifier.DefaultComponentVerifier;
-import org.apache.camel.impl.verifier.ResultBuilder;
-import org.apache.camel.impl.verifier.ResultErrorBuilder;
-import org.apache.camel.impl.verifier.ResultErrorHelper;
-import twitter4j.Twitter;
-import twitter4j.TwitterException;
-
-public class DefaultTwitterComponentVerifier extends DefaultComponentVerifier {
-
-    public DefaultTwitterComponentVerifier(AbstractTwitterComponent component) {
-        super("twitter", component.getCamelContext());
-    }
-
-    public DefaultTwitterComponentVerifier(AbstractTwitterComponent component, String scheme) {
-        super(scheme, component.getCamelContext());
-    }
-
-    // *********************************
-    // Parameters validation
-    // *********************************
-
-    @Override
-    protected Result verifyParameters(Map<String, Object> parameters) {
-        ResultBuilder builder = ResultBuilder.withStatusAndScope(Result.Status.OK, Scope.PARAMETERS)
-            .error(ResultErrorHelper.requiresOption("accessToken", parameters))
-            .error(ResultErrorHelper.requiresOption("accessTokenSecret", parameters))
-            .error(ResultErrorHelper.requiresOption("consumerKey", parameters))
-            .error(ResultErrorHelper.requiresOption("consumerSecret", parameters));
-
-        // Validate using the catalog
-        super.verifyParametersAgainstCatalog(builder, parameters);
-
-        return builder.build();
-    }
-
-    // *********************************
-    // Connectivity validation
-    // *********************************
-
-    @Override
-    protected Result verifyConnectivity(Map<String, Object> parameters) {
-        return ResultBuilder.withStatusAndScope(Result.Status.OK, Scope.CONNECTIVITY)
-            .error(parameters, this::verifyCredentials)
-            .build();
-    }
-
-    private void verifyCredentials(ResultBuilder builder, Map<String, Object> parameters) throws Exception {
-        try {
-            TwitterConfiguration configuration = setProperties(new TwitterConfiguration(), parameters);
-            Twitter twitter = configuration.getTwitter();
-
-            twitter.verifyCredentials();
-        } catch (TwitterException e) {
-            // verifyCredentials throws TwitterException when Twitter service or
-            // network is unavailable or if supplied credential is wrong
-            ResultErrorBuilder errorBuilder = ResultErrorBuilder.withCodeAndDescription(VerificationError.StandardCode.AUTHENTICATION, e.getErrorMessage())
-                .detail("twitter_error_code", e.getErrorCode())
-                .detail("twitter_status_code", e.getStatusCode())
-                .detail("twitter_exception_code", e.getExceptionCode())
-                .detail("twitter_exception_message", e.getMessage())
-                .detail("twitter_exception_caused-by-network-issue", e.isCausedByNetworkIssue())
-                .detail(ComponentVerifier.VerificationError.ExceptionAttribute.EXCEPTION_CLASS, e.getClass().getName())
-                .detail(ComponentVerifier.VerificationError.ExceptionAttribute.EXCEPTION_INSTANCE, e);
-
-            // For a complete list of error codes see:
-            //   https://dev.twitter.com/overview/api/response-codes
-            if (e.getErrorCode() == 89) {
-                errorBuilder.parameterKey("accessToken");
-            }
-
-            builder.error(errorBuilder.build());
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/camel/blob/42529399/components/camel-twitter/src/main/java/org/apache/camel/component/twitter/TwitterComponent.java
----------------------------------------------------------------------
diff --git a/components/camel-twitter/src/main/java/org/apache/camel/component/twitter/TwitterComponent.java b/components/camel-twitter/src/main/java/org/apache/camel/component/twitter/TwitterComponent.java
index a1b7e5d..92ea505 100644
--- a/components/camel-twitter/src/main/java/org/apache/camel/component/twitter/TwitterComponent.java
+++ b/components/camel-twitter/src/main/java/org/apache/camel/component/twitter/TwitterComponent.java
@@ -19,12 +19,7 @@ package org.apache.camel.component.twitter;
 import java.util.Map;
 
 import org.apache.camel.CamelContext;
-import org.apache.camel.ComponentVerifier;
 import org.apache.camel.Endpoint;
-import org.apache.camel.VerifiableComponent;
-import org.apache.camel.component.twitter.data.ConsumerType;
-import org.apache.camel.component.twitter.data.EndpointType;
-import org.apache.camel.impl.DefaultComponent;
 import org.apache.camel.spi.Metadata;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -35,7 +30,7 @@ import org.slf4j.LoggerFactory;
  * @deprecated Use
  * {@link org.apache.camel.component.twitter.directmessage.TwitterDirectMessageComponent},
  * {@link org.apache.camel.component.twitter.search.TwitterSearchComponent},
- * {@link org.apache.camel.component.twitter.streaming..TwitterStreamingComponent} or
+ * {@link org.apache.camel.component.twitter.streaming.TwitterStreamingComponent} or
  * {@link org.apache.camel.component.twitter.timeline.TwitterTimelineComponent}
  * instead.
  */
@@ -46,12 +41,14 @@ public class TwitterComponent extends AbstractTwitterComponent {
     private static final Logger LOG = LoggerFactory.getLogger(TwitterComponent.class);
 
     public TwitterComponent() {
+        super("twitter");
     }
 
     public TwitterComponent(CamelContext context) {
-        super(context);
+        super(context, "twitter");
     }
 
+    @Override
     protected Endpoint doCreateEndpoint(TwitterConfiguration properties, String uri, String remaining, Map<String, Object> parameters) throws Exception {
         String[] tokens = remaining.split("/");
         LOG.warn("The scheme syntax 'twitter:{}' has been deprecated. Use 'twitter-{}' instead.", tokens[0], tokens[0]);
@@ -73,11 +70,4 @@ public class TwitterComponent extends AbstractTwitterComponent {
         endpoint.setKeywords(getAndRemoveParameter(parameters, "keywords", String.class));
         return endpoint;
     }
-
-    /**
-     * Get a verifier for the twitter component.
-     */
-    public ComponentVerifier getVerifier() {
-        return new DefaultTwitterComponentVerifier(this);
-    }
 }

http://git-wip-us.apache.org/repos/asf/camel/blob/42529399/components/camel-twitter/src/main/java/org/apache/camel/component/twitter/TwitterComponentVerifierExtension.java
----------------------------------------------------------------------
diff --git a/components/camel-twitter/src/main/java/org/apache/camel/component/twitter/TwitterComponentVerifierExtension.java b/components/camel-twitter/src/main/java/org/apache/camel/component/twitter/TwitterComponentVerifierExtension.java
new file mode 100644
index 0000000..f92fa84
--- /dev/null
+++ b/components/camel-twitter/src/main/java/org/apache/camel/component/twitter/TwitterComponentVerifierExtension.java
@@ -0,0 +1,94 @@
+/**
+ * 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.twitter;
+
+import java.util.Map;
+
+import org.apache.camel.component.extension.verifier.DefaultComponentVerifierExtension;
+import org.apache.camel.component.extension.verifier.ResultBuilder;
+import org.apache.camel.component.extension.verifier.ResultErrorBuilder;
+import org.apache.camel.component.extension.verifier.ResultErrorHelper;
+import twitter4j.Twitter;
+import twitter4j.TwitterException;
+
+public final class TwitterComponentVerifierExtension extends DefaultComponentVerifierExtension {
+
+    public TwitterComponentVerifierExtension() {
+        this("twitter");
+    }
+
+    public TwitterComponentVerifierExtension(String scheme) {
+        super(scheme);
+    }
+
+    // *********************************
+    // Parameters validation
+    // *********************************
+
+    @Override
+    protected Result verifyParameters(Map<String, Object> parameters) {
+        ResultBuilder builder = ResultBuilder.withStatusAndScope(Result.Status.OK, Scope.PARAMETERS)
+            .error(ResultErrorHelper.requiresOption("accessToken", parameters))
+            .error(ResultErrorHelper.requiresOption("accessTokenSecret", parameters))
+            .error(ResultErrorHelper.requiresOption("consumerKey", parameters))
+            .error(ResultErrorHelper.requiresOption("consumerSecret", parameters));
+
+        // Validate using the catalog
+        super.verifyParametersAgainstCatalog(builder, parameters);
+
+        return builder.build();
+    }
+
+    // *********************************
+    // Connectivity validation
+    // *********************************
+
+    @Override
+    protected Result verifyConnectivity(Map<String, Object> parameters) {
+        return ResultBuilder.withStatusAndScope(Result.Status.OK, Scope.CONNECTIVITY)
+            .error(parameters, this::verifyCredentials)
+            .build();
+    }
+
+    private void verifyCredentials(ResultBuilder builder, Map<String, Object> parameters) throws Exception {
+        try {
+            TwitterConfiguration configuration = setProperties(new TwitterConfiguration(), parameters);
+            Twitter twitter = configuration.getTwitter();
+
+            twitter.verifyCredentials();
+        } catch (TwitterException e) {
+            // verifyCredentials throws TwitterException when Twitter service or
+            // network is unavailable or if supplied credential is wrong
+            ResultErrorBuilder errorBuilder = ResultErrorBuilder.withCodeAndDescription(VerificationError.StandardCode.AUTHENTICATION, e.getErrorMessage())
+                .detail("twitter_error_code", e.getErrorCode())
+                .detail("twitter_status_code", e.getStatusCode())
+                .detail("twitter_exception_code", e.getExceptionCode())
+                .detail("twitter_exception_message", e.getMessage())
+                .detail("twitter_exception_caused-by-network-issue", e.isCausedByNetworkIssue())
+                .detail(VerificationError.ExceptionAttribute.EXCEPTION_CLASS, e.getClass().getName())
+                .detail(VerificationError.ExceptionAttribute.EXCEPTION_INSTANCE, e);
+
+            // For a complete list of error codes see:
+            //   https://dev.twitter.com/overview/api/response-codes
+            if (e.getErrorCode() == 89) {
+                errorBuilder.parameterKey("accessToken");
+            }
+
+            builder.error(errorBuilder.build());
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/42529399/components/camel-twitter/src/main/java/org/apache/camel/component/twitter/directmessage/TwitterDirectMessageComponent.java
----------------------------------------------------------------------
diff --git a/components/camel-twitter/src/main/java/org/apache/camel/component/twitter/directmessage/TwitterDirectMessageComponent.java b/components/camel-twitter/src/main/java/org/apache/camel/component/twitter/directmessage/TwitterDirectMessageComponent.java
index 516bb31..7ad0636 100644
--- a/components/camel-twitter/src/main/java/org/apache/camel/component/twitter/directmessage/TwitterDirectMessageComponent.java
+++ b/components/camel-twitter/src/main/java/org/apache/camel/component/twitter/directmessage/TwitterDirectMessageComponent.java
@@ -18,10 +18,9 @@ package org.apache.camel.component.twitter.directmessage;
 
 import java.util.Map;
 
-import org.apache.camel.ComponentVerifier;
+import org.apache.camel.CamelContext;
 import org.apache.camel.Endpoint;
 import org.apache.camel.component.twitter.AbstractTwitterComponent;
-import org.apache.camel.component.twitter.DefaultTwitterComponentVerifier;
 import org.apache.camel.component.twitter.TwitterConfiguration;
 import org.apache.camel.spi.Metadata;
 
@@ -31,14 +30,16 @@ import org.apache.camel.spi.Metadata;
 @Metadata(label = "verifiers", enums = "parameters,connectivity")
 public class TwitterDirectMessageComponent extends AbstractTwitterComponent {
 
-    protected Endpoint doCreateEndpoint(TwitterConfiguration properties, String uri, String remaining, Map<String, Object> parameters) throws Exception {
-        return new TwitterDirectMessageEndpoint(uri, remaining, this, properties);
+    public TwitterDirectMessageComponent() {
+        super("twitter-directmessage");
+    }
+
+    public TwitterDirectMessageComponent(CamelContext context) {
+        super(context, "twitter-directmessage");
     }
 
-    /**
-     * Get a verifier for the twitter directmessage component.
-     */
-    public ComponentVerifier getVerifier() {
-        return new DefaultTwitterComponentVerifier(this, "twitter-directmessage");
+    @Override
+    protected Endpoint doCreateEndpoint(TwitterConfiguration properties, String uri, String remaining, Map<String, Object> parameters) throws Exception {
+        return new TwitterDirectMessageEndpoint(uri, remaining, this, properties);
     }
 }

http://git-wip-us.apache.org/repos/asf/camel/blob/42529399/components/camel-twitter/src/main/java/org/apache/camel/component/twitter/search/TwitterSearchComponent.java
----------------------------------------------------------------------
diff --git a/components/camel-twitter/src/main/java/org/apache/camel/component/twitter/search/TwitterSearchComponent.java b/components/camel-twitter/src/main/java/org/apache/camel/component/twitter/search/TwitterSearchComponent.java
index 8457887..5123ab2 100644
--- a/components/camel-twitter/src/main/java/org/apache/camel/component/twitter/search/TwitterSearchComponent.java
+++ b/components/camel-twitter/src/main/java/org/apache/camel/component/twitter/search/TwitterSearchComponent.java
@@ -18,11 +18,9 @@ package org.apache.camel.component.twitter.search;
 
 import java.util.Map;
 
-import org.apache.camel.ComponentVerifier;
+import org.apache.camel.CamelContext;
 import org.apache.camel.Endpoint;
-import org.apache.camel.VerifiableComponent;
 import org.apache.camel.component.twitter.AbstractTwitterComponent;
-import org.apache.camel.component.twitter.DefaultTwitterComponentVerifier;
 import org.apache.camel.component.twitter.TwitterConfiguration;
 import org.apache.camel.spi.Metadata;
 
@@ -32,14 +30,16 @@ import org.apache.camel.spi.Metadata;
 @Metadata(label = "verifiers", enums = "parameters,connectivity")
 public class TwitterSearchComponent extends AbstractTwitterComponent {
 
-    protected Endpoint doCreateEndpoint(TwitterConfiguration properties, String uri, String remaining, Map<String, Object> parameters) throws Exception {
-        return new TwitterSearchEndpoint(uri, remaining, this, properties);
+    public TwitterSearchComponent() {
+        super("twitter-search");
+    }
+
+    public TwitterSearchComponent(CamelContext context) {
+        super(context, "twitter-search");
     }
 
-    /**
-     * Get a verifier for the twitter search component.
-     */
-    public ComponentVerifier getVerifier() {
-        return new DefaultTwitterComponentVerifier(this, "twitter-search");
+    @Override
+    protected Endpoint doCreateEndpoint(TwitterConfiguration properties, String uri, String remaining, Map<String, Object> parameters) throws Exception {
+        return new TwitterSearchEndpoint(uri, remaining, this, properties);
     }
 }

http://git-wip-us.apache.org/repos/asf/camel/blob/42529399/components/camel-twitter/src/main/java/org/apache/camel/component/twitter/streaming/TwitterStreamingComponent.java
----------------------------------------------------------------------
diff --git a/components/camel-twitter/src/main/java/org/apache/camel/component/twitter/streaming/TwitterStreamingComponent.java b/components/camel-twitter/src/main/java/org/apache/camel/component/twitter/streaming/TwitterStreamingComponent.java
index 1ccf160..5de57a0 100644
--- a/components/camel-twitter/src/main/java/org/apache/camel/component/twitter/streaming/TwitterStreamingComponent.java
+++ b/components/camel-twitter/src/main/java/org/apache/camel/component/twitter/streaming/TwitterStreamingComponent.java
@@ -18,10 +18,9 @@ package org.apache.camel.component.twitter.streaming;
 
 import java.util.Map;
 
-import org.apache.camel.ComponentVerifier;
+import org.apache.camel.CamelContext;
 import org.apache.camel.Endpoint;
 import org.apache.camel.component.twitter.AbstractTwitterComponent;
-import org.apache.camel.component.twitter.DefaultTwitterComponentVerifier;
 import org.apache.camel.component.twitter.TwitterConfiguration;
 import org.apache.camel.spi.Metadata;
 
@@ -31,15 +30,17 @@ import org.apache.camel.spi.Metadata;
 @Metadata(label = "verifiers", enums = "parameters,connectivity")
 public class TwitterStreamingComponent extends AbstractTwitterComponent {
 
+    public TwitterStreamingComponent() {
+        super("twitter-streaming");
+    }
+
+    public TwitterStreamingComponent(CamelContext context) {
+        super(context, "twitter-streaming");
+    }
+
+    @Override
     protected Endpoint doCreateEndpoint(TwitterConfiguration properties, String uri, String remaining, Map<String, Object> parameters) throws Exception {
         String keywords = getAndRemoveParameter(parameters, "keywords", String.class);
         return new TwitterStreamingEndpoint(uri, remaining, keywords, this, properties);
     }
-
-    /**
-     * Get a verifier for the twitter streaming component.
-     */
-    public ComponentVerifier getVerifier() {
-        return new DefaultTwitterComponentVerifier(this, "twitter-streaming");
-    }
 }

http://git-wip-us.apache.org/repos/asf/camel/blob/42529399/components/camel-twitter/src/main/java/org/apache/camel/component/twitter/timeline/TwitterTimelineComponent.java
----------------------------------------------------------------------
diff --git a/components/camel-twitter/src/main/java/org/apache/camel/component/twitter/timeline/TwitterTimelineComponent.java b/components/camel-twitter/src/main/java/org/apache/camel/component/twitter/timeline/TwitterTimelineComponent.java
index 0c9c885..ece0d0f 100644
--- a/components/camel-twitter/src/main/java/org/apache/camel/component/twitter/timeline/TwitterTimelineComponent.java
+++ b/components/camel-twitter/src/main/java/org/apache/camel/component/twitter/timeline/TwitterTimelineComponent.java
@@ -18,10 +18,9 @@ package org.apache.camel.component.twitter.timeline;
 
 import java.util.Map;
 
-import org.apache.camel.ComponentVerifier;
+import org.apache.camel.CamelContext;
 import org.apache.camel.Endpoint;
 import org.apache.camel.component.twitter.AbstractTwitterComponent;
-import org.apache.camel.component.twitter.DefaultTwitterComponentVerifier;
 import org.apache.camel.component.twitter.TwitterConfiguration;
 import org.apache.camel.spi.Metadata;
 
@@ -31,16 +30,17 @@ import org.apache.camel.spi.Metadata;
 @Metadata(label = "verifiers", enums = "parameters,connectivity")
 public class TwitterTimelineComponent extends AbstractTwitterComponent {
 
+    public TwitterTimelineComponent() {
+        super("twitter-timeline");
+    }
+
+    public TwitterTimelineComponent(CamelContext context) {
+        super(context, "twitter-timeline");
+    }
+
     @Override
     protected Endpoint doCreateEndpoint(TwitterConfiguration properties, String uri, String remaining, Map<String, Object> parameters) throws Exception {
         String user = getAndRemoveParameter(parameters, "user", String.class);
         return new TwitterTimelineEndpoint(uri, remaining, user, this, properties);
     }
-
-    /**
-     * Get a verifier for the twitter timeline component.
-     */
-    public ComponentVerifier getVerifier() {
-        return new DefaultTwitterComponentVerifier(this, "twitter-timeline");
-    }
 }

http://git-wip-us.apache.org/repos/asf/camel/blob/42529399/components/camel-twitter/src/test/java/org/apache/camel/component/twitter/AbstractComponentVerifierExtensionTest.java
----------------------------------------------------------------------
diff --git a/components/camel-twitter/src/test/java/org/apache/camel/component/twitter/AbstractComponentVerifierExtensionTest.java b/components/camel-twitter/src/test/java/org/apache/camel/component/twitter/AbstractComponentVerifierExtensionTest.java
new file mode 100644
index 0000000..21331da
--- /dev/null
+++ b/components/camel-twitter/src/test/java/org/apache/camel/component/twitter/AbstractComponentVerifierExtensionTest.java
@@ -0,0 +1,82 @@
+/**
+ * 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.twitter;
+
+import java.util.Map;
+
+import org.apache.camel.Component;
+import org.apache.camel.component.extension.ComponentVerifierExtension;
+import org.junit.Assert;
+import org.junit.Test;
+
+
+public abstract class AbstractComponentVerifierExtensionTest extends CamelTwitterTestSupport {
+
+    protected abstract String getComponentScheme();
+    
+    @Override
+    public boolean isUseRouteBuilder() {
+        return false;
+    }
+
+    @Test
+    public void testConnectivity() {
+        Component component = context().getComponent(getComponentScheme());
+        ComponentVerifierExtension verifier = component.getExtension(ComponentVerifierExtension.class).orElseThrow(IllegalStateException::new);
+
+        Map<String, Object> parameters = getParameters();
+        ComponentVerifierExtension.Result result = verifier.verify(ComponentVerifierExtension.Scope.CONNECTIVITY, parameters);
+
+        Assert.assertEquals(ComponentVerifierExtension.Result.Status.OK, result.getStatus());
+    }
+
+    @Test
+    public void testInvalidKeyConfiguration() {
+        Component component = context().getComponent(getComponentScheme());
+        ComponentVerifierExtension verifier = component.getExtension(ComponentVerifierExtension.class).orElseThrow(IllegalStateException::new);
+
+        Map<String, Object> parameters = getParameters();
+        parameters.put("consumerKey", "invalid");
+
+        ComponentVerifierExtension.Result result = verifier.verify(ComponentVerifierExtension.Scope.CONNECTIVITY, parameters);
+
+        Assert.assertEquals(ComponentVerifierExtension.Result.Status.ERROR, result.getStatus());
+        Assert.assertEquals(1, result.getErrors().size());
+        Assert.assertEquals(ComponentVerifierExtension.VerificationError.StandardCode.AUTHENTICATION, result.getErrors().get(0).getCode());
+        Assert.assertEquals(401, result.getErrors().get(0).getDetails().get(ComponentVerifierExtension.VerificationError.asAttribute("twitter_status_code")));
+        Assert.assertEquals(32, result.getErrors().get(0).getDetails().get(ComponentVerifierExtension.VerificationError.asAttribute("twitter_error_code")));
+    }
+
+    @Test
+    public void testInvalidTokenConfiguration() {
+        Component component = context().getComponent(getComponentScheme());
+        ComponentVerifierExtension verifier = component.getExtension(ComponentVerifierExtension.class).orElseThrow(IllegalStateException::new);
+
+        Map<String, Object> parameters = getParameters();
+        parameters.put("accessToken", "invalid");
+
+        ComponentVerifierExtension.Result result = verifier.verify(ComponentVerifierExtension.Scope.CONNECTIVITY, parameters);
+
+        Assert.assertEquals(ComponentVerifierExtension.Result.Status.ERROR, result.getStatus());
+        Assert.assertEquals(1, result.getErrors().size());
+        Assert.assertEquals(ComponentVerifierExtension.VerificationError.StandardCode.AUTHENTICATION, result.getErrors().get(0).getCode());
+        Assert.assertEquals(401, result.getErrors().get(0).getDetails().get(ComponentVerifierExtension.VerificationError.asAttribute("twitter_status_code")));
+        Assert.assertEquals(89, result.getErrors().get(0).getDetails().get(ComponentVerifierExtension.VerificationError.asAttribute("twitter_error_code")));
+        Assert.assertEquals(1, result.getErrors().get(0).getParameterKeys().size());
+        Assert.assertEquals("accessToken", result.getErrors().get(0).getParameterKeys().iterator().next());
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/42529399/components/camel-twitter/src/test/java/org/apache/camel/component/twitter/AbstractComponentVerifierTest.java
----------------------------------------------------------------------
diff --git a/components/camel-twitter/src/test/java/org/apache/camel/component/twitter/AbstractComponentVerifierTest.java b/components/camel-twitter/src/test/java/org/apache/camel/component/twitter/AbstractComponentVerifierTest.java
new file mode 100644
index 0000000..703f7cf
--- /dev/null
+++ b/components/camel-twitter/src/test/java/org/apache/camel/component/twitter/AbstractComponentVerifierTest.java
@@ -0,0 +1,81 @@
+/**
+ * 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.twitter;
+
+import java.util.Map;
+
+import org.apache.camel.ComponentVerifier;
+import org.junit.Assert;
+import org.junit.Test;
+
+
+public abstract class AbstractComponentVerifierTest extends CamelTwitterTestSupport {
+
+    protected abstract String getComponentScheme();
+    
+    @Override
+    public boolean isUseRouteBuilder() {
+        return false;
+    }
+
+    @Test
+    public void testConnectivity() {
+        AbstractTwitterComponent component = context().getComponent(getComponentScheme(), AbstractTwitterComponent.class);
+        ComponentVerifier verifier = component.getVerifier();
+
+        Map<String, Object> parameters = getParameters();
+        ComponentVerifier.Result result = verifier.verify(ComponentVerifier.Scope.CONNECTIVITY, parameters);
+
+        Assert.assertEquals(ComponentVerifier.Result.Status.OK, result.getStatus());
+    }
+
+    @Test
+    public void testInvalidKeyConfiguration() {
+        AbstractTwitterComponent component = context().getComponent(getComponentScheme(), AbstractTwitterComponent.class);
+        ComponentVerifier verifier = component.getVerifier();
+
+        Map<String, Object> parameters = getParameters();
+        parameters.put("consumerKey", "invalid");
+
+        ComponentVerifier.Result result = verifier.verify(ComponentVerifier.Scope.CONNECTIVITY, parameters);
+
+        Assert.assertEquals(ComponentVerifier.Result.Status.ERROR, result.getStatus());
+        Assert.assertEquals(1, result.getErrors().size());
+        Assert.assertEquals(ComponentVerifier.VerificationError.StandardCode.AUTHENTICATION, result.getErrors().get(0).getCode());
+        Assert.assertEquals(401, result.getErrors().get(0).getDetails().get(ComponentVerifier.VerificationError.asAttribute("twitter_status_code")));
+        Assert.assertEquals(32, result.getErrors().get(0).getDetails().get(ComponentVerifier.VerificationError.asAttribute("twitter_error_code")));
+    }
+
+    @Test
+    public void testInvalidTokenConfiguration() {
+        AbstractTwitterComponent component = context().getComponent(getComponentScheme(), AbstractTwitterComponent.class);
+        ComponentVerifier verifier = component.getVerifier();
+
+        Map<String, Object> parameters = getParameters();
+        parameters.put("accessToken", "invalid");
+
+        ComponentVerifier.Result result = verifier.verify(ComponentVerifier.Scope.CONNECTIVITY, parameters);
+
+        Assert.assertEquals(ComponentVerifier.Result.Status.ERROR, result.getStatus());
+        Assert.assertEquals(1, result.getErrors().size());
+        Assert.assertEquals(ComponentVerifier.VerificationError.StandardCode.AUTHENTICATION, result.getErrors().get(0).getCode());
+        Assert.assertEquals(401, result.getErrors().get(0).getDetails().get(ComponentVerifier.VerificationError.asAttribute("twitter_status_code")));
+        Assert.assertEquals(89, result.getErrors().get(0).getDetails().get(ComponentVerifier.VerificationError.asAttribute("twitter_error_code")));
+        Assert.assertEquals(1, result.getErrors().get(0).getParameterKeys().size());
+        Assert.assertEquals("accessToken", result.getErrors().get(0).getParameterKeys().iterator().next());
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/42529399/components/camel-twitter/src/test/java/org/apache/camel/component/twitter/CamelComponentVerifierTest.java
----------------------------------------------------------------------
diff --git a/components/camel-twitter/src/test/java/org/apache/camel/component/twitter/CamelComponentVerifierTest.java b/components/camel-twitter/src/test/java/org/apache/camel/component/twitter/CamelComponentVerifierTest.java
deleted file mode 100644
index 28c2992..0000000
--- a/components/camel-twitter/src/test/java/org/apache/camel/component/twitter/CamelComponentVerifierTest.java
+++ /dev/null
@@ -1,123 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.camel.component.twitter;
-
-import java.util.Collections;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-
-import org.apache.camel.ComponentVerifier;
-import org.apache.camel.ComponentVerifier.VerificationError;
-import org.apache.camel.component.twitter.search.TwitterSearchComponent;
-import org.junit.Assert;
-import org.junit.Test;
-
-import static org.apache.camel.ComponentVerifier.VerificationError.asAttribute;
-
-public class CamelComponentVerifierTest extends CamelTwitterTestSupport {
-
-    @Override
-    public boolean isUseRouteBuilder() {
-        return false;
-    }
-
-    @Test
-    public void testConnectivity() {
-        TwitterSearchComponent component = context().getComponent("twitter-search", TwitterSearchComponent.class);
-        DefaultTwitterComponentVerifier verifier = (DefaultTwitterComponentVerifier)component.getVerifier();
-
-        Map<String, Object> parameters = getParameters();
-        ComponentVerifier.Result result = verifier.verify(ComponentVerifier.Scope.CONNECTIVITY, parameters);
-
-        Assert.assertEquals(ComponentVerifier.Result.Status.OK, result.getStatus());
-    }
-
-    @Test
-    public void testInvalidKeyConfiguration() {
-        TwitterSearchComponent component = context().getComponent("twitter-search", TwitterSearchComponent.class);
-        DefaultTwitterComponentVerifier verifier = (DefaultTwitterComponentVerifier)component.getVerifier();
-
-        Map<String, Object> parameters = getParameters();
-        parameters.put("consumerKey", "invalid");
-
-        ComponentVerifier.Result result = verifier.verify(ComponentVerifier.Scope.CONNECTIVITY, parameters);
-
-        Assert.assertEquals(ComponentVerifier.Result.Status.ERROR, result.getStatus());
-        Assert.assertEquals(1, result.getErrors().size());
-        Assert.assertEquals(VerificationError.StandardCode.AUTHENTICATION, result.getErrors().get(0).getCode());
-        Assert.assertEquals(401, result.getErrors().get(0).getDetails().get(asAttribute("twitter_status_code")));
-        Assert.assertEquals(32, result.getErrors().get(0).getDetails().get(asAttribute("twitter_error_code")));
-    }
-
-    @Test
-    public void testInvalidTokenConfiguration() {
-        TwitterSearchComponent component = context().getComponent("twitter-search", TwitterSearchComponent.class);
-        DefaultTwitterComponentVerifier verifier = (DefaultTwitterComponentVerifier)component.getVerifier();
-
-        Map<String, Object> parameters = getParameters();
-        parameters.put("accessToken", "invalid");
-
-        ComponentVerifier.Result result = verifier.verify(ComponentVerifier.Scope.CONNECTIVITY, parameters);
-
-        Assert.assertEquals(ComponentVerifier.Result.Status.ERROR, result.getStatus());
-        Assert.assertEquals(1, result.getErrors().size());
-        Assert.assertEquals(VerificationError.StandardCode.AUTHENTICATION, result.getErrors().get(0).getCode());
-        Assert.assertEquals(401, result.getErrors().get(0).getDetails().get(asAttribute("twitter_status_code")));
-        Assert.assertEquals(89, result.getErrors().get(0).getDetails().get(asAttribute("twitter_error_code")));
-        Assert.assertEquals(1, result.getErrors().get(0).getParameterKeys().size());
-        Assert.assertEquals("accessToken", result.getErrors().get(0).getParameterKeys().iterator().next());
-    }
-
-    @Test
-    public void testEmptyConfiguration() {
-        TwitterSearchComponent component = context().getComponent("twitter-search", TwitterSearchComponent.class);
-        DefaultTwitterComponentVerifier verifier = (DefaultTwitterComponentVerifier)component.getVerifier();
-
-        {
-            // Parameters validation
-            ComponentVerifier.Result result = verifier.verify(ComponentVerifier.Scope.PARAMETERS, Collections.emptyMap());
-
-            Assert.assertEquals(ComponentVerifier.Result.Status.ERROR, result.getStatus());
-            Assert.assertEquals(5, result.getErrors().size());
-
-            List<String> expected = new LinkedList<>();
-            expected.add("keywords");
-            expected.add("consumerKey");
-            expected.add("consumerSecret");
-            expected.add("accessToken");
-            expected.add("accessTokenSecret");
-
-            for (VerificationError error : result.getErrors()) {
-                expected.removeAll(error.getParameterKeys());
-            }
-
-            Assert.assertTrue("Missing expected params: " + expected.toString(), expected.isEmpty());
-        }
-
-        {
-            // Connectivity validation
-            ComponentVerifier.Result result = verifier.verify(ComponentVerifier.Scope.CONNECTIVITY, Collections.emptyMap());
-
-            Assert.assertEquals(ComponentVerifier.Result.Status.ERROR, result.getStatus());
-            Assert.assertEquals(1, result.getErrors().size());
-            Assert.assertEquals(VerificationError.StandardCode.EXCEPTION, result.getErrors().get(0).getCode());
-            Assert.assertNotNull(result.getErrors().get(0).getDetails().get(VerificationError.ExceptionAttribute.EXCEPTION_INSTANCE));
-            Assert.assertTrue(result.getErrors().get(0).getDetails().get(VerificationError.ExceptionAttribute.EXCEPTION_INSTANCE) instanceof IllegalArgumentException);
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/camel/blob/42529399/components/camel-twitter/src/test/java/org/apache/camel/component/twitter/TwitterComponentVerifierExtensionTest.java
----------------------------------------------------------------------
diff --git a/components/camel-twitter/src/test/java/org/apache/camel/component/twitter/TwitterComponentVerifierExtensionTest.java b/components/camel-twitter/src/test/java/org/apache/camel/component/twitter/TwitterComponentVerifierExtensionTest.java
new file mode 100644
index 0000000..d3fc2da
--- /dev/null
+++ b/components/camel-twitter/src/test/java/org/apache/camel/component/twitter/TwitterComponentVerifierExtensionTest.java
@@ -0,0 +1,24 @@
+/**
+ * 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.twitter;
+
+public class TwitterComponentVerifierExtensionTest extends AbstractComponentVerifierExtensionTest {
+    @Override
+    protected String getComponentScheme() {
+        return "twitter";
+    }
+}


[07/19] camel git commit: CAMEL-11550: Component extensions

Posted by lb...@apache.org.
CAMEL-11550: Component extensions


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

Branch: refs/heads/master
Commit: 4252939938f6603080fb8adda750872a8001a74b
Parents: f347292
Author: lburgazzoli <lb...@gmail.com>
Authored: Tue Jul 18 18:47:28 2017 +0200
Committer: lburgazzoli <lb...@gmail.com>
Committed: Fri Aug 4 18:09:04 2017 +0200

----------------------------------------------------------------------
 .../main/java/org/apache/camel/Component.java   |  25 ++
 .../java/org/apache/camel/ComponentAware.java   |  61 +++
 .../org/apache/camel/ComponentVerifier.java     | 361 +----------------
 .../camel/ComponentVerifierException.java       |  34 --
 .../apache/camel/ComponentVerifierHelper.java   | 140 -------
 .../apache/camel/IllegalOptionException.java    |  39 --
 .../org/apache/camel/NoSuchOptionException.java |  29 --
 .../org/apache/camel/VerifiableComponent.java   |   3 +
 .../component/extension/ComponentExtension.java |  26 ++
 .../extension/ComponentExtensionHelper.java     |  43 +++
 .../extension/ComponentVerifierExtension.java   | 385 +++++++++++++++++++
 .../component/extension/MetaDataExtension.java  |  74 ++++
 .../metadata/AbstractMetaDataExtension.java     |  65 ++++
 .../extension/metadata/DefaultMetaData.java     |  63 +++
 .../extension/metadata/MetaDataBuilder.java     |  64 +++
 .../component/extension/metadata/package.html   |  25 ++
 .../camel/component/extension/package.html      |  25 ++
 .../verifier/CatalogVerifierCustomizer.java     | 104 +++++
 .../verifier/ComponentVerifierException.java    |  36 ++
 .../ComponentVerifierExtensionHelper.java       | 145 +++++++
 .../DefaultComponentVerifierExtension.java      | 214 +++++++++++
 .../extension/verifier/DefaultResult.java       |  57 +++
 .../DefaultResultVerificationError.java         |  66 ++++
 .../verifier/IllegalOptionException.java        |  39 ++
 .../verifier/NoSuchOptionException.java         |  29 ++
 .../extension/verifier/OptionsGroup.java        | 142 +++++++
 .../extension/verifier/ResultBuilder.java       | 141 +++++++
 .../extension/verifier/ResultErrorBuilder.java  | 213 ++++++++++
 .../extension/verifier/ResultErrorHelper.java   | 164 ++++++++
 .../component/extension/verifier/package.html   |  25 ++
 .../camel/component/rest/RestComponent.java     |  12 +-
 .../component/rest/RestComponentVerifier.java   | 152 --------
 .../rest/RestComponentVerifierExtension.java    | 151 ++++++++
 .../org/apache/camel/impl/DefaultComponent.java |  36 ++
 .../verifier/CatalogVerifierCustomizer.java     | 104 -----
 .../impl/verifier/DefaultComponentVerifier.java | 202 ----------
 .../camel/impl/verifier/DefaultResult.java      |  57 ---
 .../DefaultResultVerificationError.java         |  66 ----
 .../camel/impl/verifier/OptionsGroup.java       | 142 -------
 .../camel/impl/verifier/ResultBuilder.java      | 143 -------
 .../camel/impl/verifier/ResultErrorBuilder.java | 213 ----------
 .../camel/impl/verifier/ResultErrorHelper.java  | 164 --------
 .../management/mbean/ManagedComponent.java      |   5 +-
 .../apache/camel/util/CamelContextHelper.java   |   2 +-
 .../org/apache/camel/ComponentVerifierTest.java |  66 ----
 .../verifier/ComponentVerifierTest.java         |  66 ++++
 .../RestComponentVerifierExtensionTest.java     | 141 +++++++
 .../rest/RestComponentVerifierTest.java         |  32 +-
 .../verifier/DefaultComponentVerifierTest.java  |  23 +-
 .../impl/verifier/ResultErrorHelperTest.java    |   9 +-
 .../camel/management/ManagedComponentTest.java  |   6 +-
 .../camel/component/http/HttpComponent.java     |  11 +-
 .../component/http/HttpComponentVerifier.java   | 250 ------------
 .../http/HttpComponentVerifierExtension.java    | 246 ++++++++++++
 .../http/CamelComponentVerifierTest.java        | 192 ---------
 .../HttpComponentVerifierExtensionTest.java     | 151 ++++++++
 .../http/HttpComponentVerifierTest.java         | 150 ++++++++
 .../camel/component/http4/HttpComponent.java    |  11 +-
 .../component/http4/HttpComponentVerifier.java  | 250 ------------
 .../http4/HttpComponentVerifierExtension.java   | 248 ++++++++++++
 .../CamelComponentVerifierExtensionTest.java    | 263 +++++++++++++
 .../http4/CamelComponentVerifierTest.java       |  43 ++-
 .../salesforce/SalesforceComponent.java         |   7 +-
 .../salesforce/SalesforceComponentVerifier.java | 204 ----------
 .../SalesforceComponentVerifierExtension.java   | 205 ++++++++++
 ...alesforceComponentVerifierExtensionTest.java | 183 +++++++++
 .../SalesforceComponentVerifierTest.java        |  27 +-
 .../servicenow/ServiceNowComponent.java         |  37 +-
 .../servicenow/ServiceNowComponentVerifier.java | 113 ------
 .../ServiceNowComponentVerifierExtension.java   | 112 ++++++
 ...erviceNowComponentVerifierExtensionTest.java | 151 ++++++++
 .../ServiceNowComponentVerifierTest.java        |  32 +-
 .../twitter/AbstractTwitterComponent.java       |  17 +-
 .../DefaultTwitterComponentVerifier.java        |  95 -----
 .../component/twitter/TwitterComponent.java     |  18 +-
 .../TwitterComponentVerifierExtension.java      |  94 +++++
 .../TwitterDirectMessageComponent.java          |  19 +-
 .../twitter/search/TwitterSearchComponent.java  |  20 +-
 .../streaming/TwitterStreamingComponent.java    |  19 +-
 .../timeline/TwitterTimelineComponent.java      |  18 +-
 .../AbstractComponentVerifierExtensionTest.java |  82 ++++
 .../twitter/AbstractComponentVerifierTest.java  |  81 ++++
 .../twitter/CamelComponentVerifierTest.java     | 123 ------
 .../TwitterComponentVerifierExtensionTest.java  |  24 ++
 .../twitter/TwitterComponentVerifierTest.java   |  24 ++
 ...ctmessageComponentVerifierExtensionTest.java |  26 ++
 ...itterDirectmessageComponentVerifierTest.java |  26 ++
 ...terSearchComponentVerifierExtensionTest.java |  72 ++++
 .../TwitterSearchComponentVerifierTest.java     |  72 ++++
 ...StreamingComponentVerifierExtensionTest.java |  26 ++
 .../TwitterStreamingComponentVerifierTest.java  |  26 ++
 ...rTimelineComponentVerifierExtensionTest.java |  26 ++
 .../TwitterTimelineComponentVerifierTest.java   |  26 ++
 .../component/undertow/UndertowComponent.java   |  10 +-
 .../undertow/UndertowComponentVerifier.java     | 239 ------------
 .../UndertowComponentVerifierExtension.java     | 236 ++++++++++++
 .../UndertowComponentVerifierExtensionTest.java | 104 +++++
 .../SpringBootAutoConfigurationMojo.java        |   2 +-
 .../connector/DefaultConnectorComponent.java    |  28 +-
 99 files changed, 5515 insertions(+), 3553 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/camel/blob/42529399/camel-core/src/main/java/org/apache/camel/Component.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/Component.java b/camel-core/src/main/java/org/apache/camel/Component.java
index d873470..b21e7a4 100644
--- a/camel-core/src/main/java/org/apache/camel/Component.java
+++ b/camel-core/src/main/java/org/apache/camel/Component.java
@@ -16,6 +16,12 @@
  */
 package org.apache.camel;
 
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Optional;
+
+import org.apache.camel.component.extension.ComponentExtension;
+
 /**
  * A <a href="http://camel.apache.org/component.html">component</a> is
  * a factory of {@link Endpoint} objects.
@@ -73,4 +79,23 @@ public interface Component extends CamelContextAware {
      */
     @Deprecated
     ComponentConfiguration createComponentConfiguration();
+
+    /**
+     * Gets a list of supported extensions.
+     *
+     * @return the list of extensions.
+     */
+    default Collection<Class<? extends ComponentExtension>> getSupportedExtensions() {
+        return Collections.emptyList();
+    }
+
+    /**
+     * Gets the extension of the given type.
+     *
+     * @param extensionType tye type of the extensions
+     * @return an optional extension
+     */
+    default <T extends ComponentExtension> Optional<T> getExtension(Class<T> extensionType) {
+        return Optional.empty();
+    }
 }

http://git-wip-us.apache.org/repos/asf/camel/blob/42529399/camel-core/src/main/java/org/apache/camel/ComponentAware.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/ComponentAware.java b/camel-core/src/main/java/org/apache/camel/ComponentAware.java
new file mode 100644
index 0000000..88f7a31
--- /dev/null
+++ b/camel-core/src/main/java/org/apache/camel/ComponentAware.java
@@ -0,0 +1,61 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel;
+
+/**
+ * An interface to represent an object which wishes to be injected with
+ * a {@link Component}.
+ */
+public interface ComponentAware {
+
+    /**
+     * Injects the {@link Component}
+     *
+     * @param component the component
+     */
+    void setComponent(Component component);
+
+    /**
+     * Get the {@link Component}
+     *
+     * @return the component
+     */
+    Component getComponent();
+
+    /**
+     * Get the {@link Component} as the specified type.
+     *
+     * @param type the proprietary class or interface of the underlying concrete Component.
+     * @return an instance of the underlying concrete Component as the required type.
+     * @throws IllegalArgumentException if the component class can't be cast to required type,
+     */
+    default <T extends Component> T getComponent(Class<T> type) {
+        final Component component = getComponent();
+
+        if (component == null) {
+            return null;
+        }
+
+        if (Component.class.isAssignableFrom(type)) {
+            return type.cast(component);
+        }
+
+        throw new IllegalArgumentException(
+            "Unable to unwrap the Component type (" + component.getClass() + ") to the required type (" + type + ")"
+        );
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/42529399/camel-core/src/main/java/org/apache/camel/ComponentVerifier.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/ComponentVerifier.java b/camel-core/src/main/java/org/apache/camel/ComponentVerifier.java
index bcbda7c..d95a7e7 100644
--- a/camel-core/src/main/java/org/apache/camel/ComponentVerifier.java
+++ b/camel-core/src/main/java/org/apache/camel/ComponentVerifier.java
@@ -16,14 +16,9 @@
  */
 package org.apache.camel;
 
-import java.io.Serializable;
-import java.util.List;
 import java.util.Map;
-import java.util.Set;
 
-import org.apache.camel.ComponentVerifierHelper.ExceptionErrorAttribute;
-import org.apache.camel.impl.verifier.ResultErrorBuilder;
-import org.apache.camel.util.ObjectHelper;
+import org.apache.camel.component.extension.ComponentVerifierExtension;
 
 /**
  * Defines the interface used for validating component/endpoint parameters. The central method of this
@@ -31,356 +26,8 @@ import org.apache.camel.util.ObjectHelper;
  * <p/>
  * The return value is a {@link Result} of the verification
  *
+ * @deprecated use {@link ComponentVerifierExtension}
  */
-public interface ComponentVerifier {
-
-    /**
-     * Verify the given parameters against a provided scope.
-     *
-     * <p>
-     * The supported scopes are:
-     * <ul>
-     *   <li><strong>{@link Scope#PARAMETERS}</strong>: to validate that all the mandatory options are provided and syntactically correct.</li>
-     *   <li><strong>{@link Scope#CONNECTIVITY}</strong>: to validate that the given options (i.e. credentials, addresses) are correct. Verifying with this
-     *       scope typically implies reaching out to the backend via some sort of network connection.</li>
-     * </ul>
-     *
-     * @param scope the scope of the verification
-     * @param parameters the parameters to verify which are interpreted individually by each component verifier
-     * @return the verification result
-     */
-    Result verify(Scope scope, Map<String, Object> parameters);
-
-    /**
-     * The result of a verification
-     */
-    interface Result extends Serializable {
-
-        /**
-         * Status of the verification
-         */
-        enum Status {
-            /**
-             * Verification succeeded
-             */
-            OK,
-            /**
-             * Error occurred during the verification
-             */
-            ERROR,
-            /**
-             * Verification is not supported. This can depend on the given scope.
-             */
-            UNSUPPORTED
-        }
-
-        /**
-         * Scope of the verification. This is the scope given to the call to {@link #verify(Scope, Map)}  and
-         * can be used for correlation.
-         *
-         * @return the scope against which the parameters have been validated.
-         */
-        Scope getScope();
-
-        /**
-         * Result of the validation as status. This should be the first datum to check after a verification
-         * happened.
-         *
-         * @return the status
-         */
-        Status getStatus();
-
-        /**
-         * Collection of errors happened for the verification. This list is empty (but non null) if the verification
-         * succeeded.
-         *
-         * @return a list of errors. Can be empty when verification was successful
-         */
-        List<VerificationError> getErrors();
-    }
-
-    /**
-     * The scope defines how the parameters should be verified.
-     */
-    enum Scope {
-        /**
-         * Only validate the parameters for their <em>syntactic</em> soundness. Verifications in this scope should
-         * be as fast as possible
-         */
-        PARAMETERS,
-
-        /**
-         * Reach out to the backend and verify that a connection can be established. This means, if the verification
-         * in this scope succeeds, then it can safely be assumed that the component can be used.
-         */
-        CONNECTIVITY;
-
-        private static final Scope[] VALUES = values();
-
-        /**
-         * Get an instance of this scope from a string representation
-         *
-         * @param scope the scope as string, which can be in any case
-         * @return the scope enum represented by this string
-         */
-        public static Scope fromString(String scope) {
-            for (Scope value : VALUES) {
-                if (ObjectHelper.equal(scope, value.name(), true)) {
-                    return value;
-                }
-            }
-            throw new IllegalArgumentException("Unknown scope <" + scope + ">");
-        }
-    }
-
-    // =============================================================================================
-
-    /**
-     * This interface represents a detailed error in case when the verification fails.
-     */
-    interface VerificationError extends Serializable {
-
-        /**
-         * The overall error code, which can be either a {@link StandardCode} or a custom code. It is
-         * recommended to stick to the predefined standard codes
-         *
-         * @return the general error code.
-         */
-        Code getCode();
-
-        /**
-         * A human readable description of the error in plain english
-         *
-         * @return the error description (if available)
-         */
-        String getDescription();
-
-        /**
-         * A set of input parameter names which fails the verification. These are keys to the parameter provided
-         * to {@link #verify(Scope, Map)}.
-         *
-         * @return the parameter names which are malformed and caused the failure of the validation
-         */
-        Set<String> getParameterKeys();
-
-        /**
-         * Details about the failed verification. The keys can be either predefined values
-         * ({@link ExceptionAttribute}, {@link HttpAttribute}, {@link GroupAttribute}) or it can be free-form
-         * custom keys specific to a component. The standard attributes are defined as enums in all uppercase (with
-         * underscore as separator), custom attributes are supposed to be in all lower case (also with underscores
-         * as separators)
-         *
-         * @return a number of key/value pair with additional information related to the verification.
-         */
-        Map<Attribute, Object> getDetails();
-
-        /**
-         * Get a single detail for a given attribute
-         *
-         * @param attribute the attribute to lookup
-         * @return the detail value or null if no such attribute exists
-         */
-        default Object getDetail(Attribute attribute) {
-            Map<Attribute, Object> details = getDetails();
-            if (details != null) {
-                return details.get(attribute);
-            }
-            return null;
-        }
-
-        /**
-         * Get a single detail for a given attribute
-         *
-         * @param attribute the attribute to lookup
-         * @return the detail value or null if no such attribute exists
-         */
-        default Object getDetail(String attribute) {
-            return getDetail(asAttribute(attribute));
-        }
-
-        /**
-         * Convert a string to an {@link Code}
-         *
-         * @param code the code to convert. It should be in all lower case (with
-         *             underscore as a separator) to avoid overlap with {@link StandardCode}
-         * @return error code
-         */
-        static Code asCode(String code) {
-            return new ComponentVerifierHelper.ErrorCode(code);
-        }
-
-        /**
-         * Convert a string to an {@link Attribute}
-         *
-         * @param attribute the string representation of an attribute to convert. It should be in all lower case (with
-         *                  underscore as a separator) to avoid overlap with standard attributes like {@link ExceptionAttribute},
-         *                  {@link HttpAttribute} or {@link GroupAttribute}
-         * @return generated attribute
-         */
-        static Attribute asAttribute(String attribute) {
-            return new ComponentVerifierHelper.ErrorAttribute(attribute);
-        }
-
-        /**
-         * Interface defining an error code. This is implemented by the {@link StandardCode} but also
-         * own code can be generated by implementing this interface. This is best done via {@link #asCode(String)}
-         * If possible, the standard codes should be reused
-         */
-        interface Code extends Serializable {
-            /**
-             * Name of the code. All uppercase for standard codes, all lower case for custom codes.
-             * Separator between two words is an underscore.
-             *
-             * @return code name
-             */
-            String name();
-
-            /**
-             * Bean style accessor to name.
-             * This is required for framework like Jackson using bean convention for object serialization.
-             *
-             * @return code name
-             */
-            default String getName() {
-                return name();
-            }
-        }
-
-        /**
-         * Standard set of error codes
-         */
-        interface StandardCode extends Code {
-            /**
-             * Authentication failed
-             */
-            StandardCode AUTHENTICATION = new ComponentVerifierHelper.StandardErrorCode("AUTHENTICATION");
-            /**
-             * An exception occurred
-             */
-            StandardCode EXCEPTION = new ComponentVerifierHelper.StandardErrorCode("EXCEPTION");
-            /**
-             * Internal error while performing the verification
-             */
-            StandardCode INTERNAL = new ComponentVerifierHelper.StandardErrorCode("INTERNAL");
-            /**
-             * A mandatory parameter is missing
-             */
-            StandardCode MISSING_PARAMETER = new ComponentVerifierHelper.StandardErrorCode("MISSING_PARAMETER");
-            /**
-             * A given parameter is not known to the component
-             */
-            StandardCode UNKNOWN_PARAMETER = new ComponentVerifierHelper.StandardErrorCode("UNKNOWN_PARAMETER");
-            /**
-             * A given parameter is illegal
-             */
-            StandardCode ILLEGAL_PARAMETER = new ComponentVerifierHelper.StandardErrorCode("ILLEGAL_PARAMETER");
-            /**
-             * A combination of parameters is illegal. See {@link VerificationError#getParameterKeys()} for the set
-             * of affected parameters
-             */
-            StandardCode ILLEGAL_PARAMETER_GROUP_COMBINATION = new ComponentVerifierHelper.StandardErrorCode("ILLEGAL_PARAMETER_GROUP_COMBINATION");
-            /**
-             * A parameter <em>value</em> is not valid
-             */
-            StandardCode ILLEGAL_PARAMETER_VALUE = new ComponentVerifierHelper.StandardErrorCode("ILLEGAL_PARAMETER_VALUE");
-            /**
-             * A group of parameters is not complete in order to be valid
-             */
-            StandardCode INCOMPLETE_PARAMETER_GROUP = new ComponentVerifierHelper.StandardErrorCode("INCOMPLETE_PARAMETER_GROUP");
-            /**
-             * The verification is not supported
-             */
-            StandardCode UNSUPPORTED = new ComponentVerifierHelper.StandardErrorCode("UNSUPPORTED");
-            /**
-             * The requested {@link Scope} is not supported
-             */
-            StandardCode UNSUPPORTED_SCOPE = new ComponentVerifierHelper.StandardErrorCode("UNSUPPORTED_SCOPE");
-            /**
-             * The requested {@link Component} is not supported
-             */
-            StandardCode UNSUPPORTED_COMPONENT = new ComponentVerifierHelper.StandardErrorCode("UNSUPPORTED_COMPONENT");
-            /**
-             * Generic error which is explained in more details with {@link VerificationError#getDetails()}
-             */
-            StandardCode GENERIC = new ComponentVerifierHelper.StandardErrorCode("GENERIC");
-        }
-
-        /**
-         * Interface defining an attribute which is a key for the detailed error messages. This is implemented by several
-         * standard enums like {@link ExceptionAttribute}, {@link HttpAttribute} or {@link GroupAttribute} but can also
-         * implemented for component specific details. This is best done via {@link #asAttribute(String)}
-         * or using one of the other builder method in this error builder (like {@link ResultErrorBuilder#detail(String, Object)}
-         * <p>
-         * With respecting to name, the same rules as for {@link Code} apply: Standard attributes are all upper case with _
-         * as separators, whereas custom attributes are lower case with underscore separators.
-         */
-        interface Attribute extends Serializable {
-            /**
-             * Name of the attribute. All uppercase for standard attributes and all lower case for custom attributes.
-             * Separator between words is an underscore.
-             *
-             * @return attribute name
-             */
-            String name();
-
-            /**
-             * Bean style accessor to name;
-             * This is required for framework like Jackson using bean convention for object serialization.
-             *
-             * @return attribute name
-             */
-            default String getName() {
-                return name();
-            }
-        }
-
-        /**
-         * Attributes for details about an exception that was raised
-         */
-        interface ExceptionAttribute extends Attribute {
-            /**
-             * The exception object that has been thrown. Note that this can be a complex
-             * object and can cause large content when e.g. serialized as JSON
-             */
-            ExceptionAttribute EXCEPTION_INSTANCE = new ExceptionErrorAttribute("EXCEPTION_INSTANCE");
-            /**
-             * The exception class
-             */
-            ExceptionAttribute EXCEPTION_CLASS = new ExceptionErrorAttribute("EXCEPTION_CLASS");
-        }
-
-        /**
-         * HTTP related error details
-         */
-        interface HttpAttribute extends Attribute {
-            /**
-             * The erroneous HTTP code that occurred
-             */
-            HttpAttribute HTTP_CODE = new ComponentVerifierHelper.HttpErrorAttribute("HTTP_CODE");
-            /**
-             * HTTP response's body
-             */
-            HttpAttribute HTTP_TEXT = new ComponentVerifierHelper.HttpErrorAttribute("HTTP_TEXT");
-            /**
-             * If given as details, specifies that a redirect happened and the
-             * content of this detail is the redirect URL
-             */
-            HttpAttribute HTTP_REDIRECT = new ComponentVerifierHelper.HttpErrorAttribute("HTTP_REDIRECT");
-        }
-
-        /**
-         * Group related details
-         */
-        interface GroupAttribute extends Attribute {
-            /**
-             * Group name
-             */
-            GroupAttribute GROUP_NAME = new ComponentVerifierHelper.GroupErrorAttribute("GROUP_NAME");
-            /**
-             * Options for the group
-             */
-            GroupAttribute GROUP_OPTIONS = new ComponentVerifierHelper.GroupErrorAttribute("GROUP_OPTIONS");
-        }
-    }
-
+@Deprecated
+public interface ComponentVerifier extends ComponentVerifierExtension {
 }

http://git-wip-us.apache.org/repos/asf/camel/blob/42529399/camel-core/src/main/java/org/apache/camel/ComponentVerifierException.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/ComponentVerifierException.java b/camel-core/src/main/java/org/apache/camel/ComponentVerifierException.java
deleted file mode 100644
index 358498b..0000000
--- a/camel-core/src/main/java/org/apache/camel/ComponentVerifierException.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.camel;
-
-public class ComponentVerifierException extends CamelException {
-    public ComponentVerifierException() {
-    }
-
-    public ComponentVerifierException(String message) {
-        super(message);
-    }
-
-    public ComponentVerifierException(String message, Throwable cause) {
-        super(message, cause);
-    }
-
-    public ComponentVerifierException(Throwable cause) {
-        super(cause);
-    }
-}

http://git-wip-us.apache.org/repos/asf/camel/blob/42529399/camel-core/src/main/java/org/apache/camel/ComponentVerifierHelper.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/ComponentVerifierHelper.java b/camel-core/src/main/java/org/apache/camel/ComponentVerifierHelper.java
deleted file mode 100644
index 7fc8115..0000000
--- a/camel-core/src/main/java/org/apache/camel/ComponentVerifierHelper.java
+++ /dev/null
@@ -1,140 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.camel;
-
-import org.apache.camel.ComponentVerifier.VerificationError.Attribute;
-import org.apache.camel.ComponentVerifier.VerificationError.Code;
-
-/**
- * Package visible helper class holding implementation classes for
- * constant like error code and attributes in {@link ComponentVerifier.VerificationError}
- */
-class ComponentVerifierHelper {
-
-    /**
-     * Custom class for error codes
-     */
-    static class ErrorCode implements Code {
-
-        private final String name;
-
-        ErrorCode(String name) {
-            if (name == null) {
-                throw new IllegalArgumentException("Name of an error code must not be null");
-            }
-            this.name = name;
-        }
-
-        @Override
-        public String name() {
-            return name;
-        }
-
-        @Override
-        public boolean equals(Object o) {
-            if (this == o) {
-                return true;
-            }
-            if (!(o instanceof Code)) {
-                return false;
-            }
-
-            Code errorCode = (Code) o;
-
-            return name.equals(errorCode.name());
-        }
-
-        @Override
-        public int hashCode() {
-            return name.hashCode();
-        }
-
-        @Override
-        public String toString() {
-            return name();
-        }
-    }
-
-    static class ErrorAttribute implements Attribute {
-
-        private final String name;
-
-        ErrorAttribute(String name) {
-            if (name == null) {
-                throw new IllegalArgumentException("Name of an error attribute must not be null");
-            }
-            this.name = name;
-        }
-
-        @Override
-        public String name() {
-            return name;
-        }
-
-
-        @Override
-        public boolean equals(Object o) {
-            if (this == o) {
-                return true;
-            }
-            if (!(o instanceof Attribute)) {
-                return false;
-            }
-
-            Attribute that = (Attribute) o;
-
-            return name.equals(that.name());
-        }
-
-        @Override
-        public int hashCode() {
-            return name.hashCode();
-        }
-
-        @Override
-        public String toString() {
-            return name();
-        }
-    }
-
-    // ===========================================================================================================
-    // Helper classes for implementing the constants in ComponentVerifier:
-
-    static class StandardErrorCode extends ErrorCode implements ComponentVerifier.VerificationError.StandardCode {
-        StandardErrorCode(String name) {
-            super(name);
-        }
-    }
-
-    static class ExceptionErrorAttribute extends ErrorAttribute implements ComponentVerifier.VerificationError.ExceptionAttribute {
-        ExceptionErrorAttribute(String name) {
-            super(name);
-        }
-    }
-
-    static class HttpErrorAttribute extends ErrorAttribute implements ComponentVerifier.VerificationError.HttpAttribute {
-        HttpErrorAttribute(String name) {
-            super(name);
-        }
-    }
-
-    static class GroupErrorAttribute extends ErrorAttribute implements ComponentVerifier.VerificationError.GroupAttribute {
-        GroupErrorAttribute(String name) {
-            super(name);
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/camel/blob/42529399/camel-core/src/main/java/org/apache/camel/IllegalOptionException.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/IllegalOptionException.java b/camel-core/src/main/java/org/apache/camel/IllegalOptionException.java
deleted file mode 100644
index 527eb9d..0000000
--- a/camel-core/src/main/java/org/apache/camel/IllegalOptionException.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.camel;
-
-public class IllegalOptionException extends ComponentVerifierException {
-    private final String optionName;
-    private final String optionValue;
-
-    public IllegalOptionException(String optionName) {
-        this(optionName, null);
-    }
-
-    public IllegalOptionException(String optionName, String optionValue) {
-        this.optionName = optionName;
-        this.optionValue = optionValue;
-    }
-
-    public String getOptionName() {
-        return optionName;
-    }
-
-    public String getOptionValue() {
-        return optionValue;
-    }
-}

http://git-wip-us.apache.org/repos/asf/camel/blob/42529399/camel-core/src/main/java/org/apache/camel/NoSuchOptionException.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/NoSuchOptionException.java b/camel-core/src/main/java/org/apache/camel/NoSuchOptionException.java
deleted file mode 100644
index 3f1d561..0000000
--- a/camel-core/src/main/java/org/apache/camel/NoSuchOptionException.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.camel;
-
-public class NoSuchOptionException extends ComponentVerifierException {
-    private final String optionName;
-
-    public NoSuchOptionException(String optionName) {
-        this.optionName = optionName;
-    }
-
-    public String getOptionName() {
-        return optionName;
-    }
-}

http://git-wip-us.apache.org/repos/asf/camel/blob/42529399/camel-core/src/main/java/org/apache/camel/VerifiableComponent.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/VerifiableComponent.java b/camel-core/src/main/java/org/apache/camel/VerifiableComponent.java
index 2b95404..2e2b6f6 100644
--- a/camel-core/src/main/java/org/apache/camel/VerifiableComponent.java
+++ b/camel-core/src/main/java/org/apache/camel/VerifiableComponent.java
@@ -18,7 +18,10 @@ package org.apache.camel;
 
 /**
  * An interface to represent an object which support validation
+ *
+ * @deprecated see {@link org.apache.camel.extension.ComponentExtension}
  */
+@Deprecated
 public interface VerifiableComponent {
     /**
      * Get the {@link ComponentVerifier}

http://git-wip-us.apache.org/repos/asf/camel/blob/42529399/camel-core/src/main/java/org/apache/camel/component/extension/ComponentExtension.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/component/extension/ComponentExtension.java b/camel-core/src/main/java/org/apache/camel/component/extension/ComponentExtension.java
new file mode 100644
index 0000000..8d90d31
--- /dev/null
+++ b/camel-core/src/main/java/org/apache/camel/component/extension/ComponentExtension.java
@@ -0,0 +1,26 @@
+/**
+ * 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.extension;
+
+/**
+ * Marker interface for component extensions.
+ * <p/>
+ * An extension is a feature provided by the component such as ComponentVerifier,
+ * ServiceMetaData.
+ */
+public interface ComponentExtension {
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/42529399/camel-core/src/main/java/org/apache/camel/component/extension/ComponentExtensionHelper.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/component/extension/ComponentExtensionHelper.java b/camel-core/src/main/java/org/apache/camel/component/extension/ComponentExtensionHelper.java
new file mode 100644
index 0000000..3487b3c
--- /dev/null
+++ b/camel-core/src/main/java/org/apache/camel/component/extension/ComponentExtensionHelper.java
@@ -0,0 +1,43 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.extension;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.CamelContextAware;
+import org.apache.camel.Component;
+import org.apache.camel.ComponentAware;
+
+public final class ComponentExtensionHelper {
+    private ComponentExtensionHelper() {
+    }
+
+    public static <T> T trySetCamelContext(T object, CamelContext camelContext) {
+        if (object instanceof CamelContextAware) {
+            ((CamelContextAware) object).setCamelContext(camelContext);
+        }
+
+        return object;
+    }
+
+    public static <T> T trySetComponent(T object, Component component) {
+        if (object instanceof ComponentAware) {
+            ((ComponentAware) object).setComponent(component);
+        }
+
+        return object;
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/42529399/camel-core/src/main/java/org/apache/camel/component/extension/ComponentVerifierExtension.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/component/extension/ComponentVerifierExtension.java b/camel-core/src/main/java/org/apache/camel/component/extension/ComponentVerifierExtension.java
new file mode 100644
index 0000000..f9acf0e
--- /dev/null
+++ b/camel-core/src/main/java/org/apache/camel/component/extension/ComponentVerifierExtension.java
@@ -0,0 +1,385 @@
+/**
+ * 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.extension;
+
+import java.io.Serializable;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.camel.Component;
+import org.apache.camel.component.extension.verifier.ComponentVerifierExtensionHelper;
+import org.apache.camel.component.extension.verifier.ResultErrorBuilder;
+import org.apache.camel.util.ObjectHelper;
+/**
+ * Defines the interface used for validating component/endpoint parameters. The central method of this
+ * interface is {@link #verify(ComponentVerifierExtension.Scope, Map)} which takes a scope and a set of parameters which should be verified.
+ * <p/>
+ * The return value is a {@link ComponentVerifierExtension.Result} of the verification
+ *
+ */
+public interface ComponentVerifierExtension extends ComponentExtension {
+
+    /**
+     * Verify the given parameters against a provided scope.
+     *
+     * <p>
+     * The supported scopes are:
+     * <ul>
+     *   <li><strong>{@link ComponentVerifierExtension.Scope#PARAMETERS}</strong>: to validate that all the mandatory options are provided and syntactically correct.</li>
+     *   <li><strong>{@link ComponentVerifierExtension.Scope#CONNECTIVITY}</strong>: to validate that the given options (i.e. credentials, addresses) are correct. Verifying with this
+     *       scope typically implies reaching out to the backend via some sort of network connection.</li>
+     * </ul>
+     *
+     * @param scope the scope of the verification
+     * @param parameters the parameters to verify which are interpreted individually by each component verifier
+     * @return the verification result
+     */
+    ComponentVerifierExtension.Result verify(ComponentVerifierExtension.Scope scope, Map<String, Object> parameters);
+
+    /**
+     * The result of a verification
+     */
+    interface Result extends Serializable {
+
+        /**
+         * Status of the verification
+         */
+        enum Status {
+            /**
+             * Verification succeeded
+             */
+            OK,
+            /**
+             * Error occurred during the verification
+             */
+            ERROR,
+            /**
+             * Verification is not supported. This can depend on the given scope.
+             */
+            UNSUPPORTED
+        }
+
+        /**
+         * Scope of the verification. This is the scope given to the call to {@link #verify(ComponentVerifierExtension.Scope, Map)}  and
+         * can be used for correlation.
+         *
+         * @return the scope against which the parameters have been validated.
+         */
+        ComponentVerifierExtension.Scope getScope();
+
+        /**
+         * Result of the validation as status. This should be the first datum to check after a verification
+         * happened.
+         *
+         * @return the status
+         */
+        ComponentVerifierExtension.Result.Status getStatus();
+
+        /**
+         * Collection of errors happened for the verification. This list is empty (but non null) if the verification
+         * succeeded.
+         *
+         * @return a list of errors. Can be empty when verification was successful
+         */
+        List<ComponentVerifierExtension.VerificationError> getErrors();
+    }
+
+    /**
+     * The scope defines how the parameters should be verified.
+     */
+    enum Scope {
+        /**
+         * Only validate the parameters for their <em>syntactic</em> soundness. Verifications in this scope should
+         * be as fast as possible
+         */
+        PARAMETERS,
+
+        /**
+         * Reach out to the backend and verify that a connection can be established. This means, if the verification
+         * in this scope succeeds, then it can safely be assumed that the component can be used.
+         */
+        CONNECTIVITY;
+
+        private static final ComponentVerifierExtension.Scope[] VALUES = values();
+
+        /**
+         * Get an instance of this scope from a string representation
+         *
+         * @param scope the scope as string, which can be in any case
+         * @return the scope enum represented by this string
+         */
+        public static ComponentVerifierExtension.Scope fromString(String scope) {
+            for (ComponentVerifierExtension.Scope value : VALUES) {
+                if (ObjectHelper.equal(scope, value.name(), true)) {
+                    return value;
+                }
+            }
+            throw new IllegalArgumentException("Unknown scope <" + scope + ">");
+        }
+    }
+
+    // =============================================================================================
+
+    /**
+     * This interface represents a detailed error in case when the verification fails.
+     */
+    interface VerificationError extends Serializable {
+
+        /**
+         * The overall error code, which can be either a {@link StandardCode} or a custom code. It is
+         * recommended to stick to the predefined standard codes
+         *
+         * @return the general error code.
+         */
+        Code getCode();
+
+        /**
+         * A human readable description of the error in plain english
+         *
+         * @return the error description (if available)
+         */
+        String getDescription();
+
+        /**
+         * A set of input parameter names which fails the verification. These are keys to the parameter provided
+         * to {@link #verify(ComponentVerifierExtension.Scope, Map)}.
+         *
+         * @return the parameter names which are malformed and caused the failure of the validation
+         */
+        Set<String> getParameterKeys();
+
+        /**
+         * Details about the failed verification. The keys can be either predefined values
+         * ({@link ExceptionAttribute}, {@link HttpAttribute}, {@link GroupAttribute}) or it can be free-form
+         * custom keys specific to a component. The standard attributes are defined as enums in all uppercase (with
+         * underscore as separator), custom attributes are supposed to be in all lower case (also with underscores
+         * as separators)
+         *
+         * @return a number of key/value pair with additional information related to the verification.
+         */
+        Map<ComponentVerifierExtension.VerificationError.Attribute, Object> getDetails();
+
+        /**
+         * Get a single detail for a given attribute
+         *
+         * @param attribute the attribute to lookup
+         * @return the detail value or null if no such attribute exists
+         */
+        default Object getDetail(ComponentVerifierExtension.VerificationError.Attribute attribute) {
+            Map<ComponentVerifierExtension.VerificationError.Attribute, Object> details = getDetails();
+            if (details != null) {
+                return details.get(attribute);
+            }
+            return null;
+        }
+
+        /**
+         * Get a single detail for a given attribute
+         *
+         * @param attribute the attribute to lookup
+         * @return the detail value or null if no such attribute exists
+         */
+        default Object getDetail(String attribute) {
+            return getDetail(asAttribute(attribute));
+        }
+
+        /**
+         * Convert a string to an {@link Code}
+         *
+         * @param code the code to convert. It should be in all lower case (with
+         *             underscore as a separator) to avoid overlap with {@link StandardCode}
+         * @return error code
+         */
+        static Code asCode(String code) {
+            return new ComponentVerifierExtensionHelper.ErrorCode(code);
+        }
+
+        /**
+         * Convert a string to an {@link Attribute}
+         *
+         * @param attribute the string representation of an attribute to convert. It should be in all lower case (with
+         *                  underscore as a separator) to avoid overlap with standard attributes like {@linkExceptionAttribute},
+         *                  {@linkHttpAttribute} or {@link GroupAttribute}
+         * @return generated attribute
+         */
+        static Attribute asAttribute(String attribute) {
+            return new ComponentVerifierExtensionHelper.ErrorAttribute(attribute);
+        }
+
+        /**
+         * Interface defining an error code. This is implemented by the {@link StandardCode} but also
+         * own code can be generated by implementing this interface. This is best done via {@link #asCode(String)}
+         * If possible, the standard codes should be reused
+         */
+        interface Code extends Serializable {
+            /**
+             * Name of the code. All uppercase for standard codes, all lower case for custom codes.
+             * Separator between two words is an underscore.
+             *
+             * @return code name
+             */
+            String name();
+
+            /**
+             * Bean style accessor to name.
+             * This is required for framework like Jackson using bean convention for object serialization.
+             *
+             * @return code name
+             */
+            default String getName() {
+                return name();
+            }
+        }
+
+        /**
+         * Standard set of error codes
+         */
+        interface StandardCode extends Code {
+            /**
+             * Authentication failed
+             */
+            StandardCode AUTHENTICATION = new ComponentVerifierExtensionHelper.StandardErrorCode("AUTHENTICATION");
+            /**
+             * An exception occurred
+             */
+            StandardCode EXCEPTION = new ComponentVerifierExtensionHelper.StandardErrorCode("EXCEPTION");
+            /**
+             * Internal error while performing the verification
+             */
+            StandardCode INTERNAL = new ComponentVerifierExtensionHelper.StandardErrorCode("INTERNAL");
+            /**
+             * A mandatory parameter is missing
+             */
+            StandardCode MISSING_PARAMETER = new ComponentVerifierExtensionHelper.StandardErrorCode("MISSING_PARAMETER");
+            /**
+             * A given parameter is not known to the component
+             */
+            StandardCode UNKNOWN_PARAMETER = new ComponentVerifierExtensionHelper.StandardErrorCode("UNKNOWN_PARAMETER");
+            /**
+             * A given parameter is illegal
+             */
+            StandardCode ILLEGAL_PARAMETER = new ComponentVerifierExtensionHelper.StandardErrorCode("ILLEGAL_PARAMETER");
+            /**
+             * A combination of parameters is illegal. See {@link ComponentVerifierExtension.VerificationError#getParameterKeys()} for the set
+             * of affected parameters
+             */
+            StandardCode ILLEGAL_PARAMETER_GROUP_COMBINATION = new ComponentVerifierExtensionHelper.StandardErrorCode("ILLEGAL_PARAMETER_GROUP_COMBINATION");
+            /**
+             * A parameter <em>value</em> is not valid
+             */
+            StandardCode ILLEGAL_PARAMETER_VALUE = new ComponentVerifierExtensionHelper.StandardErrorCode("ILLEGAL_PARAMETER_VALUE");
+            /**
+             * A group of parameters is not complete in order to be valid
+             */
+            StandardCode INCOMPLETE_PARAMETER_GROUP = new ComponentVerifierExtensionHelper.StandardErrorCode("INCOMPLETE_PARAMETER_GROUP");
+            /**
+             * The verification is not supported
+             */
+            StandardCode UNSUPPORTED = new ComponentVerifierExtensionHelper.StandardErrorCode("UNSUPPORTED");
+            /**
+             * The requested {@link ComponentVerifierExtension.Scope} is not supported
+             */
+            StandardCode UNSUPPORTED_SCOPE = new ComponentVerifierExtensionHelper.StandardErrorCode("UNSUPPORTED_SCOPE");
+            /**
+             * The requested {@link Component} is not supported
+             */
+            StandardCode UNSUPPORTED_COMPONENT = new ComponentVerifierExtensionHelper.StandardErrorCode("UNSUPPORTED_COMPONENT");
+            /**
+             * Generic error which is explained in more details with {@link ComponentVerifierExtension.VerificationError#getDetails()}
+             */
+            StandardCode GENERIC = new ComponentVerifierExtensionHelper.StandardErrorCode("GENERIC");
+        }
+
+        /**
+         * Interface defining an attribute which is a key for the detailed error messages. This is implemented by several
+         * standard enums like {@link ExceptionAttribute}, {@link HttpAttribute} or {@link GroupAttribute} but can also
+         * implemented for component specific details. This is best done via {@link #asAttribute(String)}
+         * or using one of the other builder method in this error builder (like {@link ResultErrorBuilder#detail(String, Object)}
+         * <p>
+         * With respecting to name, the same rules as for {@link Code} apply: Standard attributes are all upper case with _
+         * as separators, whereas custom attributes are lower case with underscore separators.
+         */
+        interface Attribute extends Serializable {
+            /**
+             * Name of the attribute. All uppercase for standard attributes and all lower case for custom attributes.
+             * Separator between words is an underscore.
+             *
+             * @return attribute name
+             */
+            String name();
+
+            /**
+             * Bean style accessor to name;
+             * This is required for framework like Jackson using bean convention for object serialization.
+             *
+             * @return attribute name
+             */
+            default String getName() {
+                return name();
+            }
+        }
+
+        /**
+         * Attributes for details about an exception that was raised
+         */
+        interface ExceptionAttribute extends Attribute {
+            /**
+             * The exception object that has been thrown. Note that this can be a complex
+             * object and can cause large content when e.g. serialized as JSON
+             */
+            ExceptionAttribute EXCEPTION_INSTANCE = new ComponentVerifierExtensionHelper.ExceptionErrorAttribute("EXCEPTION_INSTANCE");
+            /**
+             * The exception class
+             */
+            ExceptionAttribute EXCEPTION_CLASS = new ComponentVerifierExtensionHelper.ExceptionErrorAttribute("EXCEPTION_CLASS");
+        }
+
+        /**
+         * HTTP related error details
+         */
+        interface HttpAttribute extends Attribute {
+            /**
+             * The erroneous HTTP code that occurred
+             */
+            HttpAttribute HTTP_CODE = new ComponentVerifierExtensionHelper.HttpErrorAttribute("HTTP_CODE");
+            /**
+             * HTTP response's body
+             */
+            HttpAttribute HTTP_TEXT = new ComponentVerifierExtensionHelper.HttpErrorAttribute("HTTP_TEXT");
+            /**
+             * If given as details, specifies that a redirect happened and the
+             * content of this detail is the redirect URL
+             */
+            HttpAttribute HTTP_REDIRECT = new ComponentVerifierExtensionHelper.HttpErrorAttribute("HTTP_REDIRECT");
+        }
+
+        /**
+         * Group related details
+         */
+        interface GroupAttribute extends Attribute {
+            /**
+             * Group name
+             */
+            GroupAttribute GROUP_NAME = new ComponentVerifierExtensionHelper.GroupErrorAttribute("GROUP_NAME");
+            /**
+             * Options for the group
+             */
+            GroupAttribute GROUP_OPTIONS = new ComponentVerifierExtensionHelper.GroupErrorAttribute("GROUP_OPTIONS");
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/camel/blob/42529399/camel-core/src/main/java/org/apache/camel/component/extension/MetaDataExtension.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/component/extension/MetaDataExtension.java b/camel-core/src/main/java/org/apache/camel/component/extension/MetaDataExtension.java
new file mode 100644
index 0000000..9361e66
--- /dev/null
+++ b/camel-core/src/main/java/org/apache/camel/component/extension/MetaDataExtension.java
@@ -0,0 +1,74 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.extension;
+
+import java.util.Map;
+import java.util.Optional;
+
+import org.apache.camel.Exchange;
+import org.apache.camel.TypeConversionException;
+
+public interface MetaDataExtension extends ComponentExtension {
+    /**
+     * @param parameters
+     * @return the {@link MetaData}
+     */
+    Optional<MetaData> meta(Map<String, Object> parameters);
+
+    interface MetaData {
+        // Common meta-data attributes
+        String CONTENT_TYPE = Exchange.CONTENT_TYPE;
+        String JAVA_TYPE = "Java-Type";
+
+        /**
+         *
+         * Returns an attribute associated with this meta data by name.
+         *
+         * @param name the attribute name
+         * @return the attribute
+         */
+        Object getAttribute(String name);
+
+        /**
+         *
+         * Returns an attribute associated with this meta data by name and
+         * specifying the type required.
+         *
+         * @param name the attribute name
+         * @param type the type of the attribute
+         * @return the value of the given attribute or <tt>null</tt> if there is no attribute for the given name
+         * @throws TypeConversionException is thrown if error during type conversion
+         */
+        <T> T getAttribute(String name, Class<T> type);
+
+        /**
+         * Returns the payload of the meta data as a POJO.
+         *
+         * @return the body, can be <tt>null</tt>
+         */
+        Object getPayload();
+
+        /**
+         * Returns the payload of the meta data as specified type.
+         *
+         * @param type the type that the payload should be converted yo.
+         * @return the payload of the meta data as the specified type.
+         * @throws TypeConversionException is thrown if error during type conversion
+         */
+        <T> T getPayload(Class<T> type);
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/42529399/camel-core/src/main/java/org/apache/camel/component/extension/metadata/AbstractMetaDataExtension.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/component/extension/metadata/AbstractMetaDataExtension.java b/camel-core/src/main/java/org/apache/camel/component/extension/metadata/AbstractMetaDataExtension.java
new file mode 100644
index 0000000..c8bd577
--- /dev/null
+++ b/camel-core/src/main/java/org/apache/camel/component/extension/metadata/AbstractMetaDataExtension.java
@@ -0,0 +1,65 @@
+/**
+ * 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.extension.metadata;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.CamelContextAware;
+import org.apache.camel.Component;
+import org.apache.camel.ComponentAware;
+import org.apache.camel.component.extension.MetaDataExtension;
+
+public abstract class AbstractMetaDataExtension implements MetaDataExtension, ComponentAware, CamelContextAware {
+    private CamelContext camelContext;
+    private Component component;
+
+    protected AbstractMetaDataExtension() {
+        this(null, null);
+    }
+
+    protected AbstractMetaDataExtension(Component component) {
+        this(component, component.getCamelContext());
+    }
+
+    protected AbstractMetaDataExtension(CamelContext camelContext) {
+        this(null, camelContext);
+    }
+
+    protected AbstractMetaDataExtension(Component component, CamelContext camelContext) {
+        this.component = component;
+        this.camelContext = camelContext;
+    }
+
+    @Override
+    public void setComponent(Component component) {
+        this.component = component;
+    }
+
+    @Override
+    public Component getComponent() {
+        return component;
+    }
+
+    @Override
+    public void setCamelContext(CamelContext camelContext) {
+        this.camelContext = camelContext;
+    }
+
+    @Override
+    public CamelContext getCamelContext() {
+        return camelContext;
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/42529399/camel-core/src/main/java/org/apache/camel/component/extension/metadata/DefaultMetaData.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/component/extension/metadata/DefaultMetaData.java b/camel-core/src/main/java/org/apache/camel/component/extension/metadata/DefaultMetaData.java
new file mode 100644
index 0000000..b1e2df4
--- /dev/null
+++ b/camel-core/src/main/java/org/apache/camel/component/extension/metadata/DefaultMetaData.java
@@ -0,0 +1,63 @@
+/**
+ * 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.extension.metadata;
+
+import java.util.Map;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.component.extension.MetaDataExtension;
+
+public class DefaultMetaData implements MetaDataExtension.MetaData {
+    private final Map<String, Object> attributes;
+    private final Object payload;
+    private CamelContext camelContext;
+    
+    public DefaultMetaData(CamelContext camelContext, Map<String, Object> attributes, Object payload) {
+        this.camelContext = camelContext;
+        this.attributes = attributes;
+        this.payload = payload;
+    }
+
+    @Override
+    public Object getAttribute(String name) {
+        return attributes.get(name);
+    }
+
+    @Override
+    public <T> T getAttribute(String name, Class<T> type) {
+        Object value = attributes.get(name);
+        if (camelContext != null) {
+            return camelContext.getTypeConverter().convertTo(type, value);
+        }
+
+        throw new IllegalStateException("Unable to perform conversion as CamelContext is not set");
+    }
+
+    @Override
+    public Object getPayload() {
+        return payload;
+    }
+
+    @Override
+    public <T> T getPayload(Class<T> type) {
+        if (camelContext != null) {
+            return camelContext.getTypeConverter().convertTo(type, payload);
+        }
+
+        throw new IllegalStateException("Unable to perform conversion as CamelContext is not set");
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/42529399/camel-core/src/main/java/org/apache/camel/component/extension/metadata/MetaDataBuilder.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/component/extension/metadata/MetaDataBuilder.java b/camel-core/src/main/java/org/apache/camel/component/extension/metadata/MetaDataBuilder.java
new file mode 100644
index 0000000..0957c64
--- /dev/null
+++ b/camel-core/src/main/java/org/apache/camel/component/extension/metadata/MetaDataBuilder.java
@@ -0,0 +1,64 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.extension.metadata;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.component.extension.MetaDataExtension;
+
+public final class MetaDataBuilder {
+    private final CamelContext camelContext;
+    private Object payload;
+    private Map<String, Object> attributes;
+
+    private MetaDataBuilder(CamelContext camelContext) {
+        this.camelContext = camelContext;
+    }
+
+    public MetaDataBuilder withPayload(Object payload) {
+        this.payload = payload;
+        return this;
+    }
+
+    public MetaDataBuilder withAttribute(String name, Object value) {
+        if (this.attributes == null) {
+            this.attributes = new HashMap<>();
+        }
+
+        this.attributes.put(name, value);
+        return this;
+    }
+
+    public MetaDataExtension.MetaData build() {
+        return new DefaultMetaData(
+            camelContext,
+            attributes == null ? Collections.emptyMap() : attributes,
+            payload
+        );
+    }
+
+    // *****************************
+    //
+    // *****************************
+
+    public static MetaDataBuilder on(CamelContext camelContext) {
+        return new MetaDataBuilder(camelContext);
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/42529399/camel-core/src/main/java/org/apache/camel/component/extension/metadata/package.html
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/component/extension/metadata/package.html b/camel-core/src/main/java/org/apache/camel/component/extension/metadata/package.html
new file mode 100644
index 0000000..6687307
--- /dev/null
+++ b/camel-core/src/main/java/org/apache/camel/component/extension/metadata/package.html
@@ -0,0 +1,25 @@
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one or more
+  ~ contributor license agreements.  See the NOTICE file distributed with
+  ~ this work for additional information regarding copyright ownership.
+  ~ The ASF licenses this file to You under the Apache License, Version 2.0
+  ~ (the "License"); you may not use this file except in compliance with
+  ~ the License.  You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+<html>
+<head>
+</head>
+<body>
+
+MetaData component extension
+
+</body>
+</html>

http://git-wip-us.apache.org/repos/asf/camel/blob/42529399/camel-core/src/main/java/org/apache/camel/component/extension/package.html
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/component/extension/package.html b/camel-core/src/main/java/org/apache/camel/component/extension/package.html
new file mode 100644
index 0000000..be2383a
--- /dev/null
+++ b/camel-core/src/main/java/org/apache/camel/component/extension/package.html
@@ -0,0 +1,25 @@
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one or more
+  ~ contributor license agreements.  See the NOTICE file distributed with
+  ~ this work for additional information regarding copyright ownership.
+  ~ The ASF licenses this file to You under the Apache License, Version 2.0
+  ~ (the "License"); you may not use this file except in compliance with
+  ~ the License.  You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+<html>
+<head>
+</head>
+<body>
+
+Component extension
+
+</body>
+</html>

http://git-wip-us.apache.org/repos/asf/camel/blob/42529399/camel-core/src/main/java/org/apache/camel/component/extension/verifier/CatalogVerifierCustomizer.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/component/extension/verifier/CatalogVerifierCustomizer.java b/camel-core/src/main/java/org/apache/camel/component/extension/verifier/CatalogVerifierCustomizer.java
new file mode 100644
index 0000000..e8d256a
--- /dev/null
+++ b/camel-core/src/main/java/org/apache/camel/component/extension/verifier/CatalogVerifierCustomizer.java
@@ -0,0 +1,104 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.extension.verifier;
+
+public class CatalogVerifierCustomizer {
+    private boolean includeUnknown = true;
+    private boolean includeRequired = true;
+    private boolean includeInvalidBoolean = true;
+    private boolean includeInvalidInteger = true;
+    private boolean includeInvalidNumber = true;
+    private boolean includeInvalidEnum = true;
+
+    public boolean isIncludeUnknown() {
+        return includeUnknown;
+    }
+
+    public void setIncludeUnknown(boolean includeUnknown) {
+        this.includeUnknown = includeUnknown;
+    }
+
+    public boolean isIncludeRequired() {
+        return includeRequired;
+    }
+
+    public void setIncludeRequired(boolean includeRequired) {
+        this.includeRequired = includeRequired;
+    }
+
+    public boolean isIncludeInvalidBoolean() {
+        return includeInvalidBoolean;
+    }
+
+    public void setIncludeInvalidBoolean(boolean includeInvalidBoolean) {
+        this.includeInvalidBoolean = includeInvalidBoolean;
+    }
+
+    public boolean isIncludeInvalidInteger() {
+        return includeInvalidInteger;
+    }
+
+    public void setIncludeInvalidInteger(boolean includeInvalidInteger) {
+        this.includeInvalidInteger = includeInvalidInteger;
+    }
+
+    public boolean isIncludeInvalidNumber() {
+        return includeInvalidNumber;
+    }
+
+    public void setIncludeInvalidNumber(boolean includeInvalidNumber) {
+        this.includeInvalidNumber = includeInvalidNumber;
+    }
+
+    public boolean isIncludeInvalidEnum() {
+        return includeInvalidEnum;
+    }
+
+    public void setIncludeInvalidEnum(boolean includeInvalidEnum) {
+        this.includeInvalidEnum = includeInvalidEnum;
+    }
+
+    public CatalogVerifierCustomizer excludeUnknown() {
+        this.includeUnknown = false;
+        return this;
+    }
+
+    public CatalogVerifierCustomizer excludeRequired() {
+        this.includeRequired = false;
+        return this;
+    }
+
+    public CatalogVerifierCustomizer excludeInvalidBoolean() {
+        this.includeInvalidBoolean = false;
+        return this;
+    }
+
+    public CatalogVerifierCustomizer excludeInvalidInteger() {
+        this.includeInvalidInteger = false;
+        return this;
+    }
+
+    public CatalogVerifierCustomizer excludeInvalidNumber() {
+        this.includeInvalidNumber = false;
+        return this;
+    }
+
+    public CatalogVerifierCustomizer excludeInvalidEnum() {
+        this.includeInvalidEnum = false;
+        return this;
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/42529399/camel-core/src/main/java/org/apache/camel/component/extension/verifier/ComponentVerifierException.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/component/extension/verifier/ComponentVerifierException.java b/camel-core/src/main/java/org/apache/camel/component/extension/verifier/ComponentVerifierException.java
new file mode 100644
index 0000000..690a571
--- /dev/null
+++ b/camel-core/src/main/java/org/apache/camel/component/extension/verifier/ComponentVerifierException.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.component.extension.verifier;
+
+import org.apache.camel.CamelException;
+
+public class ComponentVerifierException extends CamelException {
+    public ComponentVerifierException() {
+    }
+
+    public ComponentVerifierException(String message) {
+        super(message);
+    }
+
+    public ComponentVerifierException(String message, Throwable cause) {
+        super(message, cause);
+    }
+
+    public ComponentVerifierException(Throwable cause) {
+        super(cause);
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/42529399/camel-core/src/main/java/org/apache/camel/component/extension/verifier/ComponentVerifierExtensionHelper.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/component/extension/verifier/ComponentVerifierExtensionHelper.java b/camel-core/src/main/java/org/apache/camel/component/extension/verifier/ComponentVerifierExtensionHelper.java
new file mode 100644
index 0000000..583ccf7
--- /dev/null
+++ b/camel-core/src/main/java/org/apache/camel/component/extension/verifier/ComponentVerifierExtensionHelper.java
@@ -0,0 +1,145 @@
+/**
+ * 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.extension.verifier;
+
+import org.apache.camel.component.extension.ComponentVerifierExtension;
+import org.apache.camel.component.extension.ComponentVerifierExtension.VerificationError.Attribute;
+import org.apache.camel.component.extension.ComponentVerifierExtension.VerificationError.Code;
+import org.apache.camel.component.extension.ComponentVerifierExtension.VerificationError.ExceptionAttribute;
+import org.apache.camel.component.extension.ComponentVerifierExtension.VerificationError.GroupAttribute;
+import org.apache.camel.component.extension.ComponentVerifierExtension.VerificationError.HttpAttribute;
+import org.apache.camel.component.extension.ComponentVerifierExtension.VerificationError.StandardCode;
+
+/**
+ * Package visible helper class holding implementation classes for
+ * constant like error code and attributes in {@link  ComponentVerifierExtension.VerificationError}
+ */
+public final class ComponentVerifierExtensionHelper {
+
+    /**
+     * Custom class for error codes
+     */
+    public static class ErrorCode implements Code {
+
+        private final String name;
+
+        public ErrorCode(String name) {
+            if (name == null) {
+                throw new IllegalArgumentException("Name of an error code must not be null");
+            }
+            this.name = name;
+        }
+
+        @Override
+        public String name() {
+            return name;
+        }
+
+        @Override
+        public boolean equals(Object o) {
+            if (this == o) {
+                return true;
+            }
+            if (!(o instanceof Code)) {
+                return false;
+            }
+
+            Code errorCode = (Code) o;
+
+            return name.equals(errorCode.name());
+        }
+
+        @Override
+        public int hashCode() {
+            return name.hashCode();
+        }
+
+        @Override
+        public String toString() {
+            return name();
+        }
+    }
+
+    public static class ErrorAttribute implements Attribute {
+
+        private final String name;
+
+        public ErrorAttribute(String name) {
+            if (name == null) {
+                throw new IllegalArgumentException("Name of an error attribute must not be null");
+            }
+            this.name = name;
+        }
+
+        @Override
+        public String name() {
+            return name;
+        }
+
+
+        @Override
+        public boolean equals(Object o) {
+            if (this == o) {
+                return true;
+            }
+            if (!(o instanceof Attribute)) {
+                return false;
+            }
+
+            Attribute that = (Attribute) o;
+
+            return name.equals(that.name());
+        }
+
+        @Override
+        public int hashCode() {
+            return name.hashCode();
+        }
+
+        @Override
+        public String toString() {
+            return name();
+        }
+    }
+
+    // ===========================================================================================================
+    // Helper classes for implementing the constants in ComponentVerifier:
+
+    public static class StandardErrorCode extends ErrorCode implements StandardCode {
+        public StandardErrorCode(String name) {
+            super(name);
+        }
+    }
+
+    public static class ExceptionErrorAttribute extends ErrorAttribute implements ExceptionAttribute {
+        public ExceptionErrorAttribute(String name) {
+            super(name);
+        }
+    }
+
+    public static class HttpErrorAttribute extends ErrorAttribute implements HttpAttribute {
+        public HttpErrorAttribute(String name) {
+            super(name);
+        }
+    }
+
+    public static class GroupErrorAttribute extends ErrorAttribute implements GroupAttribute {
+        public GroupErrorAttribute(String name) {
+            super(name);
+        }
+    }
+}


[16/19] camel git commit: CAMEL-11555: ServiceNow : create a maven plugin to generate models based on table layout

Posted by lb...@apache.org.
http://git-wip-us.apache.org/repos/asf/camel/blob/109da7c9/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/releases/helsinki/HelsinkiServiceNowServiceCatalogItemsProcessor.java
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/releases/helsinki/HelsinkiServiceNowServiceCatalogItemsProcessor.java b/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/releases/helsinki/HelsinkiServiceNowServiceCatalogItemsProcessor.java
new file mode 100644
index 0000000..c0520c1
--- /dev/null
+++ b/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/releases/helsinki/HelsinkiServiceNowServiceCatalogItemsProcessor.java
@@ -0,0 +1,216 @@
+/**
+ * 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.servicenow.releases.helsinki;
+
+import javax.ws.rs.HttpMethod;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+import org.apache.camel.Exchange;
+import org.apache.camel.Message;
+import org.apache.camel.component.servicenow.AbstractServiceNowProcessor;
+import org.apache.camel.component.servicenow.ServiceNowEndpoint;
+import org.apache.camel.component.servicenow.ServiceNowParams;
+import org.apache.camel.util.ObjectHelper;
+
+import static org.apache.camel.component.servicenow.ServiceNowConstants.ACTION_CREATE;
+import static org.apache.camel.component.servicenow.ServiceNowConstants.ACTION_RETRIEVE;
+import static org.apache.camel.component.servicenow.ServiceNowConstants.ACTION_SUBJECT_CART;
+import static org.apache.camel.component.servicenow.ServiceNowConstants.ACTION_SUBJECT_CHECKOUT_GUIDE;
+import static org.apache.camel.component.servicenow.ServiceNowConstants.ACTION_SUBJECT_PRODUCER;
+import static org.apache.camel.component.servicenow.ServiceNowConstants.ACTION_SUBJECT_SUBMIT_GUIDE;
+
+class HelsinkiServiceNowServiceCatalogItemsProcessor extends AbstractServiceNowProcessor {
+
+    HelsinkiServiceNowServiceCatalogItemsProcessor(ServiceNowEndpoint endpoint) throws Exception {
+        super(endpoint);
+
+        addDispatcher(ACTION_RETRIEVE, ACTION_SUBJECT_SUBMIT_GUIDE, this::submitItemGuide);
+        addDispatcher(ACTION_RETRIEVE, ACTION_SUBJECT_CHECKOUT_GUIDE, this::checkoutItemGuide);
+        addDispatcher(ACTION_RETRIEVE, this::retrieveItems);
+        addDispatcher(ACTION_CREATE, ACTION_SUBJECT_CART, this::addItemToCart);
+        addDispatcher(ACTION_CREATE, ACTION_SUBJECT_PRODUCER, this::submitItemProducer);
+    }
+
+    /*
+     * This method retrieves a list of catalogs to which the user has access or
+     * a single one if sys_id is defined.
+     *
+     * Method:
+     * - GET
+     *
+     * URL Format:
+     * - /sn_sc/servicecatalog/items
+     * - /sn_sc/servicecatalog/items/{sys_id}
+     */
+    private void retrieveItems(Exchange exchange) throws Exception {
+        final Message in = exchange.getIn();
+        final Class<?> responseModel = getResponseModel(in);
+        final String sysId = getSysID(in);
+        final String apiVersion = getApiVersion(in);
+
+        Response response = ObjectHelper.isEmpty(sysId)
+            ? client.reset()
+                .types(MediaType.APPLICATION_JSON_TYPE)
+                .path("sn_sc")
+                .path(apiVersion)
+                .path("servicecatalog")
+                .path("items")
+                .query(ServiceNowParams.SYSPARM_CATEGORY, in)
+                .query(ServiceNowParams.SYSPARM_TYPE, in)
+                .query(ServiceNowParams.SYSPARM_LIMIT, in)
+                .query(ServiceNowParams.SYSPARM_TEXT, in)
+                .query(ServiceNowParams.SYSPARM_OFFSET, in)
+                .query(ServiceNowParams.SYSPARM_CATALOG, in)
+                .query(ServiceNowParams.SYSPARM_VIEW, in)
+                .query(responseModel)
+                .invoke(HttpMethod.GET)
+            : client.reset()
+                .types(MediaType.APPLICATION_JSON_TYPE)
+                .path("sn_sc")
+                .path(apiVersion)
+                .path("items")
+                .path("items")
+                .path(sysId)
+                .query(ServiceNowParams.SYSPARM_VIEW, in)
+                .query(responseModel)
+                .invoke(HttpMethod.GET);
+
+        setBodyAndHeaders(in, responseModel, response);
+    }
+
+    /*
+     * This method retrieves a list of items based on the needs described for an
+     * order guide.
+     *
+     * Method:
+     * - POST
+     *
+     * URL Format:
+     * - /sn_sc/servicecatalog/items/{sys_id}/submit_guide
+     */
+    private void submitItemGuide(Exchange exchange) throws Exception {
+        final Message in = exchange.getIn();
+        final Class<?> responseModel = getResponseModel(in);
+        final String sysId = getSysID(in);
+        final String apiVersion = getApiVersion(in);
+
+        Response response =  client.reset()
+            .types(MediaType.APPLICATION_JSON_TYPE)
+            .path("sn_sc")
+            .path(apiVersion)
+            .path("servicecatalog")
+            .path("items")
+            .path(ObjectHelper.notNull(sysId, "sysId"))
+            .path("submit_guide")
+            .query(ServiceNowParams.SYSPARM_VIEW, in)
+            .query(responseModel)
+            .invoke(HttpMethod.POST, in.getMandatoryBody());
+
+        setBodyAndHeaders(in, responseModel, response);
+    }
+
+    /*
+     * This method retrieves an array of contents requested for checkout.
+     *
+     * Method:
+     * - POST
+     *
+     * URL Format:
+     * - /sn_sc/servicecatalog/items/{sys_id}/checkout_guide
+     */
+    private void checkoutItemGuide(Exchange exchange) throws Exception {
+        final Message in = exchange.getIn();
+        final Class<?> responseModel = getResponseModel(in);
+        final String sysId = getSysID(in);
+        final String apiVersion = getApiVersion(in);
+
+        Response response = client.reset()
+            .types(MediaType.APPLICATION_JSON_TYPE)
+            .path("sn_sc")
+            .path(apiVersion)
+            .path("servicecatalog")
+            .path("items")
+            .path(ObjectHelper.notNull(sysId, "sysId"))
+            .path("submit_guide")
+            .query(responseModel)
+            .invoke(HttpMethod.POST, in.getMandatoryBody());
+
+        setBodyAndHeaders(in, responseModel, response);
+    }
+
+    /*
+     * This method adds an item to the cart of the current user.
+     *
+     * Method:
+     * - POST
+     *
+     * URL Format:
+     * - /sn_sc/servicecatalog/items/{sys_id}/add_to_cart
+     */
+    private void addItemToCart(Exchange exchange) throws Exception {
+        final Message in = exchange.getIn();
+        final Class<?> responseModel = getResponseModel(in);
+        final String sysId = getSysID(in);
+        final String apiVersion = getApiVersion(in);
+
+        Response response = client.reset()
+            .types(MediaType.APPLICATION_JSON_TYPE)
+            .path("sn_sc")
+            .path(apiVersion)
+            .path("servicecatalog")
+            .path("items")
+            .path(ObjectHelper.notNull(sysId, "sysId"))
+            .path("add_to_cart")
+            .query(responseModel)
+            .invoke(HttpMethod.POST);
+
+        setBodyAndHeaders(in, responseModel, response);
+    }
+
+    /*
+     * This method creates a record and returns the Table API relative path and
+     * redirect url to access the created record.
+     *
+     * Method:
+     * - POST
+     *
+     * URL Format:
+     * - /sn_sc/servicecatalog/items/{sys_id}/submit_producer
+     */
+    private void submitItemProducer(Exchange exchange) throws Exception {
+        final Message in = exchange.getIn();
+        final Class<?> responseModel = getResponseModel(in);
+        final String sysId = getSysID(in);
+        final String apiVersion = getApiVersion(in);
+
+        Response response = client.reset()
+            .types(MediaType.APPLICATION_JSON_TYPE)
+            .path("sn_sc")
+            .path(apiVersion)
+            .path("servicecatalog")
+            .path("items")
+            .path(ObjectHelper.notNull(sysId, "sysId"))
+            .path("submit_producer")
+            .query(ServiceNowParams.SYSPARM_VIEW, in)
+            .query(responseModel)
+            .invoke(HttpMethod.POST, in.getMandatoryBody());
+
+        setBodyAndHeaders(in, responseModel, response);
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/109da7c9/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/releases/helsinki/HelsinkiServiceNowServiceCatalogProcessor.java
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/releases/helsinki/HelsinkiServiceNowServiceCatalogProcessor.java b/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/releases/helsinki/HelsinkiServiceNowServiceCatalogProcessor.java
new file mode 100644
index 0000000..42b5da3
--- /dev/null
+++ b/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/releases/helsinki/HelsinkiServiceNowServiceCatalogProcessor.java
@@ -0,0 +1,118 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.camel.component.servicenow.releases.helsinki;
+
+import javax.ws.rs.HttpMethod;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+import org.apache.camel.Exchange;
+import org.apache.camel.Message;
+import org.apache.camel.component.servicenow.AbstractServiceNowProcessor;
+import org.apache.camel.component.servicenow.ServiceNowEndpoint;
+import org.apache.camel.component.servicenow.ServiceNowParams;
+import org.apache.camel.util.ObjectHelper;
+
+import static org.apache.camel.component.servicenow.ServiceNowConstants.ACTION_RETRIEVE;
+import static org.apache.camel.component.servicenow.ServiceNowConstants.ACTION_SUBJECT_CATEGORIES;
+
+class HelsinkiServiceNowServiceCatalogProcessor extends AbstractServiceNowProcessor {
+
+    HelsinkiServiceNowServiceCatalogProcessor(ServiceNowEndpoint endpoint) throws Exception {
+        super(endpoint);
+
+        addDispatcher(ACTION_RETRIEVE, ACTION_SUBJECT_CATEGORIES, this::retrieveCatalogsCategories);
+        addDispatcher(ACTION_RETRIEVE, this::retrieveCatalogs);
+    }
+
+    /*
+     * This method retrieves a list of catalogs to which the user has access or
+     * a single one if sys_id is defined.
+     *
+     * Method:
+     * - GET
+     *
+     * URL Format:
+     * - /sn_sc/servicecatalog/catalogs
+     * - /sn_sc/servicecatalog/catalogs/{sys_id}
+     */
+    private void retrieveCatalogs(Exchange exchange) throws Exception {
+        final Message in = exchange.getIn();
+        final Class<?> responseModel = getResponseModel(in);
+        final String sysId = getSysID(in);
+        final String apiVersion = getApiVersion(in);
+
+        Response response = ObjectHelper.isEmpty(sysId)
+            ? client.reset()
+                .types(MediaType.APPLICATION_JSON_TYPE)
+                .path("sn_sc")
+                .path(apiVersion)
+                .path("servicecatalog")
+                .path("catalogs")
+                .query(ServiceNowParams.SYSPARM_LIMIT, in)
+                .query(ServiceNowParams.SYSPARM_QUERY, in)
+                .query(ServiceNowParams.SYSPARM_VIEW, in)
+                .query(responseModel)
+                .invoke(HttpMethod.GET)
+            : client.reset()
+                .types(MediaType.APPLICATION_JSON_TYPE)
+                .path("sn_sc")
+                .path(apiVersion)
+                .path("servicecatalog")
+                .path("catalogs")
+                .path(sysId)
+                .query(ServiceNowParams.SYSPARM_VIEW, in)
+                .query(responseModel)
+                .invoke(HttpMethod.GET);
+
+        setBodyAndHeaders(in, responseModel, response);
+    }
+
+    /*
+     * This method retrieves a list of categories for a catalog.
+     *
+     * Method:
+     * - GET
+     *
+     * URL Format:
+     * - /sn_sc/servicecatalog/catalogs/{sys_id}/categories
+     */
+    private void retrieveCatalogsCategories(Exchange exchange) throws Exception {
+        final Message in = exchange.getIn();
+        final Class<?> responseModel = getResponseModel(in);
+        final String sysId = getSysID(in);
+        final String apiVersion = getApiVersion(in);
+
+        Response response = client.reset()
+            .types(MediaType.APPLICATION_JSON_TYPE)
+            .path("sn_sc")
+            .path(apiVersion)
+            .path("servicecatalog")
+            .path("catalogs")
+            .path(ObjectHelper.notNull(sysId, "sysId"))
+            .path("categories")
+            .query(ServiceNowParams.SYSPARM_TOP_LEVEL_ONLY, in)
+            .query(ServiceNowParams.SYSPARM_LIMIT, in)
+            .query(ServiceNowParams.SYSPARM_VIEW, in)
+            .query(ServiceNowParams.SYSPARM_OFFSET, in)
+            .query(responseModel)
+            .invoke(HttpMethod.GET);
+
+        setBodyAndHeaders(in, responseModel, response);
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/109da7c9/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/releases/helsinki/HelsinkiServiceNowTableProcessor.java
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/releases/helsinki/HelsinkiServiceNowTableProcessor.java b/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/releases/helsinki/HelsinkiServiceNowTableProcessor.java
new file mode 100644
index 0000000..8e62408
--- /dev/null
+++ b/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/releases/helsinki/HelsinkiServiceNowTableProcessor.java
@@ -0,0 +1,214 @@
+/**
+ * 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.servicenow.releases.helsinki;
+
+import javax.ws.rs.HttpMethod;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+import org.apache.camel.Exchange;
+import org.apache.camel.Message;
+import org.apache.camel.component.servicenow.AbstractServiceNowProcessor;
+import org.apache.camel.component.servicenow.ServiceNowEndpoint;
+import org.apache.camel.component.servicenow.ServiceNowParams;
+import org.apache.camel.util.ObjectHelper;
+
+import static org.apache.camel.component.servicenow.ServiceNowConstants.ACTION_CREATE;
+import static org.apache.camel.component.servicenow.ServiceNowConstants.ACTION_DELETE;
+import static org.apache.camel.component.servicenow.ServiceNowConstants.ACTION_MODIFY;
+import static org.apache.camel.component.servicenow.ServiceNowConstants.ACTION_RETRIEVE;
+import static org.apache.camel.component.servicenow.ServiceNowConstants.ACTION_UPDATE;
+
+class HelsinkiServiceNowTableProcessor extends AbstractServiceNowProcessor {
+    HelsinkiServiceNowTableProcessor(ServiceNowEndpoint endpoint) throws Exception {
+        super(endpoint);
+
+        addDispatcher(ACTION_RETRIEVE, this::retrieveRecord);
+        addDispatcher(ACTION_CREATE, this::createRecord);
+        addDispatcher(ACTION_MODIFY, this::modifyRecord);
+        addDispatcher(ACTION_DELETE, this::deleteRecord);
+        addDispatcher(ACTION_UPDATE, this::updateRecord);
+    }
+
+    /*
+     * GET
+     * https://instance.service-now.com/api/now/table/{tableName}
+     * https://instance.service-now.com/api/now/table/{tableName}/{sys_id}
+     */
+    private void retrieveRecord(Exchange exchange) throws Exception {
+        final Message in = exchange.getIn();
+        final String tableName = getTableName(in);
+        final String apiVersion = getApiVersion(in);
+        final Class<?> responseModel = getResponseModel(in, tableName);
+        final String sysId = getSysID(in);
+
+        Response response = ObjectHelper.isEmpty(sysId)
+            ? client.reset()
+                .types(MediaType.APPLICATION_JSON_TYPE)
+                .path("now")
+                .path(apiVersion)
+                .path("table")
+                .path(tableName)
+                .query(ServiceNowParams.SYSPARM_QUERY, in)
+                .query(ServiceNowParams.SYSPARM_DISPLAY_VALUE, in)
+                .query(ServiceNowParams.SYSPARM_EXCLUDE_REFERENCE_LINK, in)
+                .query(ServiceNowParams.SYSPARM_SUPPRESS_PAGINATION_HEADER, in)
+                .query(ServiceNowParams.SYSPARM_FIELDS, in)
+                .query(ServiceNowParams.SYSPARM_LIMIT, in)
+                .query(ServiceNowParams.SYSPARM_OFFSET, in)
+                .query(ServiceNowParams.SYSPARM_VIEW, in)
+                .query(responseModel)
+                .invoke(HttpMethod.GET)
+            : client.reset()
+                .types(MediaType.APPLICATION_JSON_TYPE)
+                .path("now")
+                .path(apiVersion)
+                .path("table")
+                .path(tableName)
+                .path(sysId)
+                .query(ServiceNowParams.SYSPARM_DISPLAY_VALUE, in)
+                .query(ServiceNowParams.SYSPARM_EXCLUDE_REFERENCE_LINK, in)
+                .query(ServiceNowParams.SYSPARM_FIELDS, in)
+                .query(ServiceNowParams.SYSPARM_VIEW, in)
+                .query(responseModel)
+                .invoke(HttpMethod.GET);
+
+        setBodyAndHeaders(exchange.getIn(), responseModel, response);
+    }
+
+    /*
+     * POST
+     * https://instance.service-now.com/api/now/table/{tableName}
+     */
+    private void createRecord(Exchange exchange) throws Exception {
+        final Message in = exchange.getIn();
+        final String tableName = getTableName(in);
+        final String apiVersion = getApiVersion(in);
+        final Class<?> requestModel = getRequestModel(in, tableName);
+        final Class<?> responseModel = getResponseModel(in, tableName);
+        final String sysId = getSysID(in);
+
+        validateBody(in, requestModel);
+
+        Response response = client.reset()
+            .types(MediaType.APPLICATION_JSON_TYPE)
+            .path("now")
+            .path(apiVersion)
+            .path("table")
+            .path(tableName)
+            .query(ServiceNowParams.SYSPARM_DISPLAY_VALUE, in)
+            .query(ServiceNowParams.SYSPARM_EXCLUDE_REFERENCE_LINK, in)
+            .query(ServiceNowParams.SYSPARM_FIELDS, in)
+            .query(ServiceNowParams.SYSPARM_INPUT_DISPLAY_VALUE, in)
+            .query(ServiceNowParams.SYSPARM_SUPPRESS_AUTO_SYS_FIELD, in)
+            .query(ServiceNowParams.SYSPARM_VIEW, in)
+            .query(responseModel)
+            .invoke(HttpMethod.POST, in.getMandatoryBody());
+
+        setBodyAndHeaders(exchange.getIn(), responseModel, response);
+    }
+
+    /*
+     * PUT
+     * https://instance.service-now.com/api/now/table/{tableName}/{sys_id}
+     */
+    private void modifyRecord(Exchange exchange) throws Exception {
+        final Message in = exchange.getIn();
+        final String tableName = getTableName(in);
+        final String apiVersion = getApiVersion(in);
+        final Class<?> requestModel = getRequestModel(in, tableName);
+        final Class<?> responseModel = getResponseModel(in, tableName);
+        final String sysId = getSysID(in);
+
+        validateBody(in, requestModel);
+
+        Response response = client.reset()
+            .types(MediaType.APPLICATION_JSON_TYPE)
+            .path("now")
+            .path(apiVersion)
+            .path("table")
+            .path(tableName)
+            .path(ObjectHelper.notNull(sysId, "sysId"))
+            .query(ServiceNowParams.SYSPARM_DISPLAY_VALUE, in)
+            .query(ServiceNowParams.SYSPARM_EXCLUDE_REFERENCE_LINK, in)
+            .query(ServiceNowParams.SYSPARM_FIELDS, in)
+            .query(ServiceNowParams.SYSPARM_INPUT_DISPLAY_VALUE, in)
+            .query(ServiceNowParams.SYSPARM_SUPPRESS_AUTO_SYS_FIELD, in)
+            .query(ServiceNowParams.SYSPARM_VIEW, in)
+            .query(responseModel)
+            .invoke(HttpMethod.PUT, in.getMandatoryBody());
+
+        setBodyAndHeaders(exchange.getIn(), responseModel, response);
+    }
+
+    /*
+     * DELETE
+     * https://instance.service-now.com/api/now/table/{tableName}/{sys_id}
+     */
+    private void deleteRecord(Exchange exchange) throws Exception {
+        final Message in = exchange.getIn();
+        final String tableName = getTableName(in);
+        final String apiVersion = getApiVersion(in);
+        final Class<?> responseModel = getResponseModel(in, tableName);
+        final String sysId = getSysID(in);
+
+        Response response = client.reset()
+            .types(MediaType.APPLICATION_JSON_TYPE)
+            .path("now")
+            .path(apiVersion)
+            .path("table")
+            .path(tableName)
+            .path(ObjectHelper.notNull(sysId, "sysId"))
+            .query(responseModel)
+            .invoke(HttpMethod.DELETE, null);
+
+        setBodyAndHeaders(exchange.getIn(), responseModel, response);
+    }
+
+    /*
+     * PATCH
+     * instance://instance.service-now.com/api/now/table/{tableName}/{sys_id}
+     */
+    private void updateRecord(Exchange exchange) throws Exception {
+        final Message in = exchange.getIn();
+        final String tableName = getTableName(in);
+        final String apiVersion = getApiVersion(in);
+        final Class<?> requestModel = getRequestModel(in, tableName);
+        final Class<?> responseModel = getResponseModel(in, tableName);
+        final String sysId = getSysID(in);
+
+        validateBody(in, requestModel);
+
+        Response response = client.reset()
+            .types(MediaType.APPLICATION_JSON_TYPE)
+            .path("now")
+            .path(apiVersion)
+            .path("table")
+            .path(tableName)
+            .path(ObjectHelper.notNull(sysId, "sysId"))
+            .query(ServiceNowParams.SYSPARM_DISPLAY_VALUE, in)
+            .query(ServiceNowParams.SYSPARM_EXCLUDE_REFERENCE_LINK, in)
+            .query(ServiceNowParams.SYSPARM_FIELDS, in)
+            .query(ServiceNowParams.SYSPARM_INPUT_DISPLAY_VALUE, in)
+            .query(ServiceNowParams.SYSPARM_SUPPRESS_AUTO_SYS_FIELD, in)
+            .query(ServiceNowParams.SYSPARM_VIEW, in)
+            .query(responseModel)
+            .invoke("PATCH", in.getMandatoryBody());
+
+        setBodyAndHeaders(exchange.getIn(), responseModel, response);
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/109da7c9/components/camel-servicenow/camel-servicenow-component/src/main/resources/META-INF/LICENSE.txt
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/camel-servicenow-component/src/main/resources/META-INF/LICENSE.txt b/components/camel-servicenow/camel-servicenow-component/src/main/resources/META-INF/LICENSE.txt
new file mode 100644
index 0000000..6b0b127
--- /dev/null
+++ b/components/camel-servicenow/camel-servicenow-component/src/main/resources/META-INF/LICENSE.txt
@@ -0,0 +1,203 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed 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.
+

http://git-wip-us.apache.org/repos/asf/camel/blob/109da7c9/components/camel-servicenow/camel-servicenow-component/src/main/resources/META-INF/NOTICE.txt
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/camel-servicenow-component/src/main/resources/META-INF/NOTICE.txt b/components/camel-servicenow/camel-servicenow-component/src/main/resources/META-INF/NOTICE.txt
new file mode 100644
index 0000000..2e215bf
--- /dev/null
+++ b/components/camel-servicenow/camel-servicenow-component/src/main/resources/META-INF/NOTICE.txt
@@ -0,0 +1,11 @@
+   =========================================================================
+   ==  NOTICE file corresponding to the section 4 d of                    ==
+   ==  the Apache License, Version 2.0,                                   ==
+   ==  in this case for the Apache Camel distribution.                    ==
+   =========================================================================
+
+   This product includes software developed by
+   The Apache Software Foundation (http://www.apache.org/).
+
+   Please read the different LICENSE files present in the licenses directory of
+   this distribution.

http://git-wip-us.apache.org/repos/asf/camel/blob/109da7c9/components/camel-servicenow/camel-servicenow-component/src/main/resources/META-INF/services/org/apache/camel/component/servicenow
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/camel-servicenow-component/src/main/resources/META-INF/services/org/apache/camel/component/servicenow b/components/camel-servicenow/camel-servicenow-component/src/main/resources/META-INF/services/org/apache/camel/component/servicenow
new file mode 100644
index 0000000..38858aa
--- /dev/null
+++ b/components/camel-servicenow/camel-servicenow-component/src/main/resources/META-INF/services/org/apache/camel/component/servicenow
@@ -0,0 +1,18 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+class=org.apache.camel.component.servicenow.ServiceNowComponent

http://git-wip-us.apache.org/repos/asf/camel/blob/109da7c9/components/camel-servicenow/camel-servicenow-component/src/test/java/org/apache/camel/component/servicenow/ServiceNowAttachmentTest.java
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/camel-servicenow-component/src/test/java/org/apache/camel/component/servicenow/ServiceNowAttachmentTest.java b/components/camel-servicenow/camel-servicenow-component/src/test/java/org/apache/camel/component/servicenow/ServiceNowAttachmentTest.java
new file mode 100644
index 0000000..18772d2
--- /dev/null
+++ b/components/camel-servicenow/camel-servicenow-component/src/test/java/org/apache/camel/component/servicenow/ServiceNowAttachmentTest.java
@@ -0,0 +1,129 @@
+/**
+ * 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.servicenow;
+
+import java.io.InputStream;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+
+import org.apache.camel.Exchange;
+import org.apache.camel.Produce;
+import org.apache.camel.ProducerTemplate;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.servicenow.model.AttachmentMeta;
+import org.junit.Test;
+
+import static org.apache.camel.util.ResourceHelper.resolveResourceAsInputStream;
+
+public class ServiceNowAttachmentTest extends ServiceNowTestSupport {
+    @Produce(uri = "direct:servicenow")
+    ProducerTemplate template;
+
+    @Test
+    public void testAttachment() throws Exception {
+        List<AttachmentMeta> attachmentMetaList = template.requestBodyAndHeaders(
+            "direct:servicenow",
+            null,
+            kvBuilder()
+                .put(ServiceNowConstants.RESOURCE, ServiceNowConstants.RESOURCE_ATTACHMENT)
+                .put(ServiceNowConstants.ACTION, ServiceNowConstants.ACTION_RETRIEVE)
+                .put(ServiceNowConstants.MODEL, AttachmentMeta.class)
+                .put(ServiceNowParams.SYSPARM_QUERY, "content_type=application/octet-stream")
+                .put(ServiceNowParams.SYSPARM_LIMIT, 1)
+                .build(),
+            List.class
+        );
+
+        assertFalse(attachmentMetaList.isEmpty());
+
+        Exchange getExistingResult = template.send(
+            "direct:servicenow",
+            e -> {
+                e.getIn().setHeader(ServiceNowConstants.RESOURCE, ServiceNowConstants.RESOURCE_ATTACHMENT);
+                e.getIn().setHeader(ServiceNowConstants.ACTION, ServiceNowConstants.ACTION_CONTENT);
+                e.getIn().setHeader(ServiceNowParams.PARAM_SYS_ID.getHeader(), attachmentMetaList.get(0).getId());
+            }
+        );
+
+        assertNotNull(getExistingResult.getIn().getHeader(ServiceNowConstants.CONTENT_META));
+        assertNotNull(getExistingResult.getIn().getBody());
+        assertTrue(getExistingResult.getIn().getBody() instanceof InputStream);
+
+        Map<String, String> contentMeta = getExistingResult.getIn().getHeader(ServiceNowConstants.CONTENT_META, Map.class);
+        assertEquals(contentMeta.get("file_name"), attachmentMetaList.get(0).getFileName());
+        assertEquals(contentMeta.get("table_name"), attachmentMetaList.get(0).getTableName());
+        assertEquals(contentMeta.get("sys_id"), attachmentMetaList.get(0).getId());
+
+        Exchange putResult = template.send(
+            "direct:servicenow",
+            e -> {
+                e.getIn().setHeader(ServiceNowConstants.RESOURCE, ServiceNowConstants.RESOURCE_ATTACHMENT);
+                e.getIn().setHeader(ServiceNowConstants.ACTION, ServiceNowConstants.ACTION_UPLOAD);
+                e.getIn().setHeader(ServiceNowConstants.MODEL, AttachmentMeta.class);
+                e.getIn().setHeader(ServiceNowConstants.CONTENT_TYPE, "application/octet-stream");
+                e.getIn().setHeader(ServiceNowParams.PARAM_FILE_NAME.getHeader(), UUID.randomUUID().toString());
+                e.getIn().setHeader(ServiceNowParams.PARAM_TABLE_NAME.getHeader(), attachmentMetaList.get(0).getTableName());
+                e.getIn().setHeader(ServiceNowParams.PARAM_TABLE_SYS_ID.getHeader(), attachmentMetaList.get(0).getTableSysId());
+                e.getIn().setBody(resolveResourceAsInputStream(e.getContext().getClassResolver(), "classpath:my-content.txt"));
+            }
+        );
+
+        Exchange getCreatedResult = template.send(
+            "direct:servicenow",
+            e -> {
+                e.getIn().setHeader(ServiceNowConstants.RESOURCE, ServiceNowConstants.RESOURCE_ATTACHMENT);
+                e.getIn().setHeader(ServiceNowConstants.ACTION, ServiceNowConstants.ACTION_CONTENT);
+                e.getIn().setHeader(ServiceNowParams.PARAM_SYS_ID.getHeader(), putResult.getIn().getBody(AttachmentMeta.class).getId());
+            }
+        );
+
+        assertNotNull(getCreatedResult.getIn().getHeader(ServiceNowConstants.CONTENT_META));
+        assertNotNull(getCreatedResult.getIn().getBody());
+        assertTrue(getCreatedResult.getIn().getBody() instanceof InputStream);
+
+        Exchange deleteResult = template.send(
+            "direct:servicenow",
+            e -> {
+                e.getIn().setHeader(ServiceNowConstants.RESOURCE, ServiceNowConstants.RESOURCE_ATTACHMENT);
+                e.getIn().setHeader(ServiceNowConstants.ACTION, ServiceNowConstants.ACTION_DELETE);
+                e.getIn().setHeader(ServiceNowParams.PARAM_SYS_ID.getHeader(), putResult.getIn().getBody(AttachmentMeta.class).getId());
+            }
+        );
+
+        if (deleteResult.getException() != null) {
+            throw deleteResult.getException();
+        }
+    }
+
+    // *************************************************************************
+    //
+    // *************************************************************************
+
+    @Override
+    protected RouteBuilder createRouteBuilder() throws Exception {
+        return new RouteBuilder() {
+            public void configure() {
+                from("direct:servicenow")
+                    .to("servicenow:{{env:SERVICENOW_INSTANCE}}")
+                    .to("log:org.apache.camel.component.servicenow?level=INFO&showAll=true")
+                    .to("mock:servicenow");
+            }
+        };
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/109da7c9/components/camel-servicenow/camel-servicenow-component/src/test/java/org/apache/camel/component/servicenow/ServiceNowBlueprintComponentAuthTest.java
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/camel-servicenow-component/src/test/java/org/apache/camel/component/servicenow/ServiceNowBlueprintComponentAuthTest.java b/components/camel-servicenow/camel-servicenow-component/src/test/java/org/apache/camel/component/servicenow/ServiceNowBlueprintComponentAuthTest.java
new file mode 100644
index 0000000..c3b524a
--- /dev/null
+++ b/components/camel-servicenow/camel-servicenow-component/src/test/java/org/apache/camel/component/servicenow/ServiceNowBlueprintComponentAuthTest.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.component.servicenow;
+
+import java.util.List;
+
+import org.apache.camel.Exchange;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.component.servicenow.model.Incident;
+import org.apache.camel.test.blueprint.CamelBlueprintTestSupport;
+import org.junit.Test;
+
+public class ServiceNowBlueprintComponentAuthTest extends CamelBlueprintTestSupport {
+    @Override
+    protected String getBlueprintDescriptor() {
+        return "OSGI-INF/blueprint/blueprint-component-auth.xml";
+    }
+
+    @Test
+    public void testAuth() throws Exception {
+        MockEndpoint mock1 = getMockEndpoint("mock:servicenow-1");
+        mock1.expectedMessageCount(1);
+        MockEndpoint mock2 = getMockEndpoint("mock:servicenow-2");
+        mock2.expectedMessageCount(1);
+
+        template().sendBodyAndHeaders(
+            "direct:servicenow",
+            null,
+            ServiceNowTestSupport.kvBuilder()
+                .put(ServiceNowConstants.RESOURCE, "table")
+                .put(ServiceNowConstants.ACTION, ServiceNowConstants.ACTION_RETRIEVE)
+                .put(ServiceNowParams.SYSPARM_LIMIT, 10)
+                .put(ServiceNowParams.PARAM_TABLE_NAME, "incident")
+                .build()
+        );
+
+        mock1.assertIsSatisfied();
+        mock2.assertIsSatisfied();
+
+        validate(mock1.getExchanges().get(0));
+        validate(mock2.getExchanges().get(0));
+    }
+
+    private void validate(Exchange exchange) {
+        List<Incident> items = exchange.getIn().getBody(List.class);
+
+        assertNotNull(items);
+        assertTrue(items.size() <= 10);
+        assertNotNull(exchange.getIn().getHeader(ServiceNowConstants.OFFSET_FIRST));
+        assertNotNull(exchange.getIn().getHeader(ServiceNowConstants.OFFSET_NEXT));
+        assertNotNull(exchange.getIn().getHeader(ServiceNowConstants.OFFSET_LAST));
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/109da7c9/components/camel-servicenow/camel-servicenow-component/src/test/java/org/apache/camel/component/servicenow/ServiceNowBlueprintEndpointAuthTest.java
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/camel-servicenow-component/src/test/java/org/apache/camel/component/servicenow/ServiceNowBlueprintEndpointAuthTest.java b/components/camel-servicenow/camel-servicenow-component/src/test/java/org/apache/camel/component/servicenow/ServiceNowBlueprintEndpointAuthTest.java
new file mode 100644
index 0000000..581404c
--- /dev/null
+++ b/components/camel-servicenow/camel-servicenow-component/src/test/java/org/apache/camel/component/servicenow/ServiceNowBlueprintEndpointAuthTest.java
@@ -0,0 +1,61 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.camel.component.servicenow;
+
+import java.util.List;
+
+import org.apache.camel.Exchange;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.component.servicenow.model.Incident;
+import org.apache.camel.test.blueprint.CamelBlueprintTestSupport;
+import org.junit.Test;
+
+public class ServiceNowBlueprintEndpointAuthTest extends CamelBlueprintTestSupport {
+    @Override
+    protected String getBlueprintDescriptor() {
+        return "OSGI-INF/blueprint/blueprint-endpoint-auth.xml";
+    }
+
+    @Test
+    public void testAuth() throws Exception {
+        MockEndpoint mock = getMockEndpoint("mock:servicenow");
+        mock.expectedMessageCount(1);
+
+        template().sendBodyAndHeaders(
+            "direct:servicenow",
+            null,
+            ServiceNowTestSupport.kvBuilder()
+                .put(ServiceNowConstants.RESOURCE, "table")
+                .put(ServiceNowConstants.ACTION, ServiceNowConstants.ACTION_RETRIEVE)
+                .put(ServiceNowParams.SYSPARM_LIMIT, 10)
+                .put(ServiceNowParams.PARAM_TABLE_NAME, "incident")
+                .build()
+        );
+
+        mock.assertIsSatisfied();
+
+        Exchange exchange = mock.getExchanges().get(0);
+        List<Incident> items = exchange.getIn().getBody(List.class);
+
+        assertNotNull(items);
+        assertTrue(items.size() <= 10);
+        assertNotNull(exchange.getIn().getHeader(ServiceNowConstants.OFFSET_FIRST));
+        assertNotNull(exchange.getIn().getHeader(ServiceNowConstants.OFFSET_NEXT));
+        assertNotNull(exchange.getIn().getHeader(ServiceNowConstants.OFFSET_LAST));
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/109da7c9/components/camel-servicenow/camel-servicenow-component/src/test/java/org/apache/camel/component/servicenow/ServiceNowComponentVerifierExtensionTest.java
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/camel-servicenow-component/src/test/java/org/apache/camel/component/servicenow/ServiceNowComponentVerifierExtensionTest.java b/components/camel-servicenow/camel-servicenow-component/src/test/java/org/apache/camel/component/servicenow/ServiceNowComponentVerifierExtensionTest.java
new file mode 100644
index 0000000..a06d503
--- /dev/null
+++ b/components/camel-servicenow/camel-servicenow-component/src/test/java/org/apache/camel/component/servicenow/ServiceNowComponentVerifierExtensionTest.java
@@ -0,0 +1,151 @@
+/**
+ * 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.servicenow;
+
+import java.util.Map;
+import javax.ws.rs.ProcessingException;
+
+import org.apache.camel.Component;
+import org.apache.camel.component.extension.ComponentVerifierExtension;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class ServiceNowComponentVerifierExtensionTest extends ServiceNowTestSupport {
+    public ServiceNowComponentVerifierExtensionTest() {
+        super(false);
+    }
+
+    @Override
+    public boolean isUseRouteBuilder() {
+        return false;
+    }
+
+    protected ComponentVerifierExtension getExtension() {
+        Component component = context().getComponent("servicenow");
+        ComponentVerifierExtension verifier = component.getExtension(ComponentVerifierExtension.class).orElseThrow(IllegalStateException::new);
+
+        return verifier;
+    }
+
+    // *********************************
+    // Parameters validation
+    // *********************************
+
+    @Test
+    public void testParameter() {
+        Map<String, Object> parameters = getParameters();
+        ComponentVerifierExtension.Result result = getExtension().verify(ComponentVerifierExtension.Scope.PARAMETERS, parameters);
+
+        Assert.assertEquals(ComponentVerifierExtension.Result.Status.OK, result.getStatus());
+    }
+
+    @Test
+    public void testMissingMandatoryParameter() {
+        Map<String, Object> parameters = getParameters();
+        parameters.remove("instanceName");
+        ComponentVerifierExtension.Result result = getExtension().verify(ComponentVerifierExtension.Scope.PARAMETERS, parameters);
+
+        Assert.assertEquals(ComponentVerifierExtension.Result.Status.ERROR, result.getStatus());
+        Assert.assertEquals(1, result.getErrors().size());
+        Assert.assertEquals(ComponentVerifierExtension.VerificationError.StandardCode.MISSING_PARAMETER, result.getErrors().get(0).getCode());
+        Assert.assertEquals("instanceName", result.getErrors().get(0).getParameterKeys().iterator().next());
+    }
+
+    @Test
+    public void testMissingMandatoryAuthenticationParameter() {
+        Map<String, Object> parameters = getParameters();
+        parameters.remove("userName");
+        ComponentVerifierExtension.Result result = getExtension().verify(ComponentVerifierExtension.Scope.PARAMETERS, parameters);
+
+        Assert.assertEquals(ComponentVerifierExtension.Result.Status.ERROR, result.getStatus());
+        Assert.assertEquals(1, result.getErrors().size());
+        Assert.assertEquals(ComponentVerifierExtension.VerificationError.StandardCode.MISSING_PARAMETER, result.getErrors().get(0).getCode());
+        Assert.assertEquals("userName", result.getErrors().get(0).getParameterKeys().iterator().next());
+    }
+
+    // *********************************
+    // Connectivity validation
+    // *********************************
+
+    @Test
+    public void testConnectivity() {
+        Map<String, Object> parameters = getParameters();
+        ComponentVerifierExtension.Result result = getExtension().verify(ComponentVerifierExtension.Scope.CONNECTIVITY, parameters);
+
+        Assert.assertEquals(ComponentVerifierExtension.Result.Status.OK, result.getStatus());
+    }
+
+    @Test
+    public void testConnectivityOnCustomTable() {
+        Map<String, Object> parameters = getParameters();
+        parameters.put("table", "ticket");
+
+        ComponentVerifierExtension.Result result = getExtension().verify(ComponentVerifierExtension.Scope.CONNECTIVITY, parameters);
+
+        Assert.assertEquals(ComponentVerifierExtension.Result.Status.OK, result.getStatus());
+    }
+
+    @Test
+    public void testConnectivityWithWrongInstance() {
+        Map<String, Object> parameters = getParameters();
+        parameters.put("instanceName", "unknown-instance");
+
+        ComponentVerifierExtension.Result result = getExtension().verify(ComponentVerifierExtension.Scope.CONNECTIVITY, parameters);
+
+        Assert.assertEquals(ComponentVerifierExtension.Result.Status.ERROR, result.getStatus());
+        Assert.assertEquals(1, result.getErrors().size());
+        Assert.assertEquals(ComponentVerifierExtension.VerificationError.StandardCode.EXCEPTION, result.getErrors().get(0).getCode());
+        Assert.assertNotNull(result.getErrors().get(0).getDetails().get(ComponentVerifierExtension.VerificationError.ExceptionAttribute.EXCEPTION_INSTANCE));
+        Assert.assertTrue(result.getErrors().get(0).getDetails().get(ComponentVerifierExtension.VerificationError.ExceptionAttribute.EXCEPTION_INSTANCE) instanceof ProcessingException);
+    }
+
+    @Test
+    public void testConnectivityWithWrongTable() {
+        Map<String, Object> parameters = getParameters();
+        parameters.put("table", "unknown");
+
+        ComponentVerifierExtension.Result result = getExtension().verify(ComponentVerifierExtension.Scope.CONNECTIVITY, parameters);
+
+        Assert.assertEquals(ComponentVerifierExtension.Result.Status.ERROR, result.getStatus());
+        Assert.assertEquals(1, result.getErrors().size());
+        Assert.assertEquals(ComponentVerifierExtension.VerificationError.StandardCode.EXCEPTION, result.getErrors().get(0).getCode());
+        Assert.assertNotNull(result.getErrors().get(0).getDetails().get(ComponentVerifierExtension.VerificationError.ExceptionAttribute.EXCEPTION_INSTANCE));
+        Assert.assertEquals(400, result.getErrors().get(0).getDetails().get(ComponentVerifierExtension.VerificationError.HttpAttribute.HTTP_CODE));
+        Assert.assertTrue(result.getErrors().get(0).getDetails().get(ComponentVerifierExtension.VerificationError.ExceptionAttribute.EXCEPTION_INSTANCE) instanceof ServiceNowException);
+    }
+
+    @Test
+    public void testConnectivityWithWrongAuthentication() {
+        Map<String, Object> parameters = getParameters();
+        parameters.put("userName", "unknown-user");
+        parameters.remove("oauthClientId");
+        parameters.remove("oauthClientSecret");
+
+        ComponentVerifierExtension.Result result = getExtension().verify(ComponentVerifierExtension.Scope.CONNECTIVITY, parameters);
+
+        Assert.assertEquals(ComponentVerifierExtension.Result.Status.ERROR, result.getStatus());
+        Assert.assertEquals(1, result.getErrors().size());
+        Assert.assertEquals(ComponentVerifierExtension.VerificationError.StandardCode.AUTHENTICATION, result.getErrors().get(0).getCode());
+        Assert.assertNotNull(result.getErrors().get(0).getDetails().get(ComponentVerifierExtension.VerificationError.ExceptionAttribute.EXCEPTION_INSTANCE));
+        Assert.assertEquals(401, result.getErrors().get(0).getDetails().get(ComponentVerifierExtension.VerificationError.HttpAttribute.HTTP_CODE));
+        Assert.assertTrue(result.getErrors().get(0).getDetails().get(ComponentVerifierExtension.VerificationError.ExceptionAttribute.EXCEPTION_INSTANCE) instanceof ServiceNowException);
+        Assert.assertTrue(result.getErrors().get(0).getParameterKeys().contains("userName"));
+        Assert.assertTrue(result.getErrors().get(0).getParameterKeys().contains("password"));
+        Assert.assertTrue(result.getErrors().get(0).getParameterKeys().contains("oauthClientId"));
+        Assert.assertTrue(result.getErrors().get(0).getParameterKeys().contains("oauthClientSecret"));
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/109da7c9/components/camel-servicenow/camel-servicenow-component/src/test/java/org/apache/camel/component/servicenow/ServiceNowComponentVerifierTest.java
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/camel-servicenow-component/src/test/java/org/apache/camel/component/servicenow/ServiceNowComponentVerifierTest.java b/components/camel-servicenow/camel-servicenow-component/src/test/java/org/apache/camel/component/servicenow/ServiceNowComponentVerifierTest.java
new file mode 100644
index 0000000..120346a
--- /dev/null
+++ b/components/camel-servicenow/camel-servicenow-component/src/test/java/org/apache/camel/component/servicenow/ServiceNowComponentVerifierTest.java
@@ -0,0 +1,147 @@
+/**
+ * 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.servicenow;
+
+import java.util.Map;
+import javax.ws.rs.ProcessingException;
+
+import org.apache.camel.ComponentVerifier;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class ServiceNowComponentVerifierTest extends ServiceNowTestSupport {
+    public ServiceNowComponentVerifierTest() {
+        super(false);
+    }
+
+    @Override
+    public boolean isUseRouteBuilder() {
+        return false;
+    }
+
+    protected ComponentVerifier getVerifier() {
+        return context().getComponent("servicenow", ServiceNowComponent.class).getVerifier();
+    }
+
+    // *********************************
+    // Parameters validation
+    // *********************************
+
+    @Test
+    public void testParameter() {
+        Map<String, Object> parameters = getParameters();
+        ComponentVerifier.Result result = getVerifier().verify(ComponentVerifier.Scope.PARAMETERS, parameters);
+
+        Assert.assertEquals(ComponentVerifier.Result.Status.OK, result.getStatus());
+    }
+
+    @Test
+    public void testMissingMandatoryParameter() {
+        Map<String, Object> parameters = getParameters();
+        parameters.remove("instanceName");
+        ComponentVerifier.Result result = getVerifier().verify(ComponentVerifier.Scope.PARAMETERS, parameters);
+
+        Assert.assertEquals(ComponentVerifier.Result.Status.ERROR, result.getStatus());
+        Assert.assertEquals(1, result.getErrors().size());
+        Assert.assertEquals(ComponentVerifier.VerificationError.StandardCode.MISSING_PARAMETER, result.getErrors().get(0).getCode());
+        Assert.assertEquals("instanceName", result.getErrors().get(0).getParameterKeys().iterator().next());
+    }
+
+    @Test
+    public void testMissingMandatoryAuthenticationParameter() {
+        Map<String, Object> parameters = getParameters();
+        parameters.remove("userName");
+        ComponentVerifier.Result result = getVerifier().verify(ComponentVerifier.Scope.PARAMETERS, parameters);
+
+        Assert.assertEquals(ComponentVerifier.Result.Status.ERROR, result.getStatus());
+        Assert.assertEquals(1, result.getErrors().size());
+        Assert.assertEquals(ComponentVerifier.VerificationError.StandardCode.MISSING_PARAMETER, result.getErrors().get(0).getCode());
+        Assert.assertEquals("userName", result.getErrors().get(0).getParameterKeys().iterator().next());
+    }
+
+    // *********************************
+    // Connectivity validation
+    // *********************************
+
+    @Test
+    public void testConnectivity() {
+        Map<String, Object> parameters = getParameters();
+        ComponentVerifier.Result result = getVerifier().verify(ComponentVerifier.Scope.CONNECTIVITY, parameters);
+
+        Assert.assertEquals(ComponentVerifier.Result.Status.OK, result.getStatus());
+    }
+
+    @Test
+    public void testConnectivityOnCustomTable() {
+        Map<String, Object> parameters = getParameters();
+        parameters.put("table", "ticket");
+
+        ComponentVerifier.Result result = getVerifier().verify(ComponentVerifier.Scope.CONNECTIVITY, parameters);
+
+        Assert.assertEquals(ComponentVerifier.Result.Status.OK, result.getStatus());
+    }
+
+    @Test
+    public void testConnectivityWithWrongInstance() {
+        Map<String, Object> parameters = getParameters();
+        parameters.put("instanceName", "unknown-instance");
+
+        ComponentVerifier.Result result = getVerifier().verify(ComponentVerifier.Scope.CONNECTIVITY, parameters);
+
+        Assert.assertEquals(ComponentVerifier.Result.Status.ERROR, result.getStatus());
+        Assert.assertEquals(1, result.getErrors().size());
+        Assert.assertEquals(ComponentVerifier.VerificationError.StandardCode.EXCEPTION, result.getErrors().get(0).getCode());
+        Assert.assertNotNull(result.getErrors().get(0).getDetails().get(ComponentVerifier.VerificationError.ExceptionAttribute.EXCEPTION_INSTANCE));
+        Assert.assertTrue(result.getErrors().get(0).getDetails().get(ComponentVerifier.VerificationError.ExceptionAttribute.EXCEPTION_INSTANCE) instanceof ProcessingException);
+    }
+
+    @Test
+    public void testConnectivityWithWrongTable() {
+        Map<String, Object> parameters = getParameters();
+        parameters.put("table", "unknown");
+
+        ComponentVerifier.Result result = getVerifier().verify(ComponentVerifier.Scope.CONNECTIVITY, parameters);
+
+        Assert.assertEquals(ComponentVerifier.Result.Status.ERROR, result.getStatus());
+        Assert.assertEquals(1, result.getErrors().size());
+        Assert.assertEquals(ComponentVerifier.VerificationError.StandardCode.EXCEPTION, result.getErrors().get(0).getCode());
+        Assert.assertNotNull(result.getErrors().get(0).getDetails().get(ComponentVerifier.VerificationError.ExceptionAttribute.EXCEPTION_INSTANCE));
+        Assert.assertEquals(400, result.getErrors().get(0).getDetails().get(ComponentVerifier.VerificationError.HttpAttribute.HTTP_CODE));
+        Assert.assertTrue(result.getErrors().get(0).getDetails().get(ComponentVerifier.VerificationError.ExceptionAttribute.EXCEPTION_INSTANCE) instanceof ServiceNowException);
+    }
+
+    @Test
+    public void testConnectivityWithWrongAuthentication() {
+        Map<String, Object> parameters = getParameters();
+        parameters.put("userName", "unknown-user");
+        parameters.remove("oauthClientId");
+        parameters.remove("oauthClientSecret");
+
+        ComponentVerifier.Result result = getVerifier().verify(ComponentVerifier.Scope.CONNECTIVITY, parameters);
+
+        Assert.assertEquals(ComponentVerifier.Result.Status.ERROR, result.getStatus());
+        Assert.assertEquals(1, result.getErrors().size());
+        Assert.assertEquals(ComponentVerifier.VerificationError.StandardCode.AUTHENTICATION, result.getErrors().get(0).getCode());
+        Assert.assertNotNull(result.getErrors().get(0).getDetails().get(ComponentVerifier.VerificationError.ExceptionAttribute.EXCEPTION_INSTANCE));
+        Assert.assertEquals(401, result.getErrors().get(0).getDetails().get(ComponentVerifier.VerificationError.HttpAttribute.HTTP_CODE));
+        Assert.assertTrue(result.getErrors().get(0).getDetails().get(ComponentVerifier.VerificationError.ExceptionAttribute.EXCEPTION_INSTANCE) instanceof ServiceNowException);
+        Assert.assertTrue(result.getErrors().get(0).getParameterKeys().contains("userName"));
+        Assert.assertTrue(result.getErrors().get(0).getParameterKeys().contains("password"));
+        Assert.assertTrue(result.getErrors().get(0).getParameterKeys().contains("oauthClientId"));
+        Assert.assertTrue(result.getErrors().get(0).getParameterKeys().contains("oauthClientSecret"));
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/109da7c9/components/camel-servicenow/camel-servicenow-component/src/test/java/org/apache/camel/component/servicenow/ServiceNowImportSetTest.java
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/camel-servicenow-component/src/test/java/org/apache/camel/component/servicenow/ServiceNowImportSetTest.java b/components/camel-servicenow/camel-servicenow-component/src/test/java/org/apache/camel/component/servicenow/ServiceNowImportSetTest.java
new file mode 100644
index 0000000..dd524bc
--- /dev/null
+++ b/components/camel-servicenow/camel-servicenow-component/src/test/java/org/apache/camel/component/servicenow/ServiceNowImportSetTest.java
@@ -0,0 +1,147 @@
+/**
+ * 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.servicenow;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import org.apache.camel.Message;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.component.servicenow.model.ImportSetResult;
+import org.apache.camel.component.servicenow.model.Incident;
+import org.junit.Ignore;
+import org.junit.Test;
+
+/**
+ * To set-up ServiceNow for this tests:
+ *
+ * 1. Create a new web service named u_test_imp_incident targeting incident table
+ * 2. Create a mapping (automatic)
+ */
+@Ignore
+public class ServiceNowImportSetTest extends ServiceNowTestSupport {
+
+    @Test
+    public void testIncidentImport() throws Exception {
+        MockEndpoint mock = getMockEndpoint("mock:servicenow");
+
+        mock.reset();
+        mock.expectedMessageCount(1);
+        mock.expectedHeaderReceived(ServiceNowConstants.RESPONSE_TYPE, ArrayList.class);
+
+        IncidentImportRequest incident = new IncidentImportRequest();
+        incident.description = UUID.randomUUID().toString();
+        incident.correlationId = UUID.randomUUID().toString();
+
+        template().sendBodyAndHeaders(
+            "direct:servicenow",
+            incident,
+            kvBuilder()
+                .put(ServiceNowConstants.RESOURCE, ServiceNowConstants.RESOURCE_IMPORT)
+                .put(ServiceNowConstants.ACTION, ServiceNowConstants.ACTION_CREATE)
+                .put(ServiceNowConstants.REQUEST_MODEL, IncidentImportRequest.class)
+                .put(ServiceNowConstants.RESPONSE_MODEL, ImportSetResult.class)
+                .put(ServiceNowParams.PARAM_TABLE_NAME, "u_test_imp_incident")
+                .build()
+        );
+
+        mock.assertIsSatisfied();
+
+        Message in =  mock.getExchanges().get(0).getIn();
+
+        // Meta data
+        Map<String, String> meta = in.getHeader(ServiceNowConstants.RESPONSE_META, Map.class);
+        assertNotNull(meta);
+        assertEquals("u_test_imp_incident", meta.get("staging_table"));
+
+        // Incidents
+        List<ImportSetResult> responses = in.getBody(List.class);
+        assertNotNull(responses);
+        assertEquals(1, responses.size());
+        assertEquals("inserted", responses.get(0).getStatus());
+        assertEquals("test_imp_incident", responses.get(0).getTransformMap());
+        assertEquals("incident", responses.get(0).getTable());
+    }
+
+    @Test
+    public void testIncidentImportWithRetrieve() throws Exception {
+        MockEndpoint mock = getMockEndpoint("mock:servicenow");
+
+        mock.reset();
+        mock.expectedMessageCount(1);
+        mock.expectedHeaderReceived(ServiceNowConstants.RESPONSE_TYPE, Incident.class);
+
+        IncidentImportRequest incident = new IncidentImportRequest();
+        incident.description = UUID.randomUUID().toString();
+
+        template().sendBodyAndHeaders(
+            "direct:servicenow",
+            incident,
+            kvBuilder()
+                .put(ServiceNowConstants.RESOURCE, ServiceNowConstants.RESOURCE_IMPORT)
+                .put(ServiceNowConstants.ACTION, ServiceNowConstants.ACTION_CREATE)
+                .put(ServiceNowConstants.REQUEST_MODEL, IncidentImportRequest.class)
+                .put(ServiceNowConstants.RESPONSE_MODEL, Incident.class)
+                .put(ServiceNowConstants.RETRIEVE_TARGET_RECORD, true)
+                .put(ServiceNowParams.PARAM_TABLE_NAME, "u_test_imp_incident")
+                .build()
+        );
+
+        mock.assertIsSatisfied();
+
+        Incident response = mock.getExchanges().get(0).getIn().getBody(Incident.class);
+        assertNotNull(response);
+        assertEquals(incident.description, response.getDescription());
+        assertNotNull(response.getNumber());
+        assertNotNull(response.getId());
+    }
+
+    // *************************************************************************
+    //
+    // *************************************************************************
+
+    @Override
+    protected RouteBuilder createRouteBuilder() throws Exception {
+        return new RouteBuilder() {
+            public void configure() {
+                from("direct:servicenow")
+                    .to("servicenow:{{env:SERVICENOW_INSTANCE}}")
+                    .to("log:org.apache.camel.component.servicenow?level=INFO&showAll=true")
+                    .to("mock:servicenow");
+            }
+        };
+    }
+
+    // *************************************************************************
+    //
+    // *************************************************************************
+
+    @JsonIgnoreProperties(ignoreUnknown = true)
+    @JsonInclude(JsonInclude.Include.NON_NULL)
+    private static final class IncidentImportRequest {
+        @JsonProperty("description")
+        public String description;
+        @JsonProperty("correlation_id")
+        public String correlationId;
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/109da7c9/components/camel-servicenow/camel-servicenow-component/src/test/java/org/apache/camel/component/servicenow/ServiceNowMetaDataExtensionTest.java
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/camel-servicenow-component/src/test/java/org/apache/camel/component/servicenow/ServiceNowMetaDataExtensionTest.java b/components/camel-servicenow/camel-servicenow-component/src/test/java/org/apache/camel/component/servicenow/ServiceNowMetaDataExtensionTest.java
new file mode 100644
index 0000000..1ddd0cb
--- /dev/null
+++ b/components/camel-servicenow/camel-servicenow-component/src/test/java/org/apache/camel/component/servicenow/ServiceNowMetaDataExtensionTest.java
@@ -0,0 +1,87 @@
+/**
+ * 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.servicenow;
+
+import java.util.Map;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.apache.camel.component.extension.MetaDataExtension;
+import org.junit.Assert;
+import org.junit.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class ServiceNowMetaDataExtensionTest extends ServiceNowTestSupport {
+    private static final Logger LOGGER = LoggerFactory.getLogger(ServiceNowMetaDataExtensionTest.class);
+
+    public ServiceNowMetaDataExtensionTest() {
+        super(false);
+    }
+
+    @Override
+    public boolean isUseRouteBuilder() {
+        return false;
+    }
+
+    protected ServiceNowComponent getComponent() {
+        return context().getComponent("servicenow", ServiceNowComponent.class);
+    }
+
+    protected MetaDataExtension getExtension() {
+        return getComponent().getExtension(MetaDataExtension.class).orElseThrow(UnsupportedOperationException::new);
+    }
+
+    // *********************************
+    //
+    // *********************************
+
+    @Test
+    public void testMetaData() throws Exception {
+        Map<String, Object> parameters = getParameters();
+        parameters.put("objectType", "table");
+        parameters.put("objectName", "incident");
+        //parameters.put("object.sys_user.fields", "first_name,last_name");
+        //parameters.put("object.incident.fields", "caller_id,severity,resolved_at,sys_id");
+        //parameters.put("object.incident.fields", "^sys_.*$");
+        //parameters.put("object.task.fields", "");
+
+        MetaDataExtension.MetaData result = getExtension().meta(parameters).orElseThrow(RuntimeException::new);
+
+        Assert.assertEquals("application/schema+json", result.getAttribute(MetaDataExtension.MetaData.CONTENT_TYPE));
+        Assert.assertEquals(JsonNode.class, result.getAttribute(MetaDataExtension.MetaData.JAVA_TYPE));
+        Assert.assertTrue(result.getPayload(JsonNode.class).hasNonNull("definitions"));
+        Assert.assertTrue(result.getPayload(JsonNode.class).get("definitions").hasNonNull("guid"));
+        Assert.assertTrue(result.getPayload(JsonNode.class).get("definitions").hasNonNull("date"));
+        Assert.assertTrue(result.getPayload(JsonNode.class).get("definitions").hasNonNull("time"));
+        Assert.assertTrue(result.getPayload(JsonNode.class).get("definitions").hasNonNull("date-time"));
+        Assert.assertTrue(result.getPayload(JsonNode.class).hasNonNull("properties"));
+
+        LOGGER.debug(
+            new ObjectMapper().writerWithDefaultPrettyPrinter().writeValueAsString(result.getPayload())
+        );
+    }
+
+    @Test(expected = UnsupportedOperationException.class)
+    public void testInvalidObjectType() throws Exception {
+        Map<String, Object> parameters = getParameters();
+        parameters.put("objectType", "test");
+        parameters.put("objectName", "incident");
+
+        getExtension().meta(parameters);
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/109da7c9/components/camel-servicenow/camel-servicenow-component/src/test/java/org/apache/camel/component/servicenow/ServiceNowScorecardTest.java
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/camel-servicenow-component/src/test/java/org/apache/camel/component/servicenow/ServiceNowScorecardTest.java b/components/camel-servicenow/camel-servicenow-component/src/test/java/org/apache/camel/component/servicenow/ServiceNowScorecardTest.java
new file mode 100644
index 0000000..429bec2
--- /dev/null
+++ b/components/camel-servicenow/camel-servicenow-component/src/test/java/org/apache/camel/component/servicenow/ServiceNowScorecardTest.java
@@ -0,0 +1,63 @@
+/**
+ * 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.servicenow;
+
+import java.util.List;
+
+import org.apache.camel.Produce;
+import org.apache.camel.ProducerTemplate;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.servicenow.model.Scorecard;
+import org.junit.Test;
+
+public class ServiceNowScorecardTest extends ServiceNowTestSupport {
+    @Produce(uri = "direct:servicenow")
+    ProducerTemplate template;
+
+    @Test
+    public void testScorecard() throws Exception {
+        List<Scorecard> scorecardList = template.requestBodyAndHeaders(
+            "direct:servicenow",
+            null,
+            kvBuilder()
+                .put(ServiceNowConstants.RESOURCE, ServiceNowConstants.RESOURCE_SCORECARDS)
+                .put(ServiceNowConstants.ACTION, ServiceNowConstants.ACTION_RETRIEVE)
+                .put(ServiceNowConstants.ACTION_SUBJECT, ServiceNowConstants.ACTION_SUBJECT_PERFORMANCE_ANALYTICS)
+                .put(ServiceNowConstants.MODEL, Scorecard.class)
+                .build(),
+            List.class
+        );
+
+        assertFalse(scorecardList.isEmpty());
+    }
+
+    // *************************************************************************
+    //
+    // *************************************************************************
+
+    @Override
+    protected RouteBuilder createRouteBuilder() throws Exception {
+        return new RouteBuilder() {
+            public void configure() {
+                from("direct:servicenow")
+                    .to("servicenow:{{env:SERVICENOW_INSTANCE}}")
+                    .to("log:org.apache.camel.component.servicenow?level=INFO&showAll=true")
+                    .to("mock:servicenow");
+            }
+        };
+    }
+}


[02/19] camel git commit: CAMEL-11550: Component extensions

Posted by lb...@apache.org.
http://git-wip-us.apache.org/repos/asf/camel/blob/42529399/components/camel-twitter/src/test/java/org/apache/camel/component/twitter/TwitterComponentVerifierTest.java
----------------------------------------------------------------------
diff --git a/components/camel-twitter/src/test/java/org/apache/camel/component/twitter/TwitterComponentVerifierTest.java b/components/camel-twitter/src/test/java/org/apache/camel/component/twitter/TwitterComponentVerifierTest.java
new file mode 100644
index 0000000..5d24a04
--- /dev/null
+++ b/components/camel-twitter/src/test/java/org/apache/camel/component/twitter/TwitterComponentVerifierTest.java
@@ -0,0 +1,24 @@
+/**
+ * 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.twitter;
+
+public class TwitterComponentVerifierTest extends AbstractComponentVerifierTest {
+    @Override
+    protected String getComponentScheme() {
+        return "twitter";
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/42529399/components/camel-twitter/src/test/java/org/apache/camel/component/twitter/directmessage/TwitterDirectmessageComponentVerifierExtensionTest.java
----------------------------------------------------------------------
diff --git a/components/camel-twitter/src/test/java/org/apache/camel/component/twitter/directmessage/TwitterDirectmessageComponentVerifierExtensionTest.java b/components/camel-twitter/src/test/java/org/apache/camel/component/twitter/directmessage/TwitterDirectmessageComponentVerifierExtensionTest.java
new file mode 100644
index 0000000..a5de409
--- /dev/null
+++ b/components/camel-twitter/src/test/java/org/apache/camel/component/twitter/directmessage/TwitterDirectmessageComponentVerifierExtensionTest.java
@@ -0,0 +1,26 @@
+/**
+ * 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.twitter.directmessage;
+
+import org.apache.camel.component.twitter.AbstractComponentVerifierExtensionTest;
+
+public class TwitterDirectmessageComponentVerifierExtensionTest extends AbstractComponentVerifierExtensionTest {
+    @Override
+    protected String getComponentScheme() {
+        return "twitter-directmessage";
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/42529399/components/camel-twitter/src/test/java/org/apache/camel/component/twitter/directmessage/TwitterDirectmessageComponentVerifierTest.java
----------------------------------------------------------------------
diff --git a/components/camel-twitter/src/test/java/org/apache/camel/component/twitter/directmessage/TwitterDirectmessageComponentVerifierTest.java b/components/camel-twitter/src/test/java/org/apache/camel/component/twitter/directmessage/TwitterDirectmessageComponentVerifierTest.java
new file mode 100644
index 0000000..8292712
--- /dev/null
+++ b/components/camel-twitter/src/test/java/org/apache/camel/component/twitter/directmessage/TwitterDirectmessageComponentVerifierTest.java
@@ -0,0 +1,26 @@
+/**
+ * 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.twitter.directmessage;
+
+import org.apache.camel.component.twitter.AbstractComponentVerifierTest;
+
+public class TwitterDirectmessageComponentVerifierTest extends AbstractComponentVerifierTest {
+    @Override
+    protected String getComponentScheme() {
+        return "twitter-directmessage";
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/42529399/components/camel-twitter/src/test/java/org/apache/camel/component/twitter/search/TwitterSearchComponentVerifierExtensionTest.java
----------------------------------------------------------------------
diff --git a/components/camel-twitter/src/test/java/org/apache/camel/component/twitter/search/TwitterSearchComponentVerifierExtensionTest.java b/components/camel-twitter/src/test/java/org/apache/camel/component/twitter/search/TwitterSearchComponentVerifierExtensionTest.java
new file mode 100644
index 0000000..ae8428f
--- /dev/null
+++ b/components/camel-twitter/src/test/java/org/apache/camel/component/twitter/search/TwitterSearchComponentVerifierExtensionTest.java
@@ -0,0 +1,72 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.twitter.search;
+
+import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
+
+import org.apache.camel.Component;
+import org.apache.camel.component.extension.ComponentVerifierExtension;
+import org.apache.camel.component.twitter.AbstractComponentVerifierExtensionTest;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class TwitterSearchComponentVerifierExtensionTest extends AbstractComponentVerifierExtensionTest {
+    @Override
+    protected String getComponentScheme() {
+        return "twitter-search";
+    }
+
+    @Test
+    public void testEmptyConfiguration() {
+        Component component = context().getComponent(getComponentScheme());
+        ComponentVerifierExtension verifier = component.getExtension(ComponentVerifierExtension.class).orElseThrow(IllegalStateException::new);
+
+        {
+            // Parameters validation
+            ComponentVerifierExtension.Result result = verifier.verify(ComponentVerifierExtension.Scope.PARAMETERS, Collections.emptyMap());
+
+            Assert.assertEquals(ComponentVerifierExtension.Result.Status.ERROR, result.getStatus());
+            Assert.assertEquals(5, result.getErrors().size());
+
+            List<String> expected = new LinkedList<>();
+            expected.add("keywords");
+            expected.add("consumerKey");
+            expected.add("consumerSecret");
+            expected.add("accessToken");
+            expected.add("accessTokenSecret");
+
+            for (ComponentVerifierExtension.VerificationError error : result.getErrors()) {
+                expected.removeAll(error.getParameterKeys());
+            }
+
+            Assert.assertTrue("Missing expected params: " + expected.toString(), expected.isEmpty());
+        }
+
+        {
+            // Connectivity validation
+            ComponentVerifierExtension.Result result = verifier.verify(ComponentVerifierExtension.Scope.CONNECTIVITY, Collections.emptyMap());
+
+            Assert.assertEquals(ComponentVerifierExtension.Result.Status.ERROR, result.getStatus());
+            Assert.assertEquals(1, result.getErrors().size());
+            Assert.assertEquals(ComponentVerifierExtension.VerificationError.StandardCode.EXCEPTION, result.getErrors().get(0).getCode());
+            Assert.assertNotNull(result.getErrors().get(0).getDetails().get(ComponentVerifierExtension.VerificationError.ExceptionAttribute.EXCEPTION_INSTANCE));
+            Assert.assertTrue(result.getErrors().get(0).getDetails().get(ComponentVerifierExtension.VerificationError.ExceptionAttribute.EXCEPTION_INSTANCE) instanceof IllegalArgumentException);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/42529399/components/camel-twitter/src/test/java/org/apache/camel/component/twitter/search/TwitterSearchComponentVerifierTest.java
----------------------------------------------------------------------
diff --git a/components/camel-twitter/src/test/java/org/apache/camel/component/twitter/search/TwitterSearchComponentVerifierTest.java b/components/camel-twitter/src/test/java/org/apache/camel/component/twitter/search/TwitterSearchComponentVerifierTest.java
new file mode 100644
index 0000000..6bf6275
--- /dev/null
+++ b/components/camel-twitter/src/test/java/org/apache/camel/component/twitter/search/TwitterSearchComponentVerifierTest.java
@@ -0,0 +1,72 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.twitter.search;
+
+import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
+
+import org.apache.camel.ComponentVerifier;
+import org.apache.camel.component.twitter.AbstractComponentVerifierTest;
+import org.apache.camel.component.twitter.AbstractTwitterComponent;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class TwitterSearchComponentVerifierTest extends AbstractComponentVerifierTest {
+    @Override
+    protected String getComponentScheme() {
+        return "twitter-search";
+    }
+
+    @Test
+    public void testEmptyConfiguration() {
+        AbstractTwitterComponent component = context().getComponent(getComponentScheme(), AbstractTwitterComponent.class);
+        ComponentVerifier verifier = component.getVerifier();
+
+        {
+            // Parameters validation
+            ComponentVerifier.Result result = verifier.verify(ComponentVerifier.Scope.PARAMETERS, Collections.emptyMap());
+
+            Assert.assertEquals(ComponentVerifier.Result.Status.ERROR, result.getStatus());
+            Assert.assertEquals(5, result.getErrors().size());
+
+            List<String> expected = new LinkedList<>();
+            expected.add("keywords");
+            expected.add("consumerKey");
+            expected.add("consumerSecret");
+            expected.add("accessToken");
+            expected.add("accessTokenSecret");
+
+            for (ComponentVerifier.VerificationError error : result.getErrors()) {
+                expected.removeAll(error.getParameterKeys());
+            }
+
+            Assert.assertTrue("Missing expected params: " + expected.toString(), expected.isEmpty());
+        }
+
+        {
+            // Connectivity validation
+            ComponentVerifier.Result result = verifier.verify(ComponentVerifier.Scope.CONNECTIVITY, Collections.emptyMap());
+
+            Assert.assertEquals(ComponentVerifier.Result.Status.ERROR, result.getStatus());
+            Assert.assertEquals(1, result.getErrors().size());
+            Assert.assertEquals(ComponentVerifier.VerificationError.StandardCode.EXCEPTION, result.getErrors().get(0).getCode());
+            Assert.assertNotNull(result.getErrors().get(0).getDetails().get(ComponentVerifier.VerificationError.ExceptionAttribute.EXCEPTION_INSTANCE));
+            Assert.assertTrue(result.getErrors().get(0).getDetails().get(ComponentVerifier.VerificationError.ExceptionAttribute.EXCEPTION_INSTANCE) instanceof IllegalArgumentException);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/42529399/components/camel-twitter/src/test/java/org/apache/camel/component/twitter/streaming/TwitterStreamingComponentVerifierExtensionTest.java
----------------------------------------------------------------------
diff --git a/components/camel-twitter/src/test/java/org/apache/camel/component/twitter/streaming/TwitterStreamingComponentVerifierExtensionTest.java b/components/camel-twitter/src/test/java/org/apache/camel/component/twitter/streaming/TwitterStreamingComponentVerifierExtensionTest.java
new file mode 100644
index 0000000..9dcdb78
--- /dev/null
+++ b/components/camel-twitter/src/test/java/org/apache/camel/component/twitter/streaming/TwitterStreamingComponentVerifierExtensionTest.java
@@ -0,0 +1,26 @@
+/**
+ * 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.twitter.streaming;
+
+import org.apache.camel.component.twitter.AbstractComponentVerifierExtensionTest;
+
+public class TwitterStreamingComponentVerifierExtensionTest extends AbstractComponentVerifierExtensionTest {
+    @Override
+    protected String getComponentScheme() {
+        return "twitter-streaming";
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/42529399/components/camel-twitter/src/test/java/org/apache/camel/component/twitter/streaming/TwitterStreamingComponentVerifierTest.java
----------------------------------------------------------------------
diff --git a/components/camel-twitter/src/test/java/org/apache/camel/component/twitter/streaming/TwitterStreamingComponentVerifierTest.java b/components/camel-twitter/src/test/java/org/apache/camel/component/twitter/streaming/TwitterStreamingComponentVerifierTest.java
new file mode 100644
index 0000000..8d6da45
--- /dev/null
+++ b/components/camel-twitter/src/test/java/org/apache/camel/component/twitter/streaming/TwitterStreamingComponentVerifierTest.java
@@ -0,0 +1,26 @@
+/**
+ * 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.twitter.streaming;
+
+import org.apache.camel.component.twitter.AbstractComponentVerifierTest;
+
+public class TwitterStreamingComponentVerifierTest extends AbstractComponentVerifierTest {
+    @Override
+    protected String getComponentScheme() {
+        return "twitter-streaming";
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/42529399/components/camel-twitter/src/test/java/org/apache/camel/component/twitter/timeline/TwitterTimelineComponentVerifierExtensionTest.java
----------------------------------------------------------------------
diff --git a/components/camel-twitter/src/test/java/org/apache/camel/component/twitter/timeline/TwitterTimelineComponentVerifierExtensionTest.java b/components/camel-twitter/src/test/java/org/apache/camel/component/twitter/timeline/TwitterTimelineComponentVerifierExtensionTest.java
new file mode 100644
index 0000000..1ea478c
--- /dev/null
+++ b/components/camel-twitter/src/test/java/org/apache/camel/component/twitter/timeline/TwitterTimelineComponentVerifierExtensionTest.java
@@ -0,0 +1,26 @@
+/**
+ * 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.twitter.timeline;
+
+import org.apache.camel.component.twitter.AbstractComponentVerifierExtensionTest;
+
+public class TwitterTimelineComponentVerifierExtensionTest extends AbstractComponentVerifierExtensionTest {
+    @Override
+    protected String getComponentScheme() {
+        return "twitter-timeline";
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/42529399/components/camel-twitter/src/test/java/org/apache/camel/component/twitter/timeline/TwitterTimelineComponentVerifierTest.java
----------------------------------------------------------------------
diff --git a/components/camel-twitter/src/test/java/org/apache/camel/component/twitter/timeline/TwitterTimelineComponentVerifierTest.java b/components/camel-twitter/src/test/java/org/apache/camel/component/twitter/timeline/TwitterTimelineComponentVerifierTest.java
new file mode 100644
index 0000000..2081db5
--- /dev/null
+++ b/components/camel-twitter/src/test/java/org/apache/camel/component/twitter/timeline/TwitterTimelineComponentVerifierTest.java
@@ -0,0 +1,26 @@
+/**
+ * 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.twitter.timeline;
+
+import org.apache.camel.component.twitter.AbstractComponentVerifierTest;
+
+public class TwitterTimelineComponentVerifierTest extends AbstractComponentVerifierTest {
+    @Override
+    protected String getComponentScheme() {
+        return "twitter-timeline";
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/42529399/components/camel-undertow/src/main/java/org/apache/camel/component/undertow/UndertowComponent.java
----------------------------------------------------------------------
diff --git a/components/camel-undertow/src/main/java/org/apache/camel/component/undertow/UndertowComponent.java b/components/camel-undertow/src/main/java/org/apache/camel/component/undertow/UndertowComponent.java
index ff522f7..b3623d4 100644
--- a/components/camel-undertow/src/main/java/org/apache/camel/component/undertow/UndertowComponent.java
+++ b/components/camel-undertow/src/main/java/org/apache/camel/component/undertow/UndertowComponent.java
@@ -31,6 +31,7 @@ import org.apache.camel.Processor;
 import org.apache.camel.Producer;
 import org.apache.camel.SSLContextParametersAware;
 import org.apache.camel.VerifiableComponent;
+import org.apache.camel.component.extension.ComponentVerifierExtension;
 import org.apache.camel.impl.DefaultComponent;
 import org.apache.camel.spi.Metadata;
 import org.apache.camel.spi.RestApiConsumerFactory;
@@ -67,10 +68,13 @@ public class UndertowComponent extends DefaultComponent implements RestConsumerF
     private UndertowHostOptions hostOptions;
 
     public UndertowComponent() {
+        this(null);
     }
 
     public UndertowComponent(CamelContext context) {
         super(context);
+
+        registerExtension(UndertowComponentVerifierExtension::new);
     }
 
     @Override
@@ -361,11 +365,9 @@ public class UndertowComponent extends DefaultComponent implements RestConsumerF
         this.hostOptions = hostOptions;
     }
 
-    /**
-     *
-     */
+    @Override
     public ComponentVerifier getVerifier() {
-        return new UndertowComponentVerifier(this);
+        return (scope, parameters) -> getExtension(ComponentVerifierExtension.class).orElseThrow(UnsupportedOperationException::new).verify(scope, parameters);
     }
 
 }

http://git-wip-us.apache.org/repos/asf/camel/blob/42529399/components/camel-undertow/src/main/java/org/apache/camel/component/undertow/UndertowComponentVerifier.java
----------------------------------------------------------------------
diff --git a/components/camel-undertow/src/main/java/org/apache/camel/component/undertow/UndertowComponentVerifier.java b/components/camel-undertow/src/main/java/org/apache/camel/component/undertow/UndertowComponentVerifier.java
deleted file mode 100644
index 03a73f5..0000000
--- a/components/camel-undertow/src/main/java/org/apache/camel/component/undertow/UndertowComponentVerifier.java
+++ /dev/null
@@ -1,239 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.camel.component.undertow;
-
-import java.io.IOException;
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Optional;
-
-import io.undertow.client.ClientCallback;
-import io.undertow.client.ClientConnection;
-import io.undertow.client.ClientExchange;
-import io.undertow.client.ClientRequest;
-import io.undertow.client.ClientResponse;
-import io.undertow.client.UndertowClient;
-import io.undertow.connector.ByteBufferPool;
-import io.undertow.server.DefaultByteBufferPool;
-import io.undertow.util.Headers;
-import io.undertow.util.HttpString;
-import io.undertow.util.Methods;
-import org.apache.camel.impl.verifier.DefaultComponentVerifier;
-import org.apache.camel.impl.verifier.ResultBuilder;
-import org.apache.camel.impl.verifier.ResultErrorBuilder;
-import org.apache.camel.util.FileUtil;
-import org.apache.camel.util.ObjectHelper;
-import org.apache.camel.util.URISupport;
-import org.apache.camel.util.UnsafeUriCharactersEncoder;
-import org.xnio.AbstractIoFuture;
-import org.xnio.IoFuture;
-import org.xnio.OptionMap;
-import org.xnio.Xnio;
-import org.xnio.XnioWorker;
-
-public final class UndertowComponentVerifier extends DefaultComponentVerifier {
-    private final UndertowComponent component;
-
-    public UndertowComponentVerifier(UndertowComponent component) {
-        super("undertow", component.getCamelContext());
-
-        this.component = component;
-    }
-
-    // *********************************
-    // Parameters validation
-    // *********************************
-
-    @Override
-    protected Result verifyParameters(Map<String, Object> parameters) {
-        // Default is success
-        final ResultBuilder builder = ResultBuilder.withStatusAndScope(Result.Status.OK, Scope.PARAMETERS);
-        // Make a copy to avoid clashing with parent validation
-        final HashMap<String, Object> verifyParams = new HashMap<>(parameters);
-        // Check if validation is rest-related
-        final boolean isRest = verifyParams.entrySet().stream().anyMatch(e -> e.getKey().startsWith("rest."));
-
-        if (isRest) {
-            String httpUri = getOption(verifyParams, "rest.host", String.class).orElse(null);
-            String path = getOption(verifyParams, "rest.path", String.class).map(FileUtil::stripLeadingSeparator).orElse(null);
-
-            if (ObjectHelper.isNotEmpty(httpUri) && ObjectHelper.isNotEmpty(path)) {
-                httpUri = httpUri + "/" + path;
-            }
-
-            verifyParams.put("httpURI", httpUri);
-
-            // Cleanup parameters map from rest related stuffs
-            verifyParams.entrySet().removeIf(e -> e.getKey().startsWith("rest."));
-        }
-
-        // Validate using the catalog
-        super.verifyParametersAgainstCatalog(builder, verifyParams);
-
-        return builder.build();
-    }
-
-    // *********************************
-    // Connectivity validation
-    // *********************************
-
-    @Override
-    protected Result verifyConnectivity(Map<String, Object> parameters) {
-        // Default is success
-        final ResultBuilder builder = ResultBuilder.withStatusAndScope(Result.Status.OK, Scope.CONNECTIVITY);
-        // Make a copy to avoid clashing with parent validation
-        final HashMap<String, Object> verifyParams = new HashMap<>(parameters);
-        // Check if validation is rest-related
-        final boolean isRest = verifyParams.entrySet().stream().anyMatch(e -> e.getKey().startsWith("rest."));
-
-        String httpUri;
-        Optional<String> httpMethod;
-
-        if (isRest) {
-            // We are doing rest endpoint validation but as today the endpoint
-            // can't do any param substitution so the validation is performed
-            // against the http uri
-            httpUri = getOption(verifyParams, "rest.host", String.class).orElse(null);
-            httpMethod = getOption(verifyParams, "rest.method", String.class);
-
-            String path = getOption(verifyParams, "rest.path", String.class).map(FileUtil::stripLeadingSeparator).orElse(null);
-            if (ObjectHelper.isNotEmpty(httpUri) && ObjectHelper.isNotEmpty(path)) {
-                httpUri = httpUri + "/" + path;
-            }
-
-            verifyParams.put("httpURI", httpUri);
-
-            // Cleanup parameters from rest related stuffs
-            verifyParams.entrySet().removeIf(e -> e.getKey().startsWith("rest."));
-        }
-
-        httpUri = getOption(verifyParams, "httpURI", String.class).orElse(null);
-        httpMethod = Optional.empty();
-
-        // Check whether the http uri is null or empty
-        if (ObjectHelper.isEmpty(httpUri)) {
-            builder.error(
-                ResultErrorBuilder.withMissingOption("httpURI")
-                    .detail("rest", isRest)
-                    .build()
-            );
-
-            // lack of httpURI is a blocking issue so no need to go further
-            // with the validation
-            return builder.build();
-        }
-
-        try {
-            final UndertowClientWrapper wrapper = new UndertowClientWrapper();
-            final ClientResponse response = wrapper.send(httpUri, httpMethod);
-
-            if (response != null) {
-                int code = response.getResponseCode();
-                if (code == 401) {
-                    // Unauthorized, add authUsername and authPassword to the list
-                    // of parameters in error
-                    builder.error(
-                        ResultErrorBuilder.withHttpCode(code)
-                            .description(response.getStatus())
-                            .build()
-                    );
-                } else if (code >= 300 && code < 400) {
-                    // redirect
-                    builder.error(
-                        ResultErrorBuilder.withHttpCode(code)
-                            .description(response.getStatus())
-                            .parameterKey("httpURI")
-                            .detail(
-                                VerificationError.HttpAttribute.HTTP_REDIRECT,
-                                () -> Optional.ofNullable(response.getResponseHeaders().get(Headers.LOCATION).getFirst()))
-                            .build()
-                    );
-                } else if (code >= 400) {
-                    // generic http error
-                    builder.error(
-                        ResultErrorBuilder.withHttpCode(code)
-                            .description(response.getStatus())
-                            .build()
-                    );
-                }
-            }
-
-        } catch (Exception e) {
-            builder.error(
-                ResultErrorBuilder.withException(e).build()
-            );
-        }
-
-        return builder.build();
-    }
-
-    // *********************************
-    // Helpers
-    // *********************************
-
-    private final class UndertowClientWrapper {
-        private final XnioWorker worker;
-        private final ByteBufferPool pool;
-        private UndertowClient client;
-
-        private UndertowClientWrapper() throws IOException, URISyntaxException {
-            this.worker = Xnio.getInstance().createWorker(OptionMap.EMPTY);
-            this.pool = new DefaultByteBufferPool(true, 17 * 1024);
-            this.client = UndertowClient.getInstance();
-        }
-
-        public ClientResponse send(String httpUri, Optional<String> httpMethod) throws Exception {
-            URI uri = new URI(UnsafeUriCharactersEncoder.encodeHttpURI(httpUri));
-            HttpString method = httpMethod.map(Methods::fromString).orElse(Methods.GET);
-
-            ClientRequest request = new ClientRequest();
-            request.setMethod(method);
-            request.setPath(URISupport.pathAndQueryOf(uri));
-
-            IoFuture<ClientConnection> connectFuture = client.connect(uri, worker, pool, OptionMap.EMPTY);
-            UndertowClientResponseFuture responseFuture = new UndertowClientResponseFuture();
-
-            connectFuture.get().sendRequest(request, responseFuture);
-
-            // We should set a timeout
-            return responseFuture.get().getResponse();
-        }
-    }
-
-    private static final class UndertowClientResponseFuture extends AbstractIoFuture<ClientExchange> implements ClientCallback<ClientExchange> {
-        @Override
-        public void completed(ClientExchange result) {
-            result.setResponseListener(new ClientCallback<ClientExchange>() {
-                @Override
-                public void completed(ClientExchange result) {
-                    setResult(result);
-                }
-                @Override
-                public void failed(IOException e) {
-                    setException(e);
-                }
-            });
-        }
-
-        @Override
-        public void failed(IOException e) {
-            setException(e);
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/camel/blob/42529399/components/camel-undertow/src/main/java/org/apache/camel/component/undertow/UndertowComponentVerifierExtension.java
----------------------------------------------------------------------
diff --git a/components/camel-undertow/src/main/java/org/apache/camel/component/undertow/UndertowComponentVerifierExtension.java b/components/camel-undertow/src/main/java/org/apache/camel/component/undertow/UndertowComponentVerifierExtension.java
new file mode 100644
index 0000000..7be54be
--- /dev/null
+++ b/components/camel-undertow/src/main/java/org/apache/camel/component/undertow/UndertowComponentVerifierExtension.java
@@ -0,0 +1,236 @@
+/**
+ * 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.undertow;
+
+import java.io.IOException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Optional;
+
+import io.undertow.client.ClientCallback;
+import io.undertow.client.ClientConnection;
+import io.undertow.client.ClientExchange;
+import io.undertow.client.ClientRequest;
+import io.undertow.client.ClientResponse;
+import io.undertow.client.UndertowClient;
+import io.undertow.connector.ByteBufferPool;
+import io.undertow.server.DefaultByteBufferPool;
+import io.undertow.util.Headers;
+import io.undertow.util.HttpString;
+import io.undertow.util.Methods;
+import org.apache.camel.component.extension.verifier.DefaultComponentVerifierExtension;
+import org.apache.camel.component.extension.verifier.ResultBuilder;
+import org.apache.camel.component.extension.verifier.ResultErrorBuilder;
+import org.apache.camel.util.FileUtil;
+import org.apache.camel.util.ObjectHelper;
+import org.apache.camel.util.URISupport;
+import org.apache.camel.util.UnsafeUriCharactersEncoder;
+import org.xnio.AbstractIoFuture;
+import org.xnio.IoFuture;
+import org.xnio.OptionMap;
+import org.xnio.Xnio;
+import org.xnio.XnioWorker;
+
+public final class UndertowComponentVerifierExtension extends DefaultComponentVerifierExtension {
+
+    UndertowComponentVerifierExtension() {
+        super("undertow");
+    }
+
+    // *********************************
+    // Parameters validation
+    // *********************************
+
+    @Override
+    protected Result verifyParameters(Map<String, Object> parameters) {
+        // Default is success
+        final ResultBuilder builder = ResultBuilder.withStatusAndScope(Result.Status.OK, Scope.PARAMETERS);
+        // Make a copy to avoid clashing with parent validation
+        final HashMap<String, Object> verifyParams = new HashMap<>(parameters);
+        // Check if validation is rest-related
+        final boolean isRest = verifyParams.entrySet().stream().anyMatch(e -> e.getKey().startsWith("rest."));
+
+        if (isRest) {
+            String httpUri = getOption(verifyParams, "rest.host", String.class).orElse(null);
+            String path = getOption(verifyParams, "rest.path", String.class).map(FileUtil::stripLeadingSeparator).orElse(null);
+
+            if (ObjectHelper.isNotEmpty(httpUri) && ObjectHelper.isNotEmpty(path)) {
+                httpUri = httpUri + "/" + path;
+            }
+
+            verifyParams.put("httpURI", httpUri);
+
+            // Cleanup parameters map from rest related stuffs
+            verifyParams.entrySet().removeIf(e -> e.getKey().startsWith("rest."));
+        }
+
+        // Validate using the catalog
+        super.verifyParametersAgainstCatalog(builder, verifyParams);
+
+        return builder.build();
+    }
+
+    // *********************************
+    // Connectivity validation
+    // *********************************
+
+    @Override
+    protected Result verifyConnectivity(Map<String, Object> parameters) {
+        // Default is success
+        final ResultBuilder builder = ResultBuilder.withStatusAndScope(Result.Status.OK, Scope.CONNECTIVITY);
+        // Make a copy to avoid clashing with parent validation
+        final HashMap<String, Object> verifyParams = new HashMap<>(parameters);
+        // Check if validation is rest-related
+        final boolean isRest = verifyParams.entrySet().stream().anyMatch(e -> e.getKey().startsWith("rest."));
+
+        String httpUri;
+        Optional<String> httpMethod;
+
+        if (isRest) {
+            // We are doing rest endpoint validation but as today the endpoint
+            // can't do any param substitution so the validation is performed
+            // against the http uri
+            httpUri = getOption(verifyParams, "rest.host", String.class).orElse(null);
+            httpMethod = getOption(verifyParams, "rest.method", String.class);
+
+            String path = getOption(verifyParams, "rest.path", String.class).map(FileUtil::stripLeadingSeparator).orElse(null);
+            if (ObjectHelper.isNotEmpty(httpUri) && ObjectHelper.isNotEmpty(path)) {
+                httpUri = httpUri + "/" + path;
+            }
+
+            verifyParams.put("httpURI", httpUri);
+
+            // Cleanup parameters from rest related stuffs
+            verifyParams.entrySet().removeIf(e -> e.getKey().startsWith("rest."));
+        }
+
+        httpUri = getOption(verifyParams, "httpURI", String.class).orElse(null);
+        httpMethod = Optional.empty();
+
+        // Check whether the http uri is null or empty
+        if (ObjectHelper.isEmpty(httpUri)) {
+            builder.error(
+                ResultErrorBuilder.withMissingOption("httpURI")
+                    .detail("rest", isRest)
+                    .build()
+            );
+
+            // lack of httpURI is a blocking issue so no need to go further
+            // with the validation
+            return builder.build();
+        }
+
+        try {
+            final UndertowClientWrapper wrapper = new UndertowClientWrapper();
+            final ClientResponse response = wrapper.send(httpUri, httpMethod);
+
+            if (response != null) {
+                int code = response.getResponseCode();
+                if (code == 401) {
+                    // Unauthorized, add authUsername and authPassword to the list
+                    // of parameters in error
+                    builder.error(
+                        ResultErrorBuilder.withHttpCode(code)
+                            .description(response.getStatus())
+                            .build()
+                    );
+                } else if (code >= 300 && code < 400) {
+                    // redirect
+                    builder.error(
+                        ResultErrorBuilder.withHttpCode(code)
+                            .description(response.getStatus())
+                            .parameterKey("httpURI")
+                            .detail(
+                                VerificationError.HttpAttribute.HTTP_REDIRECT,
+                                () -> Optional.ofNullable(response.getResponseHeaders().get(Headers.LOCATION).getFirst()))
+                            .build()
+                    );
+                } else if (code >= 400) {
+                    // generic http error
+                    builder.error(
+                        ResultErrorBuilder.withHttpCode(code)
+                            .description(response.getStatus())
+                            .build()
+                    );
+                }
+            }
+
+        } catch (Exception e) {
+            builder.error(
+                ResultErrorBuilder.withException(e).build()
+            );
+        }
+
+        return builder.build();
+    }
+
+    // *********************************
+    // Helpers
+    // *********************************
+
+    private final class UndertowClientWrapper {
+        private final XnioWorker worker;
+        private final ByteBufferPool pool;
+        private UndertowClient client;
+
+        private UndertowClientWrapper() throws IOException, URISyntaxException {
+            this.worker = Xnio.getInstance().createWorker(OptionMap.EMPTY);
+            this.pool = new DefaultByteBufferPool(true, 17 * 1024);
+            this.client = UndertowClient.getInstance();
+        }
+
+        public ClientResponse send(String httpUri, Optional<String> httpMethod) throws Exception {
+            URI uri = new URI(UnsafeUriCharactersEncoder.encodeHttpURI(httpUri));
+            HttpString method = httpMethod.map(Methods::fromString).orElse(Methods.GET);
+
+            ClientRequest request = new ClientRequest();
+            request.setMethod(method);
+            request.setPath(URISupport.pathAndQueryOf(uri));
+
+            IoFuture<ClientConnection> connectFuture = client.connect(uri, worker, pool, OptionMap.EMPTY);
+            UndertowClientResponseFuture responseFuture = new UndertowClientResponseFuture();
+
+            connectFuture.get().sendRequest(request, responseFuture);
+
+            // We should set a timeout
+            return responseFuture.get().getResponse();
+        }
+    }
+
+    private static final class UndertowClientResponseFuture extends AbstractIoFuture<ClientExchange> implements ClientCallback<ClientExchange> {
+        @Override
+        public void completed(ClientExchange result) {
+            result.setResponseListener(new ClientCallback<ClientExchange>() {
+                @Override
+                public void completed(ClientExchange result) {
+                    setResult(result);
+                }
+                @Override
+                public void failed(IOException e) {
+                    setException(e);
+                }
+            });
+        }
+
+        @Override
+        public void failed(IOException e) {
+            setException(e);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/42529399/components/camel-undertow/src/test/java/org/apache/camel/component/undertow/UndertowComponentVerifierExtensionTest.java
----------------------------------------------------------------------
diff --git a/components/camel-undertow/src/test/java/org/apache/camel/component/undertow/UndertowComponentVerifierExtensionTest.java b/components/camel-undertow/src/test/java/org/apache/camel/component/undertow/UndertowComponentVerifierExtensionTest.java
new file mode 100644
index 0000000..dc6cd6e
--- /dev/null
+++ b/components/camel-undertow/src/test/java/org/apache/camel/component/undertow/UndertowComponentVerifierExtensionTest.java
@@ -0,0 +1,104 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.undertow;
+
+import java.nio.channels.UnresolvedAddressException;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.camel.Component;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.extension.ComponentVerifierExtension;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class UndertowComponentVerifierExtensionTest extends BaseUndertowTest {
+    @Test
+    public void testParameters() throws Exception {
+        Component component = context().getComponent("undertow");
+        ComponentVerifierExtension verifier = component.getExtension(ComponentVerifierExtension.class).orElseThrow(IllegalStateException::new);
+
+        Map<String, Object> parameters = new HashMap<>();
+        parameters.put("httpURI", "http://localhost:" + getPort());
+        parameters.put("tcpNoDelay", "true");
+
+        ComponentVerifierExtension.Result result = verifier.verify(ComponentVerifierExtension.Scope.PARAMETERS, parameters);
+
+        Assert.assertEquals(ComponentVerifierExtension.Result.Status.OK, result.getStatus());
+    }
+
+    @Test
+    public void testMissingParameters() throws Exception {
+        Component component = context().getComponent("undertow");
+        ComponentVerifierExtension verifier = component.getExtension(ComponentVerifierExtension.class).orElseThrow(IllegalStateException::new);
+
+        Map<String, Object> parameters = new HashMap<>();
+        parameters.put("tcpNoDelay", "true");
+
+        ComponentVerifierExtension.Result result = verifier.verify(ComponentVerifierExtension.Scope.PARAMETERS, parameters);
+
+        Assert.assertEquals(ComponentVerifierExtension.Result.Status.ERROR, result.getStatus());
+        Assert.assertEquals(1, result.getErrors().size());
+        Assert.assertEquals(ComponentVerifierExtension.VerificationError.StandardCode.MISSING_PARAMETER, result.getErrors().get(0).getCode());
+        Assert.assertEquals(1, result.getErrors().get(0).getParameterKeys().size());
+        Assert.assertTrue(result.getErrors().get(0).getParameterKeys().contains("httpURI"));
+    }
+
+    @Test
+    public void testConnectivity() throws Exception {
+        Component component = context().getComponent("undertow");
+        ComponentVerifierExtension verifier = component.getExtension(ComponentVerifierExtension.class).orElseThrow(IllegalStateException::new);
+
+        Map<String, Object> parameters = new HashMap<>();
+        parameters.put("httpURI", "http://localhost:" + getPort());
+        parameters.put("tcpNoDelay", "true");
+
+        ComponentVerifierExtension.Result result = verifier.verify(ComponentVerifierExtension.Scope.CONNECTIVITY, parameters);
+
+        Assert.assertEquals(ComponentVerifierExtension.Result.Status.OK, result.getStatus());
+    }
+
+    @Test
+    public void testConnectivityError() throws Exception {
+        Component component = context().getComponent("undertow");
+        ComponentVerifierExtension verifier = component.getExtension(ComponentVerifierExtension.class).orElseThrow(IllegalStateException::new);
+
+        Map<String, Object> parameters = new HashMap<>();
+        parameters.put("httpURI", "http://no-host:" + getPort());
+
+        ComponentVerifierExtension.Result result = verifier.verify(ComponentVerifierExtension.Scope.CONNECTIVITY, parameters);
+
+        Assert.assertEquals(ComponentVerifierExtension.Result.Status.ERROR, result.getStatus());
+        Assert.assertEquals(1, result.getErrors().size());
+
+        ComponentVerifierExtension.VerificationError error = result.getErrors().get(0);
+
+        Assert.assertEquals(ComponentVerifierExtension.VerificationError.StandardCode.EXCEPTION, error.getCode());
+        Assert.assertTrue(error.getDetail(ComponentVerifierExtension.VerificationError.ExceptionAttribute.EXCEPTION_INSTANCE) instanceof UnresolvedAddressException);
+    }
+
+    @Override
+    protected RouteBuilder createRouteBuilder() throws Exception {
+        return new RouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                from("undertow:http://localhost:{{port}}")
+                    .process(e -> e.getOut().setBody("ok"));
+            }
+        };
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/42529399/connectors/camel-connector-maven-plugin/src/main/java/org/apache/camel/maven/connector/SpringBootAutoConfigurationMojo.java
----------------------------------------------------------------------
diff --git a/connectors/camel-connector-maven-plugin/src/main/java/org/apache/camel/maven/connector/SpringBootAutoConfigurationMojo.java b/connectors/camel-connector-maven-plugin/src/main/java/org/apache/camel/maven/connector/SpringBootAutoConfigurationMojo.java
index c8ca459..23a2396 100644
--- a/connectors/camel-connector-maven-plugin/src/main/java/org/apache/camel/maven/connector/SpringBootAutoConfigurationMojo.java
+++ b/connectors/camel-connector-maven-plugin/src/main/java/org/apache/camel/maven/connector/SpringBootAutoConfigurationMojo.java
@@ -211,7 +211,7 @@ public class SpringBootAutoConfigurationMojo extends AbstractMojo {
         prefix += connectorScheme.toLowerCase(Locale.US);
 
         for (OptionModel option : model.getComponentOptions()) {
-            boolean isComponentOption= componentOptions != null && componentOptions.stream().anyMatch(o -> o.equals(option.getName()));
+            boolean isComponentOption = componentOptions != null && componentOptions.stream().anyMatch(o -> o.equals(option.getName()));
             boolean isEndpointOption = endpointOptions != null && endpointOptions.stream().anyMatch(o -> o.equals(option.getName()));
 
             // only include the options that has been explicit configured in the

http://git-wip-us.apache.org/repos/asf/camel/blob/42529399/connectors/camel-connector/src/main/java/org/apache/camel/component/connector/DefaultConnectorComponent.java
----------------------------------------------------------------------
diff --git a/connectors/camel-connector/src/main/java/org/apache/camel/component/connector/DefaultConnectorComponent.java b/connectors/camel-connector/src/main/java/org/apache/camel/component/connector/DefaultConnectorComponent.java
index 50d1407..d9f24eb 100644
--- a/connectors/camel-connector/src/main/java/org/apache/camel/component/connector/DefaultConnectorComponent.java
+++ b/connectors/camel-connector/src/main/java/org/apache/camel/component/connector/DefaultConnectorComponent.java
@@ -26,6 +26,7 @@ import java.util.Iterator;
 import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Optional;
 
 import org.apache.camel.CamelContext;
 import org.apache.camel.Component;
@@ -36,9 +37,10 @@ import org.apache.camel.Processor;
 import org.apache.camel.VerifiableComponent;
 import org.apache.camel.catalog.CamelCatalog;
 import org.apache.camel.catalog.DefaultCamelCatalog;
+import org.apache.camel.component.extension.ComponentVerifierExtension;
+import org.apache.camel.component.extension.verifier.ResultBuilder;
+import org.apache.camel.component.extension.verifier.ResultErrorBuilder;
 import org.apache.camel.impl.DefaultComponent;
-import org.apache.camel.impl.verifier.ResultBuilder;
-import org.apache.camel.impl.verifier.ResultErrorBuilder;
 import org.apache.camel.util.IntrospectionSupport;
 import org.apache.camel.util.ObjectHelper;
 import org.apache.camel.util.URISupport;
@@ -83,6 +85,8 @@ public abstract class DefaultConnectorComponent extends DefaultComponent impleme
         if (!catalog.findComponentNames().contains(componentScheme)) {
             this.catalog.addComponent(componentScheme, this.model.getBaseJavaType(), catalog.componentJSonSchema(baseScheme));
         }
+
+        registerExtension(this::getComponentVerifierExtension);
     }
 
     @Override
@@ -172,16 +176,20 @@ public abstract class DefaultConnectorComponent extends DefaultComponent impleme
         this.options = Collections.unmodifiableMap(new HashMap<>(baseComponentOptions));
     }
 
-    @SuppressWarnings("unchecked")
     @Override
     public ComponentVerifier getVerifier() {
+        return (scope, parameters) -> getExtension(ComponentVerifierExtension.class).orElseThrow(UnsupportedOperationException::new).verify(scope, parameters);
+    }
+
+    private ComponentVerifierExtension getComponentVerifierExtension() {
         try {
             // Create the component but no need to add it to the camel context
             // nor to start it.
             final Component component = createNewBaseComponent();
+            final Optional<ComponentVerifierExtension> extension = component.getExtension(ComponentVerifierExtension.class);
 
-            if (component instanceof VerifiableComponent) {
-                return (scope, map) -> {
+            if (extension.isPresent()) {
+                return (ComponentVerifierExtension.Scope scope, Map<String, Object> map) -> {
                     Map<String, Object> options;
 
                     try {
@@ -192,18 +200,18 @@ public abstract class DefaultConnectorComponent extends DefaultComponent impleme
                     } catch (URISyntaxException | NoTypeConversionAvailableException e) {
                         // If a failure is detected while reading the catalog, wrap it
                         // and stop the validation step.
-                        return ResultBuilder.withStatusAndScope(ComponentVerifier.Result.Status.OK, scope)
+                        return ResultBuilder.withStatusAndScope(ComponentVerifierExtension.Result.Status.OK, scope)
                             .error(ResultErrorBuilder.withException(e).build())
                             .build();
                     }
 
-                    return ((VerifiableComponent) component).getVerifier().verify(scope, options);
+                    return extension.get().verify(scope, options);
                 };
             } else {
                 return (scope, map) -> {
-                    return ResultBuilder.withStatusAndScope(ComponentVerifier.Result.Status.UNSUPPORTED, scope)
+                    return ResultBuilder.withStatusAndScope(ComponentVerifierExtension.Result.Status.UNSUPPORTED, scope)
                         .error(
-                            ResultErrorBuilder.withCode(ComponentVerifier.VerificationError.StandardCode.UNSUPPORTED)
+                            ResultErrorBuilder.withCode(ComponentVerifierExtension.VerificationError.StandardCode.UNSUPPORTED)
                                 .detail("camel_connector_name", getConnectorName())
                                 .detail("camel_component_name", getComponentName())
                                 .build())
@@ -212,7 +220,7 @@ public abstract class DefaultConnectorComponent extends DefaultComponent impleme
             }
         } catch (Exception e) {
             return (scope, map) -> {
-                return ResultBuilder.withStatusAndScope(ComponentVerifier.Result.Status.OK, scope)
+                return ResultBuilder.withStatusAndScope(ComponentVerifierExtension.Result.Status.OK, scope)
                     .error(ResultErrorBuilder.withException(e).build())
                     .build();
             };