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:10:06 UTC

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

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);
+    }
+}