You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by da...@apache.org on 2017/03/10 08:21:35 UTC

[1/3] camel git commit: Bad bad Claus to not refactor this as well when you changed yesterday

Repository: camel
Updated Branches:
  refs/heads/master 0d9cb0002 -> ca6249b06


Bad bad Claus to not refactor this as well when you changed yesterday


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

Branch: refs/heads/master
Commit: ca6249b060d6ba3fd954154a5f77df4688606fa6
Parents: 1e49195
Author: Claus Ibsen <da...@apache.org>
Authored: Fri Mar 10 09:05:14 2017 +0100
Committer: Claus Ibsen <da...@apache.org>
Committed: Fri Mar 10 09:21:26 2017 +0100

----------------------------------------------------------------------
 .../nexus/ConnectorCatalogNexusRepository.java  | 25 +++++++++++++++-----
 .../LocalFileConnectorNexusRepository.java      |  6 +++--
 2 files changed, 23 insertions(+), 8 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/camel/blob/ca6249b0/platforms/camel-catalog-nexus/src/main/java/org/apache/camel/catalog/nexus/ConnectorCatalogNexusRepository.java
----------------------------------------------------------------------
diff --git a/platforms/camel-catalog-nexus/src/main/java/org/apache/camel/catalog/nexus/ConnectorCatalogNexusRepository.java b/platforms/camel-catalog-nexus/src/main/java/org/apache/camel/catalog/nexus/ConnectorCatalogNexusRepository.java
index ce03701..39b1cd9 100644
--- a/platforms/camel-catalog-nexus/src/main/java/org/apache/camel/catalog/nexus/ConnectorCatalogNexusRepository.java
+++ b/platforms/camel-catalog-nexus/src/main/java/org/apache/camel/catalog/nexus/ConnectorCatalogNexusRepository.java
@@ -82,19 +82,21 @@ public class ConnectorCatalogNexusRepository extends BaseNexusRepository {
      * @param dto                 the artifact
      * @param name                the name of connector
      * @param scheme              the connector scheme
+     * @param javaType            the connector java type
      * @param description         the description of connector
      * @param labels              the labels of connector
      * @param connectorJson       camel-connector JSon
      * @param connectorSchemaJson camel-connector-schema JSon
+     * @param componentSchemaJson camel-component-schema JSon
      */
-    protected void addConnector(NexusArtifactDto dto, String name, String scheme, String description, String labels,
-                                String connectorJson, String connectorSchemaJson) {
+    protected void addConnector(NexusArtifactDto dto, String name, String scheme, String javaType, String description, String labels,
+                                String connectorJson, String connectorSchemaJson, String componentSchemaJson) {
 
         String groupId = dto.getGroupId();
         String artifactId = dto.getArtifactId();
         String version = dto.getVersion();
 
-        camelConnectorCatalog.addConnector(groupId, artifactId, version, name, scheme, description, labels, connectorJson, connectorSchemaJson);
+        camelConnectorCatalog.addConnector(groupId, artifactId, version, name, scheme, javaType, description, labels, connectorJson, connectorSchemaJson, componentSchemaJson);
         log.info("Added connector: {}:{}:{}", dto.getGroupId(), dto.getArtifactId(), dto.getVersion());
     }
 
@@ -110,6 +112,7 @@ public class ConnectorCatalogNexusRepository extends BaseNexusRepository {
                 JsonNode tree = mapper.readTree(json[0]);
                 String name = tree.get("name").textValue();
                 String scheme = tree.get("scheme").textValue();
+                String javaType = tree.get("javaType").textValue();
                 String description = tree.get("description").textValue();
                 Iterator<JsonNode> it = tree.withArray("labels").iterator();
 
@@ -119,15 +122,15 @@ public class ConnectorCatalogNexusRepository extends BaseNexusRepository {
                     csb.append(text);
                 }
 
-                addConnector(dto, name, scheme, description, csb.toString(), json[0], json[1]);
+                addConnector(dto, name, scheme, javaType, description, csb.toString(), json[0], json[1], json[2]);
             }
         } catch (IOException e) {
             log.warn("Error scanning JAR for custom Camel components", e);
         }
     }
 
-    private String[] loadConnectorJSonSchema(URLClassLoader classLoader) {
-        String[] answer = new String[2];
+    private String[] loadConnectorJSonSchema(ClassLoader classLoader) {
+        String[] answer = new String[3];
 
         String path = "camel-connector.json";
         try {
@@ -149,6 +152,16 @@ public class ConnectorCatalogNexusRepository extends BaseNexusRepository {
             log.warn("Error loading " + path + " file", e);
         }
 
+        path = "camel-component-schema.json";
+        try {
+            InputStream is = classLoader.getResourceAsStream(path);
+            if (is != null) {
+                answer[2] = loadText(is);
+            }
+        } catch (Throwable e) {
+            log.warn("Error loading " + path + " file", e);
+        }
+
         return answer;
     }
 

http://git-wip-us.apache.org/repos/asf/camel/blob/ca6249b0/platforms/camel-catalog-nexus/src/test/java/org/apache/camel/catalog/nexus/LocalFileConnectorNexusRepository.java
----------------------------------------------------------------------
diff --git a/platforms/camel-catalog-nexus/src/test/java/org/apache/camel/catalog/nexus/LocalFileConnectorNexusRepository.java b/platforms/camel-catalog-nexus/src/test/java/org/apache/camel/catalog/nexus/LocalFileConnectorNexusRepository.java
index 2276576..5c4760e 100644
--- a/platforms/camel-catalog-nexus/src/test/java/org/apache/camel/catalog/nexus/LocalFileConnectorNexusRepository.java
+++ b/platforms/camel-catalog-nexus/src/test/java/org/apache/camel/catalog/nexus/LocalFileConnectorNexusRepository.java
@@ -45,8 +45,10 @@ public class LocalFileConnectorNexusRepository extends ConnectorCatalogNexusRepo
     }
 
     @Override
-    protected void addConnector(NexusArtifactDto dto, String name, String scheme, String description, String labels, String connectorJson, String connectorSchemaJson) {
-        super.addConnector(dto, name, scheme, description, labels, connectorJson, connectorSchemaJson);
+    protected void addConnector(NexusArtifactDto dto, String name, String scheme, String javaType,
+                                String description, String labels,
+                                String connectorJson, String connectorSchemaJson, String componentSchemaJson) {
+        super.addConnector(dto, name, scheme, javaType, description, labels, connectorJson, connectorSchemaJson, componentSchemaJson);
 
         if (onAddConnector != null) {
             onAddConnector.run();


[3/3] camel git commit: Cleaned Javadoc and Ascii doc for REST DSL

Posted by da...@apache.org.
Cleaned Javadoc and Ascii doc for REST DSL


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

Branch: refs/heads/master
Commit: fca73e0521105d269b8bbd616aa7af28627f8b4f
Parents: 0d9cb00
Author: Scott Cranton <sc...@cranton.com>
Authored: Thu Mar 9 21:33:09 2017 -0500
Committer: Claus Ibsen <da...@apache.org>
Committed: Fri Mar 10 09:21:26 2017 +0100

----------------------------------------------------------------------
 .../src/main/docs/rest-api-component.adoc       | 21 +++++++-
 .../camel/model/rest/RestBindingDefinition.java | 34 +++++++-----
 .../apache/camel/model/rest/VerbDefinition.java | 56 +++++++++++---------
 3 files changed, 71 insertions(+), 40 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/camel/blob/fca73e05/camel-core/src/main/docs/rest-api-component.adoc
----------------------------------------------------------------------
diff --git a/camel-core/src/main/docs/rest-api-component.adoc b/camel-core/src/main/docs/rest-api-component.adoc
index 2d9429d..efd4477 100644
--- a/camel-core/src/main/docs/rest-api-component.adoc
+++ b/camel-core/src/main/docs/rest-api-component.adoc
@@ -408,6 +408,25 @@ rest("/users/")
         .to("direct:newUser");
 -----------------------------------------------------------------------------------------------------------
 
+To specify input and/or output using an array, append `[]` to the end
+of the canonical class name, or you can alternatively use the Java DSL only
+continence `typeList` and `outTypeList` where you just specify the array element type.
+Both approaches are shown in the following Java DSL:
+
+[source,java]
+-----------------------------------------------------------------------------------------------------------
+// configure to use restlet on localhost with the given port
+// and enable auto binding mode
+restConfiguration().component("restlet").host("localhost").port(portNum).bindingMode(RestBindingMode.auto);
+
+// use the rest DSL to define the rest services
+rest("/users/")
+    .post().type(UserPojo[].class).outType(CountryPojo[].class)
+        .to("direct:newUser")
+    .put().typeList(UserPojo.class).outTypeList(CountryPojo.class)
+        .to("direct:updateUser");
+-----------------------------------------------------------------------------------------------------------
+
 The�`UserPojo` is just a plain pojo with getter/setter as shown:
 
 [source,java]
@@ -660,7 +679,7 @@ onException(JsonParseException.class)
 
 �
 
-### Parameter default Values
+### Query Parameter default Values
 
 You can specify default values for parameters in the rest-dsl, such as
 the verbose parameter below:

http://git-wip-us.apache.org/repos/asf/camel/blob/fca73e05/camel-core/src/main/java/org/apache/camel/model/rest/RestBindingDefinition.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/model/rest/RestBindingDefinition.java b/camel-core/src/main/java/org/apache/camel/model/rest/RestBindingDefinition.java
index 8c1c291..1c037d4 100644
--- a/camel-core/src/main/java/org/apache/camel/model/rest/RestBindingDefinition.java
+++ b/camel-core/src/main/java/org/apache/camel/model/rest/RestBindingDefinition.java
@@ -244,8 +244,8 @@ public class RestBindingDefinition extends OptionalIdentifiedDefinition<RestBind
     /**
      * Adds a default value for the query parameter
      *
-     * @param paramName   query parameter name
-     * @param defaultValue the default value
+     * @param paramName    query parameter name.
+     * @param defaultValue the default value.
      */
     public void addDefaultValue(String paramName, String defaultValue) {
         if (defaultValues == null) {
@@ -254,7 +254,6 @@ public class RestBindingDefinition extends OptionalIdentifiedDefinition<RestBind
         defaultValues.put(paramName, defaultValue);
     }
 
-
     /**
      * Gets the registered default values for query parameters
      */
@@ -263,7 +262,7 @@ public class RestBindingDefinition extends OptionalIdentifiedDefinition<RestBind
     }
 
     /**
-     * Sets the component name that this definition will apply to  
+     * @param component name of the component that this definition will apply to.
      */
     public void setComponent(String component) {
         this.component = component;
@@ -274,7 +273,7 @@ public class RestBindingDefinition extends OptionalIdentifiedDefinition<RestBind
     }
 
     /**
-     * To define the content type what the REST service consumes (accept as input), such as application/xml or application/json
+     * @param consumes the HTTP Content Type of the input data, such as {@code application/xml} or {@code application/json}.
      */
     public void setConsumes(String consumes) {
         this.consumes = consumes;
@@ -285,7 +284,7 @@ public class RestBindingDefinition extends OptionalIdentifiedDefinition<RestBind
     }
 
     /**
-     * To define the content type what the REST service produces (uses for output), such as application/xml or application/json
+     * @param produces the HTTP Content Type of the output data, such as {@code application/xml} or {@code application/json}.
      */
     public void setProduces(String produces) {
         this.produces = produces;
@@ -296,9 +295,9 @@ public class RestBindingDefinition extends OptionalIdentifiedDefinition<RestBind
     }
 
     /**
-     * Sets the binding mode to use.
-     * <p/>
-     * The default value is off
+     * @param bindingMode the binding mode to use. The default value is {@code RestBindingMode.off}.
+     *
+     * @see RestBindingMode
      */
     public void setBindingMode(RestBindingMode bindingMode) {
         this.bindingMode = bindingMode;
@@ -310,6 +309,9 @@ public class RestBindingDefinition extends OptionalIdentifiedDefinition<RestBind
 
     /**
      * Sets the class name to use for binding from input to POJO for the incoming data
+     *
+     * @param type the canonical name of the class of the input data. Append a {@code []} to the end
+     *             of the canonical name if you want the input to be an array of {@code type}.
      */
     public void setType(String type) {
         this.type = type;
@@ -321,6 +323,9 @@ public class RestBindingDefinition extends OptionalIdentifiedDefinition<RestBind
 
     /**
      * Sets the class name to use for binding from POJO to output for the outgoing data
+     *
+     * @param outType the canonical name of the class of the output data. Append a {@code []} to the end
+     *                of the canonical name if you want the output to be an array of {@code outType}.
      */
     public void setOutType(String outType) {
         this.outType = outType;
@@ -331,8 +336,11 @@ public class RestBindingDefinition extends OptionalIdentifiedDefinition<RestBind
     }
 
     /**
-     * Whether to skip binding on output if there is a custom HTTP error code header.
-     * This allows to build custom error messages that do not bind to json / xml etc, as success messages otherwise will do.
+     * @param skipBindingOnErrorCode set to {@code true} to ignore the specified binding mode on output if there
+     *                               is a custom HTTP error code header. This allows to build custom error messages
+     *                               that do not bind to json / xml etc, as success messages otherwise will do.
+     *
+     * @see VerbDefinition#setBindingMode(RestBindingMode)
      */
     public void setSkipBindingOnErrorCode(Boolean skipBindingOnErrorCode) {
         this.skipBindingOnErrorCode = skipBindingOnErrorCode;
@@ -343,9 +351,7 @@ public class RestBindingDefinition extends OptionalIdentifiedDefinition<RestBind
     }
 
     /**
-     * Whether to enable CORS headers in the HTTP response.
-     * <p/>
-     * The default value is false.
+     * @param enableCORS set to {@code true} to enable CORS headers in the HTTP response. The default value is {@code false}.
      */
     public void setEnableCORS(Boolean enableCORS) {
         this.enableCORS = enableCORS;

http://git-wip-us.apache.org/repos/asf/camel/blob/fca73e05/camel-core/src/main/java/org/apache/camel/model/rest/VerbDefinition.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/model/rest/VerbDefinition.java b/camel-core/src/main/java/org/apache/camel/model/rest/VerbDefinition.java
index cc6731e..35f66e9 100644
--- a/camel-core/src/main/java/org/apache/camel/model/rest/VerbDefinition.java
+++ b/camel-core/src/main/java/org/apache/camel/model/rest/VerbDefinition.java
@@ -129,7 +129,7 @@ public class VerbDefinition extends OptionalIdentifiedDefinition<VerbDefinition>
     }
 
     /**
-     * Sets swagger operation response messages
+     * Sets swagger operation response messages.
      */
     public void setResponseMsgs(List<RestOperationResponseMsgDefinition> params) {
         this.responseMsgs = responseMsgs;
@@ -140,7 +140,7 @@ public class VerbDefinition extends OptionalIdentifiedDefinition<VerbDefinition>
     }
 
     /**
-     * The HTTP verb such as GET or POST
+     * @param method the HTTP verb name such as {@code get, post, put, patch, delete, head}.
      */
     public void setMethod(String method) {
         this.method = method;
@@ -151,7 +151,7 @@ public class VerbDefinition extends OptionalIdentifiedDefinition<VerbDefinition>
     }
 
     /**
-     * Uri template of this REST service such as /{id}.
+     * @param uri the query path for this REST service, such as {@code /&#123;id&#125;}.
      */
     public void setUri(String uri) {
         this.uri = uri;
@@ -162,8 +162,8 @@ public class VerbDefinition extends OptionalIdentifiedDefinition<VerbDefinition>
     }
 
     /**
-     * To define the content type what the REST service consumes (accept as input), such as application/xml or application/json.
-     * This option will override what may be configured on a parent level
+     * @param consumes the HTTP Content Type of the input data, such as {@code application/xml} or {@code application/json}.
+     *                 This option will override what may be configured on a parent level.
      */
     public void setConsumes(String consumes) {
         this.consumes = consumes;
@@ -174,8 +174,8 @@ public class VerbDefinition extends OptionalIdentifiedDefinition<VerbDefinition>
     }
 
     /**
-     * To define the content type what the REST service produces (uses for output), such as application/xml or application/json
-     * This option will override what may be configured on a parent level
+     * @param produces the HTTP Content Type of the output data, such as {@code application/xml} or {@code application/json}.
+     *                 This option will override what may be configured on a parent level.
      */
     public void setProduces(String produces) {
         this.produces = produces;
@@ -186,10 +186,10 @@ public class VerbDefinition extends OptionalIdentifiedDefinition<VerbDefinition>
     }
 
     /**
-     * Sets the binding mode to use.
-     * This option will override what may be configured on a parent level
-     * <p/>
-     * The default value is auto
+     * @param bindingMode the binding mode to use. The default value is {@code RestBindingMode.auto}.
+     *                    This option will override what may be configured on a parent level.
+     *
+     * @see RestBindingMode
      */
     public void setBindingMode(RestBindingMode bindingMode) {
         this.bindingMode = bindingMode;
@@ -200,9 +200,12 @@ public class VerbDefinition extends OptionalIdentifiedDefinition<VerbDefinition>
     }
 
     /**
-     * Whether to skip binding on output if there is a custom HTTP error code header.
-     * This allows to build custom error messages that do not bind to json / xml etc, as success messages otherwise will do.
-     * This option will override what may be configured on a parent level
+     * @param skipBindingOnErrorCode set to {@code true} to ignore the specified binding mode on output if there
+     *                               is a custom HTTP error code header. This allows to build custom error messages
+     *                               that do not bind to json / xml etc, as success messages otherwise will do.
+     *                               This option will override what may be configured on a parent level.
+     *
+     * @see VerbDefinition#setBindingMode(RestBindingMode)
      */
     public void setSkipBindingOnErrorCode(Boolean skipBindingOnErrorCode) {
         this.skipBindingOnErrorCode = skipBindingOnErrorCode;
@@ -213,10 +216,8 @@ public class VerbDefinition extends OptionalIdentifiedDefinition<VerbDefinition>
     }
 
     /**
-     * Whether to enable CORS headers in the HTTP response.
-     * This option will override what may be configured on a parent level
-     * <p/>
-     * The default value is false.
+     * @param enableCORS set to {@code true} to enable CORS headers in the HTTP response. The default value is {@code false}.
+     *                   This option will override what may be configured on a parent level.
      */
     public void setEnableCORS(Boolean enableCORS) {
         this.enableCORS = enableCORS;
@@ -228,7 +229,10 @@ public class VerbDefinition extends OptionalIdentifiedDefinition<VerbDefinition>
 
     /**
      * Sets the class name to use for binding from input to POJO for the incoming data
-     * This option will override what may be configured on a parent level
+     * This option will override what may be configured on a parent level.
+     *
+     * @param type the canonical name of the class of the input data. Append a {@code []} to the end
+     *             of the canonical name if you want the input to be an array of {@code type}.
      */
     public void setType(String type) {
         this.type = type;
@@ -240,7 +244,10 @@ public class VerbDefinition extends OptionalIdentifiedDefinition<VerbDefinition>
 
     /**
      * Sets the class name to use for binding from POJO to output for the outgoing data
-     * This option will override what may be configured on a parent level
+     * This option will override what may be configured on a parent level.
+     *
+     * @param outType the canonical name of the class of the output data. Append a {@code []} to the end
+     *                of the canonical name if you want the output to be an array of {@code outType}.
      */
     public void setOutType(String outType) {
         this.outType = outType;
@@ -251,7 +258,7 @@ public class VerbDefinition extends OptionalIdentifiedDefinition<VerbDefinition>
     }
 
     /**
-     * The route id this rest-dsl is using (read-only)
+     * @param routeId the route id this rest-dsl is using (read-only).
      */
     public void setRouteId(String routeId) {
         this.routeId = routeId;
@@ -262,9 +269,8 @@ public class VerbDefinition extends OptionalIdentifiedDefinition<VerbDefinition>
     }
 
     /**
-     * Whether to include or exclude the VerbDefinition in API documentation.
-     * <p/>
-     * The default value is true.
+     * @param apiDocs set to {@code true} to include or exclude the VerbDefinition in API documentation.
+     *                The default value is true.
      */
     public void setApiDocs(Boolean apiDocs) {
         this.apiDocs = apiDocs;
@@ -389,7 +395,7 @@ public class VerbDefinition extends OptionalIdentifiedDefinition<VerbDefinition>
 
     public String asVerb() {
         // we do not want the jaxb model to repeat itself, by outputting <get method="get">
-        // so we defer the verb from the instance type
+        // so we infer the verb from the instance type
         if (this instanceof GetVerbDefinition) {
             return "get";
         } else if (this instanceof PostVerbDefinition) {


[2/3] camel git commit: Added Unit test to camel-undertow to verify type and outType behave as expected with arrays

Posted by da...@apache.org.
Added Unit test to camel-undertow to verify type and outType behave as expected with arrays


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

Branch: refs/heads/master
Commit: 1e49195dad6bfbcbc6933eaf9de5cb5af6c5c82c
Parents: fca73e0
Author: Scott Cranton <sc...@cranton.com>
Authored: Thu Mar 9 21:33:48 2017 -0500
Committer: Claus Ibsen <da...@apache.org>
Committed: Fri Mar 10 09:21:26 2017 +0100

----------------------------------------------------------------------
 .../rest/RestUndertowHttpPojoTypeTest.java      | 332 +++++++++++++++++++
 1 file changed, 332 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/camel/blob/1e49195d/components/camel-undertow/src/test/java/org/apache/camel/component/undertow/rest/RestUndertowHttpPojoTypeTest.java
----------------------------------------------------------------------
diff --git a/components/camel-undertow/src/test/java/org/apache/camel/component/undertow/rest/RestUndertowHttpPojoTypeTest.java b/components/camel-undertow/src/test/java/org/apache/camel/component/undertow/rest/RestUndertowHttpPojoTypeTest.java
new file mode 100644
index 0000000..1752f54
--- /dev/null
+++ b/components/camel-undertow/src/test/java/org/apache/camel/component/undertow/rest/RestUndertowHttpPojoTypeTest.java
@@ -0,0 +1,332 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.rest;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.apache.camel.Exchange;
+import org.apache.camel.Processor;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.component.undertow.BaseUndertowTest;
+import org.apache.camel.model.rest.RestBindingMode;
+import org.apache.camel.model.rest.RestDefinition;
+import org.apache.camel.model.rest.VerbDefinition;
+import org.junit.Test;
+
+import java.util.*;
+
+public class RestUndertowHttpPojoTypeTest extends BaseUndertowTest {
+    private final ObjectMapper mapper = new ObjectMapper();
+
+    @Test
+    public void testUndertowPojoTypeValidateModel() throws Exception {
+        // Wasn't clear if there's a way to put this test into camel-core just to test the model
+        // perhaps without starting the Camel Context?
+
+        List<RestDefinition> restDefinitions = context().getRestDefinitions();
+        assertNotNull(restDefinitions);
+        assertTrue(restDefinitions.size() > 0);
+
+        RestDefinition restDefinition = restDefinitions.get(0);
+        List<VerbDefinition> verbs = restDefinition.getVerbs();
+        assertNotNull(verbs);
+
+        Map<String, VerbDefinition> mapVerb = new TreeMap<>();
+
+        verbs.forEach(verb -> mapVerb.put(verb.getId(), verb));
+
+        assertEquals(UserPojo[].class.getCanonicalName(), mapVerb.get("getUsers").getOutType());
+        assertEquals(UserPojo[].class.getCanonicalName(), mapVerb.get("getUsersList").getOutType());
+        assertEquals(UserPojo.class.getCanonicalName(), mapVerb.get("getUser").getOutType());
+
+        assertEquals(UserPojo.class.getCanonicalName(), mapVerb.get("putUser").getType());
+        assertEquals(UserPojo[].class.getCanonicalName(), mapVerb.get("putUsers").getType());
+        assertEquals(UserPojo[].class.getCanonicalName(), mapVerb.get("putUsersList").getType());
+    }
+
+    @Test
+    public void testUndertowPojoTypeGetUsers() throws Exception {
+        Exchange outExchange = template.request("undertow:http://localhost:{{port}}/users", new Processor() {
+            @Override
+            public void process(Exchange exchange) throws Exception {
+                exchange.getIn().setHeader(Exchange.HTTP_METHOD, "GET");
+                exchange.getIn().setHeader(Exchange.ACCEPT_CONTENT_TYPE, "application/json");
+            }
+        });
+
+        assertNotNull(outExchange);
+        assertEquals("application/json", outExchange.getOut().getHeader(Exchange.CONTENT_TYPE));
+        String out = outExchange.getOut().getBody(String.class);
+        assertNotNull(out);
+
+        UserPojo[] users = mapper.readValue(out, UserPojo[].class);
+        assertEquals(2, users.length);
+        assertEquals("Scott", users[0].getName());
+        assertEquals("Claus", users[1].getName());
+    }
+
+    @Test
+    public void testUndertowPojoTypePutUser() throws Exception {
+        Exchange outExchange = template.request("undertow:http://localhost:{{port}}/users/1", new Processor() {
+            @Override
+            public void process(Exchange exchange) throws Exception {
+                exchange.getIn().setHeader(Exchange.HTTP_METHOD, "PUT");
+                exchange.getIn().setHeader(Exchange.ACCEPT_CONTENT_TYPE, "application/json");
+                exchange.getIn().setHeader(Exchange.CONTENT_TYPE, "application/json");
+
+                UserPojo user = new UserPojo();
+                user.setId(1);
+                user.setName("Scott");
+
+                String body = mapper.writeValueAsString(user);
+                exchange.getIn().setBody(body);
+            }
+        });
+
+        assertNotNull(outExchange);
+        assertEquals(200, outExchange.getOut().getHeader(Exchange.HTTP_RESPONSE_CODE));
+    }
+
+    @Test
+    public void testUndertowPojoTypePutUserFail() throws Exception {
+        MockEndpoint mock = getMockEndpoint("mock:putUser");
+        mock.expectedMessageCount(0);
+
+        Exchange outExchange = template.request("undertow:http://localhost:{{port}}/users/1", new Processor() {
+            @Override
+            public void process(Exchange exchange) throws Exception {
+                exchange.getIn().setHeader(Exchange.HTTP_METHOD, "PUT");
+                exchange.getIn().setHeader(Exchange.ACCEPT_CONTENT_TYPE, "application/json");
+                exchange.getIn().setHeader(Exchange.CONTENT_TYPE, "application/json");
+
+                CountryPojo country = new CountryPojo();
+                country.setIso("US");
+                country.setCountry("United States");
+
+                String body = mapper.writeValueAsString(country);
+                exchange.getIn().setBody(body);
+            }
+        });
+
+        assertNotNull(outExchange);
+        assertEquals(400, outExchange.getOut().getHeader(Exchange.HTTP_RESPONSE_CODE));
+
+        assertMockEndpointsSatisfied();
+    }
+
+    @Test
+    public void testUndertowPojoTypePutUsers() throws Exception {
+        UserPojo user1 = new UserPojo();
+        user1.setId(1);
+        user1.setName("Scott");
+
+        UserPojo user2 = new UserPojo();
+        user2.setId(2);
+        user2.setName("Claus");
+
+        final UserPojo[] users = new UserPojo[]{user1, user2};
+
+        MockEndpoint mock = getMockEndpoint("mock:putUsers");
+        mock.expectedMessageCount(1);
+        mock.message(0).body(UserPojo[].class);
+
+        Exchange outExchange = template.request("undertow:http://localhost:{{port}}/users", new Processor() {
+            @Override
+            public void process(Exchange exchange) throws Exception {
+                exchange.getIn().setHeader(Exchange.HTTP_METHOD, "PUT");
+                exchange.getIn().setHeader(Exchange.ACCEPT_CONTENT_TYPE, "application/json");
+                exchange.getIn().setHeader(Exchange.CONTENT_TYPE, "application/json");
+
+                String body = mapper.writeValueAsString(users);
+                exchange.getIn().setBody(body);
+            }
+        });
+
+        assertNotNull(outExchange);
+        assertEquals(200, outExchange.getOut().getHeader(Exchange.HTTP_RESPONSE_CODE));
+
+        assertMockEndpointsSatisfied();
+
+        Exchange exchange = mock.assertExchangeReceived(0);
+        UserPojo[] receivedUsers = exchange.getIn().getBody(UserPojo[].class);
+        assertEquals(2, receivedUsers.length);
+        assertEquals(user1.getName(), receivedUsers[0].getName());
+        assertEquals(user2.getName(), receivedUsers[1].getName());
+    }
+
+    @Test
+    public void testUndertowPojoTypePutUsersFail() throws Exception {
+        MockEndpoint mock = getMockEndpoint("mock:putUsers");
+        mock.expectedMessageCount(0);
+
+        Exchange outExchange = template.request("undertow:http://localhost:{{port}}/users", new Processor() {
+            @Override
+            public void process(Exchange exchange) throws Exception {
+                exchange.getIn().setHeader(Exchange.HTTP_METHOD, "PUT");
+                exchange.getIn().setHeader(Exchange.ACCEPT_CONTENT_TYPE, "application/json");
+                exchange.getIn().setHeader(Exchange.CONTENT_TYPE, "application/json");
+
+                UserPojo user = new UserPojo();
+                user.setId(1);
+                user.setName("Scott");
+
+                String body = mapper.writeValueAsString(user);
+                exchange.getIn().setBody(body);
+            }
+        });
+
+        assertNotNull(outExchange);
+        assertEquals(400, outExchange.getOut().getHeader(Exchange.HTTP_RESPONSE_CODE));
+
+        assertMockEndpointsSatisfied();
+    }
+
+    @Test
+    public void testUndertowPojoTypePutUsersList() throws Exception {
+        UserPojo user1 = new UserPojo();
+        user1.setId(1);
+        user1.setName("Scott");
+
+        UserPojo user2 = new UserPojo();
+        user2.setId(2);
+        user2.setName("Claus");
+
+        final UserPojo[] users = new UserPojo[]{user1, user2};
+
+        MockEndpoint mock = getMockEndpoint("mock:putUsersList");
+        mock.expectedMessageCount(1);
+        mock.message(0).body(UserPojo[].class);
+
+        Exchange outExchange = template.request("undertow:http://localhost:{{port}}/users/list", new Processor() {
+            @Override
+            public void process(Exchange exchange) throws Exception {
+                exchange.getIn().setHeader(Exchange.HTTP_METHOD, "PUT");
+                exchange.getIn().setHeader(Exchange.ACCEPT_CONTENT_TYPE, "application/json");
+                exchange.getIn().setHeader(Exchange.CONTENT_TYPE, "application/json");
+
+                String body = mapper.writeValueAsString(users);
+                exchange.getIn().setBody(body);
+            }
+        });
+
+        assertNotNull(outExchange);
+        assertEquals(200, outExchange.getOut().getHeader(Exchange.HTTP_RESPONSE_CODE));
+
+        assertMockEndpointsSatisfied();
+
+        Exchange exchange = mock.assertExchangeReceived(0);
+        UserPojo[] receivedUsers = exchange.getIn().getBody(UserPojo[].class);
+        assertEquals(2, receivedUsers.length);
+        assertEquals(user1.getName(), receivedUsers[0].getName());
+        assertEquals(user2.getName(), receivedUsers[1].getName());
+    }
+
+    @Test
+    public void testUndertowPojoTypePutUsersListFail() throws Exception {
+        MockEndpoint mock = getMockEndpoint("mock:putUsersList");
+        mock.expectedMessageCount(0);
+
+        Exchange outExchange = template.request("undertow:http://localhost:{{port}}/users/list", new Processor() {
+            @Override
+            public void process(Exchange exchange) throws Exception {
+                exchange.getIn().setHeader(Exchange.HTTP_METHOD, "PUT");
+                exchange.getIn().setHeader(Exchange.ACCEPT_CONTENT_TYPE, "application/json");
+                exchange.getIn().setHeader(Exchange.CONTENT_TYPE, "application/json");
+
+                UserPojo user = new UserPojo();
+                user.setId(1);
+                user.setName("Scott");
+
+                String body = mapper.writeValueAsString(user);
+                exchange.getIn().setBody(body);
+            }
+        });
+
+        assertNotNull(outExchange);
+        assertEquals(400, outExchange.getOut().getHeader(Exchange.HTTP_RESPONSE_CODE));
+
+        assertMockEndpointsSatisfied();
+    }
+
+    @Override
+    protected RouteBuilder createRouteBuilder() throws Exception {
+        return new RouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                onException(Exception.class)
+                        .handled(true)
+                        .setHeader(Exchange.HTTP_RESPONSE_CODE, constant(400))
+                        .setHeader(Exchange.CONTENT_TYPE, constant("text/plain"))
+                        .setBody().simple("${exchange.message}");
+
+                // configure to use undertow on localhost with the given port
+                restConfiguration().component("undertow").host("localhost").port(getPort())
+                        .bindingMode(RestBindingMode.json);
+
+                // use the rest DSL to define the rest services
+                rest()
+                    .get("/users").id("getUsers").outType(UserPojo[].class)
+                        .route().process(new Processor() {
+                            @Override
+                            public void process(Exchange exchange) throws Exception {
+                                UserPojo user1 = new UserPojo();
+                                user1.setId(1);
+                                user1.setName("Scott");
+
+                                UserPojo user2 = new UserPojo();
+                                user2.setId(2);
+                                user2.setName("Claus");
+
+                                exchange.getOut().setBody(new UserPojo[] {user1, user2});
+                            }
+                        }).endRest()
+                    .get("/users/list").id("getUsersList").outTypeList(UserPojo.class)
+                        .route().process(new Processor() {
+                            @Override
+                            public void process(Exchange exchange) throws Exception {
+                                UserPojo user1 = new UserPojo();
+                                user1.setId(1);
+                                user1.setName("Scott");
+
+                                UserPojo user2 = new UserPojo();
+                                user2.setId(2);
+                                user2.setName("Claus");
+
+                                exchange.getOut().setBody(new UserPojo[] {user1, user2});
+                            }
+                        }).endRest()
+                    .get("/users/{id}").id("getUser").outType(UserPojo.class)
+                        .route().process(new Processor() {
+                            @Override
+                            public void process(Exchange exchange) throws Exception {
+                                UserPojo user1 = new UserPojo();
+                                user1.setId(exchange.getIn().getHeader("id", int.class));
+                                user1.setName("Scott");
+                                exchange.getOut().setBody(user1);
+                            }
+                        }).endRest()
+                    .put("/users/{id}").id("putUser").type(UserPojo.class)
+                        .to("mock:putUser")
+                    .put("/users").id("putUsers").type(UserPojo[].class)
+                        .to("mock:putUsers")
+                    .put("/users/list").id("putUsersList").typeList(UserPojo.class)
+                        .to("mock:putUsersList");
+            }
+        };
+    }
+
+}