This is an automated email from the ASF dual-hosted git repository.

jamesbognar pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/juneau.git


The following commit(s) were added to refs/heads/master by this push:
     new d09b3c1  Fix invalid field type for SchemaInfo.required.
d09b3c1 is described below

commit d09b3c16cb99bd485232593756251ef991ff7f47
Author: JamesBognar <[email protected]>
AuthorDate: Thu Mar 15 18:41:23 2018 -0400

    Fix invalid field type for SchemaInfo.required.
---
 .../apache/juneau/dto/swagger/SchemaInfoTest.java  |   38 +-
 .../org/apache/juneau/dto/swagger/SchemaInfo.java  |   65 +-
 .../org/apache/juneau/json/JsonParserSession.java  |   11 +-
 juneau-doc/src/main/javadoc/overview.html          |    7 +
 .../juneau/examples/rest/StaticFilesResource.java  |    9 +
 .../juneau/examples/rest/files/petstore.html       |  213 ----
 .../juneau/examples/rest/files/petstore.html       |  522 ++++++++++
 .../juneau/examples/rest/files/petstore.json       | 1055 ++++++++++++++++++++
 .../java/org/apache/juneau/rest/RestContext.java   |    2 +-
 9 files changed, 1674 insertions(+), 248 deletions(-)

diff --git 
a/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/dto/swagger/SchemaInfoTest.java
 
b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/dto/swagger/SchemaInfoTest.java
index 4aac32a..41b52ce 100644
--- 
a/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/dto/swagger/SchemaInfoTest.java
+++ 
b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/dto/swagger/SchemaInfoTest.java
@@ -438,19 +438,19 @@ public class SchemaInfoTest {
        public void testRequired() {
                SchemaInfo t = new SchemaInfo();
                
-               t.required(true);
-               assertEquals(true, t.getRequired());
-               assertType(Boolean.class, t.getRequired());
+               t.required("['x']");
+               assertEquals("[x]", t.getRequired().toString());
+               assertType(List.class, t.getRequired());
                
-               t.required("true");
-               assertEquals(true, t.getRequired());
-               assertType(Boolean.class, t.getRequired());
+               t.required("['x']");
+               assertEquals("[x, x]", t.getRequired().toString());
+               assertType(List.class, t.getRequired());
 
-               t.required(new StringBuilder("true"));
-               assertEquals(true, t.getRequired());
-               assertType(Boolean.class, t.getRequired());
+               t.required(new StringBuilder("['x']"));
+               assertEquals("[x, x, x]", t.getRequired().toString());
+               assertType(List.class, t.getRequired());
                
-               t.required(null);
+               t.setRequired(null);
                assertNull(t.getRequired());
        }
 
@@ -861,14 +861,14 @@ public class SchemaInfoTest {
                        .set("pattern", "k")
                        .set("properties", new 
AMap<String,Map<String,Object>>().append("l", new 
AMap<String,Object>().append("l1", 1)))
                        .set("readOnly", true)
-                       .set("required", true)
+                       .set("required", new ASet<String>().appendAll("x"))
                        .set("title", "m")
                        .set("type", "n")
                        .set("uniqueItems", true)
                        .set("xml", xml().name("o"))
                        .set("$ref", "ref");
        
-               
assertObjectEquals("{format:'i',title:'m',description:'e','default':'a',multipleOf:123.0,maximum:123.0,exclusiveMaximum:true,minimum:123.0,exclusiveMinimum:true,maxLength:123,minLength:123,pattern:'k',maxItems:123,minItems:123,uniqueItems:true,maxProperties:123,minProperties:123,required:true,'enum':['b'],type:'n',items:{type:'j'},allOf:['d'],properties:{l:{l1:1}},additionalProperties:{c:['c1']},discriminator:'f',readOnly:true,xml:{name:'o'},externalDocs:{url:'h'},example:'g','$ref':'r
 [...]
+               
assertObjectEquals("{format:'i',title:'m',description:'e','default':'a',multipleOf:123.0,maximum:123.0,exclusiveMaximum:true,minimum:123.0,exclusiveMinimum:true,maxLength:123,minLength:123,pattern:'k',maxItems:123,minItems:123,uniqueItems:true,maxProperties:123,minProperties:123,required:['x'],'enum':['b'],type:'n',items:{type:'j'},allOf:['d'],properties:{l:{l1:1}},additionalProperties:{c:['c1']},discriminator:'f',readOnly:true,xml:{name:'o'},externalDocs:{url:'h'},example:'g','$ref':'
 [...]
                
                t
                        .set("default", "a")
@@ -895,14 +895,14 @@ public class SchemaInfoTest {
                        .set("pattern", "k")
                        .set("properties", "{l:{l1:1}}")
                        .set("readOnly", "true")
-                       .set("required", "true")
+                       .set("required", "['x']")
                        .set("title", "m")
                        .set("type", "n")
                        .set("uniqueItems", "true")
                        .set("xml", "{name:'o'}")
                        .set("$ref", "ref");
        
-               
assertObjectEquals("{format:'i',title:'m',description:'e','default':'a',multipleOf:123.0,maximum:123.0,exclusiveMaximum:true,minimum:123.0,exclusiveMinimum:true,maxLength:123,minLength:123,pattern:'k',maxItems:123,minItems:123,uniqueItems:true,maxProperties:123,minProperties:123,required:true,'enum':['b'],type:'n',items:{type:'j'},allOf:['d'],properties:{l:{l1:1}},additionalProperties:{c:['c1']},discriminator:'f',readOnly:true,xml:{name:'o'},externalDocs:{url:'h'},example:'g','$ref':'r
 [...]
+               
assertObjectEquals("{format:'i',title:'m',description:'e','default':'a',multipleOf:123.0,maximum:123.0,exclusiveMaximum:true,minimum:123.0,exclusiveMinimum:true,maxLength:123,minLength:123,pattern:'k',maxItems:123,minItems:123,uniqueItems:true,maxProperties:123,minProperties:123,required:['x'],'enum':['b'],type:'n',items:{type:'j'},allOf:['d'],properties:{l:{l1:1}},additionalProperties:{c:['c1']},discriminator:'f',readOnly:true,xml:{name:'o'},externalDocs:{url:'h'},example:'g','$ref':'
 [...]
                
                t
                        .set("default", new StringBuilder("a"))
@@ -929,14 +929,14 @@ public class SchemaInfoTest {
                        .set("pattern", new StringBuilder("k"))
                        .set("properties", new StringBuilder("{l:{l1:1}}"))
                        .set("readOnly", new StringBuilder("true"))
-                       .set("required", new StringBuilder("true"))
+                       .set("required", new StringBuilder("['x']"))
                        .set("title", new StringBuilder("m"))
                        .set("type", new StringBuilder("n"))
                        .set("uniqueItems", new StringBuilder("true"))
                        .set("xml", new StringBuilder("{name:'o'}"))
                        .set("$ref", new StringBuilder("ref"));
        
-               
assertObjectEquals("{format:'i',title:'m',description:'e','default':'a',multipleOf:123.0,maximum:123.0,exclusiveMaximum:true,minimum:123.0,exclusiveMinimum:true,maxLength:123,minLength:123,pattern:'k',maxItems:123,minItems:123,uniqueItems:true,maxProperties:123,minProperties:123,required:true,'enum':['b'],type:'n',items:{type:'j'},allOf:['d'],properties:{l:{l1:1}},additionalProperties:{c:['c1']},discriminator:'f',readOnly:true,xml:{name:'o'},externalDocs:{url:'h'},example:'g','$ref':'r
 [...]
+               
assertObjectEquals("{format:'i',title:'m',description:'e','default':'a',multipleOf:123.0,maximum:123.0,exclusiveMaximum:true,minimum:123.0,exclusiveMinimum:true,maxLength:123,minLength:123,pattern:'k',maxItems:123,minItems:123,uniqueItems:true,maxProperties:123,minProperties:123,required:['x'],'enum':['b'],type:'n',items:{type:'j'},allOf:['d'],properties:{l:{l1:1}},additionalProperties:{c:['c1']},discriminator:'f',readOnly:true,xml:{name:'o'},externalDocs:{url:'h'},example:'g','$ref':'
 [...]
 
                assertEquals("a", t.get("default", String.class));
                assertEquals("['b']", t.get("enum", String.class));
@@ -962,7 +962,7 @@ public class SchemaInfoTest {
                assertEquals("k", t.get("pattern", String.class));
                assertEquals("{l:{l1:1}}", t.get("properties", String.class));
                assertEquals("true", t.get("readOnly", String.class));
-               assertEquals("true", t.get("required", String.class));
+               assertEquals("['x']", t.get("required", String.class));
                assertEquals("m", t.get("title", String.class));
                assertEquals("n", t.get("type", String.class));
                assertEquals("true", t.get("uniqueItems", String.class));
@@ -993,7 +993,7 @@ public class SchemaInfoTest {
                assertType(String.class, t.get("pattern", Object.class));
                assertType(Map.class, t.get("properties", Object.class));
                assertType(Boolean.class, t.get("readOnly", Object.class));
-               assertType(Boolean.class, t.get("required", Object.class));
+               assertType(List.class, t.get("required", Object.class));
                assertType(String.class, t.get("title", Object.class));
                assertType(String.class, t.get("type", Object.class));
                assertType(Boolean.class, t.get("uniqueItems", Object.class));
@@ -1005,7 +1005,7 @@ public class SchemaInfoTest {
                assertNull(t.get(null, Object.class));
                assertNull(t.get("foo", Object.class));
                
-               String s = 
"{format:'i',title:'m',description:'e','default':'a',multipleOf:123.0,maximum:123.0,exclusiveMaximum:true,minimum:123.0,exclusiveMinimum:true,maxLength:123,minLength:123,pattern:'k',maxItems:123,minItems:123,uniqueItems:true,maxProperties:123,minProperties:123,required:true,'enum':['b'],type:'n',items:{type:'j'},allOf:['d'],properties:{l:{l1:1}},additionalProperties:{c:['c1']},discriminator:'f',readOnly:true,xml:{name:'o'},externalDocs:{url:'h'},example:'g','$ref':'ref'}";
+               String s = 
"{format:'i',title:'m',description:'e','default':'a',multipleOf:123.0,maximum:123.0,exclusiveMaximum:true,minimum:123.0,exclusiveMinimum:true,maxLength:123,minLength:123,pattern:'k',maxItems:123,minItems:123,uniqueItems:true,maxProperties:123,minProperties:123,required:['x'],'enum':['b'],type:'n',items:{type:'j'},allOf:['d'],properties:{l:{l1:1}},additionalProperties:{c:['c1']},discriminator:'f',readOnly:true,xml:{name:'o'},externalDocs:{url:'h'},example:'g','$ref':'ref'}";
                assertObjectEquals(s, JsonParser.DEFAULT.parse(s, 
SchemaInfo.class));
        }
 }
diff --git 
a/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/swagger/SchemaInfo.java
 
b/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/swagger/SchemaInfo.java
index 613a618..90438a0 100644
--- 
a/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/swagger/SchemaInfo.java
+++ 
b/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/swagger/SchemaInfo.java
@@ -80,7 +80,6 @@ public class SchemaInfo extends SwaggerElement {
                exclusiveMaximum,
                exclusiveMinimum,
                uniqueItems,
-               required,
                readOnly;
        private Object 
                _default,
@@ -91,6 +90,8 @@ public class SchemaInfo extends SwaggerElement {
        private List<Object> 
                _enum,
                allOf;
+       private List<String>
+               required;
        private Map<String,Map<String,Object>> properties;
        private Map<String,Object> additionalProperties;
 
@@ -705,36 +706,78 @@ public class SchemaInfo extends SwaggerElement {
        /**
         * Bean property getter:  <property>required</property>.
         * 
+        * <p>
+        * The list of required properties.
+        * 
         * @return The property value, or <jk>null</jk> if it is not set.
         */
-       public Boolean getRequired() {
+       public List<String> getRequired() {
                return required;
        }
 
        /**
         * Bean property setter:  <property>required</property>.
         * 
+        * <p>
+        * The list of required properties.
+        * 
         * @param value 
         *      The new value for this property.
+        *      <br>Valid values:
+        *      <ul>
+        *              <li><js>"http"</js>
+        *              <li><js>"https"</js>
+        *              <li><js>"ws"</js>
+        *              <li><js>"wss"</js>
+        *      </ul>
         *      <br>Can be <jk>null</jk> to unset the property.
         * @return This object (for method chaining).
         */
-       public SchemaInfo setRequired(Boolean value) {
-               required = value;
+       public SchemaInfo setRequired(Collection<String> value) {
+               required = newList(value);
                return this;
        }
 
        /**
-        * Same as {@link #setRequired(Boolean)}.
+        * Adds one or more values to the <property>required</property> 
property.
         * 
-        * @param value
+        * <p>
+        * The list of required properties.
+        * 
+        * @param value 
+        *      The values to add to this property.
+        *      <br>Ignored if <jk>null</jk>.
+        * @return This object (for method chaining).
+        */
+       public SchemaInfo addRequired(Collection<String> value) {
+               required = addToList(required, value);
+               return this;
+       }
+
+       /**
+        * Same as {@link #addRequired(Collection)}.
+        * 
+        * @param values 
         *      The new value for this property.
-        *      <br>Non-boolean values will be converted to boolean using 
<code>Boolean.<jsm>valueOf</jsm>(value.toString())</code>.
-        *      <br>Can be <jk>null</jk> to unset the property.
+        *      <br>Valid types:
+        *      <ul>
+        *              <li><code>Collection&lt;String&gt;</code>
+        *              <li><code>String</code> - JSON array representation of 
<code>Collection&lt;String&gt;</code>
+        *                      <h5 class='figure'>Example:</h5>
+        *                      <p class='bcode'>
+        *      schemes(<js>"['scheme1','scheme2']"</js>);
+        *                      </p>
+        *              <li><code>String</code> - Individual values
+        *                      <h5 class='figure'>Example:</h5>
+        *                      <p class='bcode'>
+        *      schemes(<js>"scheme1</js>, <js>"scheme2"</js>);
+        *                      </p>
+        *      </ul>
         * @return This object (for method chaining).
         */
-       public SchemaInfo required(Object value) {
-               return setRequired(toBoolean(value));
+       public SchemaInfo required(Object...values) {
+               required = addToList(required, values, String.class);
+               return this;
        }
 
        /**
@@ -1323,7 +1366,7 @@ public class SchemaInfo extends SwaggerElement {
                        case "uniqueItems": return uniqueItems(value);
                        case "maxProperties": return maxProperties(value);
                        case "minProperties": return minProperties(value);
-                       case "required": return required(value);
+                       case "required": return 
setRequired(null).required(value);
                        case "enum": return setEnum(null)._enum(value);
                        case "type": return type(value);
                        case "items": return items(value);
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/json/JsonParserSession.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/json/JsonParserSession.java
index e0d7a86..e244aa6 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/json/JsonParserSession.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/json/JsonParserSession.java
@@ -285,9 +285,12 @@ public final class JsonParserSession extends 
ReaderParserSession {
                if (c == 't') {
                        parseKeyword("true", r);
                        return Boolean.TRUE;
+               } else if (c == 'f') {
+                       parseKeyword("false", r);
+                       return Boolean.FALSE;
+               } else {
+                       throw new ParseException(loc(r), "Unrecognized syntax.  
Expected boolean value, actual=''{0}''", r.read(100));
                }
-               parseKeyword("false", r);
-               return Boolean.FALSE;
        }
 
 
@@ -627,9 +630,9 @@ public final class JsonParserSession extends 
ReaderParserSession {
                        String s = r.read(keyword.length());
                        if (s.equals(keyword))
                                return;
-                       throw new ParseException(loc(r), "Unrecognized 
syntax.");
+                       throw new ParseException(loc(r), "Unrecognized syntax.  
Expected=''{0}'', Actual=''{1}''", keyword, s);
                } catch (IndexOutOfBoundsException e) {
-                       throw new ParseException(loc(r), "Unrecognized 
syntax.");
+                       throw new ParseException(loc(r), "Unrecognized syntax.  
Expected=''{0}'', found end-of-file.", keyword);
                }
        }
 
diff --git a/juneau-doc/src/main/javadoc/overview.html 
b/juneau-doc/src/main/javadoc/overview.html
index dbd8f70..e10f7f1 100644
--- a/juneau-doc/src/main/javadoc/overview.html
+++ b/juneau-doc/src/main/javadoc/overview.html
@@ -21247,6 +21247,13 @@
                                </ul>
                </ul>
                
+               <h5 class='topic w800'>juneau-dto</h5>
+               <ul class='spaced-list'>
+                       <li>
+                               Fixed bug where Swagger {@link 
org.apache.juneau.dto.swagger.SchemaInfo#required(Object)} was defined as a 
boolean
+                               instead of a list of strings.
+               </ul>
+               
                <h5 class='topic w800'>juneau-rest-server</h5>
                <ul class='spaced-list'>
                        <li>
diff --git 
a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/StaticFilesResource.java
 
b/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/StaticFilesResource.java
index 0966ccf..d0b9597 100644
--- 
a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/StaticFilesResource.java
+++ 
b/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/StaticFilesResource.java
@@ -15,6 +15,8 @@ package org.apache.juneau.examples.rest;
 import static org.apache.juneau.http.HttpMethodName.*;
 
 import org.apache.juneau.dto.*;
+import org.apache.juneau.dto.swagger.*;
+import org.apache.juneau.http.*;
 import org.apache.juneau.microservice.*;
 import org.apache.juneau.rest.annotation.*;
 import org.apache.juneau.rest.widget.*;
@@ -56,4 +58,11 @@ public class StaticFilesResource extends 
BasicRestServletJena {
                        new LinkString("petstore.html","static/petstore.html")
                };
        }
+       
+       @RestMethod(name=GET, path="/swagger", summary="xxx")
+       public Swagger testSwagger() throws Exception {
+               Swagger s = getContext().getClasspathResource(Swagger.class, 
MediaType.JSON, "files/petstore.json", null);
+               return s;
+       }
+       
 }
diff --git 
a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/files/petstore.html
 
b/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/files/petstore.html
deleted file mode 100644
index ef4bcbe..0000000
--- 
a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/files/petstore.html
+++ /dev/null
@@ -1,213 +0,0 @@
-<!--
- 
***************************************************************************************************************************
- * Licensed to the Apache Software Foundation (ASF) under one or more 
contributor license agreements.  See the NOTICE file *
- * distributed with this work for additional information regarding copyright 
ownership.  The ASF licenses this file        *
- * to you under the Apache License, Version 2.0 (the "License"); you may not 
use this file except in compliance            *
- * with the License.  You may obtain a copy of the License at                  
                                            *
- *                                                                             
                                            *
- *  http://www.apache.org/licenses/LICENSE-2.0                                 
                                            *
- *                                                                             
                                            *
- * Unless required by applicable law or agreed to in writing, software 
distributed under the License is distributed on an  *
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 
or implied.  See the License for the        *
- * specific language governing permissions and limitations under the License.  
                                            *
- 
***************************************************************************************************************************
--->
-
-<html>
-<head>
-
-<style class='text/css'>
-
-.method-button {
-       display: inline-block;
-       font-size: 14px;
-    font-weight: 700;
-    min-width: 60px;
-    padding: 6px 15px;
-    text-align: center;
-    border-radius: 3px;
-    text-shadow: 0 1px 0 rgba(0,0,0,.1);
-    font-family: Titillium Web,sans-serif;
-    color: #fff;
-}
-       
-.get .method-button        { background: rgb(97,175,254); }
-.put .method-button        { background: rgb(252,161,48); }
-.post .method-button       { background: rgb(73,204,144); }
-.delete .method-button     { background: rgb(249,62,62); }
-.options .method-button    { background: rgb(153,102,255); }
-.deprecated .method-button { background: rgb(170,170,170); }
-.other .method-button      { background: rgb(230,230,0); }
-
-.opblock {
-       margin: 0 0 15px;
-       font-family: Open Sans,sans-serif;      
-    align-items: center;
-    cursor: pointer;
-    border-radius: 4px;
-}
-
-.opblock.get        { background: rgba(97,175,254,.1); border: 1px solid 
rgb(97,175,254); }
-.opblock.put        { background: rgba(252,161,48,.1); border: 1px solid 
rgb(252,161,48); }
-.opblock.post       { background: rgba(73,204,144,.1); border: 1px solid 
rgb(73,204,144); }
-.opblock.options    { background: rgba(153,102,255,.1); border: 1px solid 
rgb(153,102,255); }
-.opblock.delete     { background: rgba(249,62,62,.1); border: 1px solid 
rgb(249,62,62); }
-.opblock.deprecated { background: rgba(170,170,170,.1); border: 1px solid 
rgb(170,170,170); }
-.opblock.other      { background: rgba(230,230,0,0.1); border: 1px solid 
rgb(230,230,0); }
-
-.opblock-summary {     
-       padding:5px;
-}
-
-.opblock-summary .path {
-       font-size: 16px;
-       word-break: break-all;
-    font-family: Source Code Pro,monospace;
-    font-weight: 600;
-       color: #3b4151;
-    padding:10px;
-}
-
-.opblock.deprecated .opblock-summary .path { color: #8f9199; text-decoration: 
line-through;}
-.opblock.deprecated .opblock-summary .description { color: #8f9199 }
-
-.opblock-summary .description {
-    font-family: Open Sans,sans-serif;
-    color: #3b4151;
-    font-size: 13px;
-    padding:10px;
-}
-
-.opblock-section-header {
-       padding: 8px 20px;
-    background: hsla(0,0%,100%,.8);
-    box-shadow: 0 1px 2px rgba(0,0,0,.1);
-    font-family: Open Sans,sans-ser;
-    color: #8f9199;      
-}
-
-.opblock-section-header .title {
-    font-size: 14px;
-       font-family: Titillium Web,sans-serif;
-    color: #3b4151;
-    margin: 0px;
-}
-
-.is-open .opblock-contents {
-       display: block;
-}
-.is-closed .opblock-contents {
-       display: none;
-}
-
-.parameters {
-    padding: 0 10px;
-    border-collapse: collapse;
-    margin: 20px;
-       width: 95%;
-}
-
-.parameters th {
-       font-size: 12px;
-    font-weight: 700;
-    padding: 12px 0;
-    text-align: left;
-    border-bottom: 1px solid rgba(59,65,81,.2);
-    font-family: Open Sans,sans-serif;
-    color: #3b4151;
-}
-
-       </style>
-       <script>
-
-       function toggle(e) {
-               var isOpen = e.classList.contains("is-open");
-               if (isOpen) {
-                       e.classList.add("is-closed");
-                       e.classList.remove("is-open");
-               } else {
-                       e.classList.add("is-open");
-                       e.classList.remove("is-closed");
-               }
-               window.getSelection().removeAllRanges();
-       }
-       </script>
-</head>
-<body>
-
-<div class='opblock get is-open' onclick='toggle(this)'>
-       <div class='opblock-summary'>
-               <span class='method-button'>GET</span>
-               <span class='path'>/pet</span>
-               <span class='description'>Everything about your Pets</span>
-       </div>
-       <div class='opblock-contents'>
-               <div class="table-container">
-                       <div class="opblock-section-header">
-                               <h4 class="title">Parameters</h4>
-                       </div>  
-                       <table class="parameters">
-                               <tr>
-                                       <th>Name</th>
-                                       <th>Description</th>
-                               </tr>
-                               <tr>
-                                       <td>foo</td>
-                                       <td>bar</td>
-                               </tr>
-                       </table>
-               </div>
-       </div>
-       
-</div>
-
-<div class='opblock put is-closed' onclick='toggle(this)'>
-       <div class='opblock-summary'>
-               <span class='method-button'>PUT</span>
-               <span class='path'>/pet</span>
-               <span class='description'>Everything about your Pets</span>
-       </div>
-</div>
-
-<div class='opblock post is-closed' onclick='toggle(this)'>
-       <div class='opblock-summary'>
-               <span class='method-button'>POST</span>
-               <span class='path'>/pet</span>
-               <span class='description'>Everything about your Pets</span>
-       </div>
-</div>
-<div class='opblock delete is-closed' onclick='toggle(this)'>
-       <div class='opblock-summary'>
-               <span class='method-button'>DELETE</span>
-               <span class='path'>/pet</span>
-               <span class='description'>Everything about your Pets</span>
-       </div>
-</div>
-<div class='opblock deprecated is-closed' onclick='toggle(this)'>
-       <div class='opblock-summary'>
-               <span class='method-button'>GET</span>
-               <span class='path'>/pet</span>
-               <span class='description'>Everything about your Pets</span>
-       </div>
-</div>
-
-<div class='opblock other is-closed' onclick='toggle(this)'>
-       <div class='opblock-summary'>
-               <span class='method-button'>OTHER</span>
-               <span class='path'>/pet</span>
-               <span class='description'>Everything about your Pets</span>
-       </div>
-</div>
-
-<div class='opblock options is-closed' onclick='toggle(this)'>
-       <div class='opblock-summary'>
-               <span class='method-button'>OPTIONS</span>
-               <span class='path'>/pet</span>
-               <span class='description'>Everything about your Pets</span>
-       </div>
-</div>
-
-
-</body>
-
-</html>
\ No newline at end of file
diff --git 
a/juneau-examples/juneau-examples-rest/src/main/resources/org/apache/juneau/examples/rest/files/petstore.html
 
b/juneau-examples/juneau-examples-rest/src/main/resources/org/apache/juneau/examples/rest/files/petstore.html
new file mode 100644
index 0000000..b3a42d4
--- /dev/null
+++ 
b/juneau-examples/juneau-examples-rest/src/main/resources/org/apache/juneau/examples/rest/files/petstore.html
@@ -0,0 +1,522 @@
+<!--
+ 
***************************************************************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one or more 
contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information regarding copyright 
ownership.  The ASF licenses this file        *
+ * to you under the Apache License, Version 2.0 (the "License"); you may not 
use this file except in compliance            *
+ * with the License.  You may obtain a copy of the License at                  
                                            *
+ *                                                                             
                                            *
+ *  http://www.apache.org/licenses/LICENSE-2.0                                 
                                            *
+ *                                                                             
                                            *
+ * Unless required by applicable law or agreed to in writing, software 
distributed under the License is distributed on an  *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 
or implied.  See the License for the        *
+ * specific language governing permissions and limitations under the License.  
                                            *
+ 
***************************************************************************************************************************
+-->
+
+<html>
+<head>
+
+<style class='text/css'>
+
+.method-button {
+       display: inline-block;
+       font-size: 14px;
+    font-weight: 700;
+    min-width: 60px;
+    padding: 6px 15px;
+    text-align: center;
+    border-radius: 3px;
+    text-shadow: 0 1px 0 rgba(0,0,0,.1);
+    font-family: Titillium Web,sans-serif;
+    color: #fff;
+}
+       
+.get .method-button        { background: rgb(97,175,254); }
+.put .method-button        { background: rgb(252,161,48); }
+.post .method-button       { background: rgb(73,204,144); }
+.delete .method-button     { background: rgb(249,62,62); }
+.options .method-button    { background: rgb(153,102,255); }
+.deprecated .method-button { background: rgb(170,170,170); }
+.other .method-button      { background: rgb(230,230,0); }
+
+.op-block {
+       margin: 0 0 15px;
+       font-family: Open Sans,sans-serif;      
+    align-items: center;
+    cursor: pointer;
+    border-radius: 4px;
+}
+
+.tag-block-summary {
+       margin: 10px 0px;
+       padding: 10px 0px;
+       font-family: Open Sans,sans-serif;      
+    align-items: center;
+    cursor: pointer;
+       border-bottom: 1px solid rgba(59,65,81,.2);
+}
+
+.tag-block-summary .name {
+       font-family: Titillium Web,sans-serif;
+       font-size: 22px;
+       padding: 0px 20px;
+}
+.tag-block-summary .description {
+       font-size: 16px;
+       font-weight: 400;
+       padding: 0px 20px;
+}
+.tag-block-summary .extdocs {
+       float: right;
+       font-size: 14px;
+       font-weight: 400;
+       padding: 0px 20px;
+}
+
+
+.op-block.get        { background: rgba(97,175,254,.1); border: 1px solid 
rgb(97,175,254); }
+.op-block.put        { background: rgba(252,161,48,.1); border: 1px solid 
rgb(252,161,48); }
+.op-block.post       { background: rgba(73,204,144,.1); border: 1px solid 
rgb(73,204,144); }
+.op-block.options    { background: rgba(153,102,255,.1); border: 1px solid 
rgb(153,102,255); }
+.op-block.delete     { background: rgba(249,62,62,.1); border: 1px solid 
rgb(249,62,62); }
+.op-block.deprecated { background: rgba(170,170,170,.1); border: 1px solid 
rgb(170,170,170); }
+.op-block.other      { background: rgba(230,230,0,0.1); border: 1px solid 
rgb(230,230,0); }
+
+.op-block-summary {    
+       padding:5px;
+}
+
+.op-block-summary .path {
+       font-size: 16px;
+       word-break: break-all;
+    font-family: Source Code Pro,monospace;
+    font-weight: 600;
+       color: #3b4151;
+    padding:10px;
+}
+
+.op-block.deprecated .op-block-summary .path { color: #8f9199; 
text-decoration: line-through;}
+.op-block.deprecated .op-block-summary .description { color: #8f9199 }
+
+.op-block-summary .description {
+    font-family: Open Sans,sans-serif;
+    color: #3b4151;
+    font-size: 13px;
+    padding:10px;
+}
+
+.op-block-section-header {
+       padding: 8px 20px;
+    background: hsla(0,0%,100%,.8);
+    box-shadow: 0 1px 2px rgba(0,0,0,.1);
+    font-family: Open Sans,sans-ser;
+    color: #8f9199;      
+}
+
+.op-block-section-header .title {
+    font-size: 14px;
+       font-family: Titillium Web,sans-serif;
+    color: #3b4151;
+    margin: 0px;
+}
+
+.is-tag-block-open .tag-block-contents {
+       display: block;
+}
+.is-tag-block-closed .tag-block-contents {
+       display: none;
+}
+
+.is-op-block-open .op-block-contents {
+       display: block;
+}
+.is-op-block-closed .op-block-contents {
+       display: none;
+}
+
+.parameters, .responses {
+    border-collapse: collapse;
+    margin: 20px;
+       width: 95%;
+       border-bottom: 1px solid rgba(59,65,81,.2);
+}
+
+.parameters th, .responses th {
+       font-size: 12px;
+    font-weight: 700;
+    padding: 5px 0;
+    text-align: left;
+    border-bottom: 1px solid rgba(59,65,81,.2);
+    font-family: Open Sans,sans-serif;
+    color: #3b4151;
+}
+
+.parameters td, .responses td {
+    padding: 12px 0;
+    text-align: left;
+    border-bottom: 1px solid rgba(59,65,81,.2);
+}
+
+.parameter-key .in {
+       font-size: 12px;
+    font-family: Source Code Pro,monospace;
+    font-weight: 600;
+    font-style: italic;
+    color: gray;
+}
+
+.parameter-key .name {
+       font-size: 16px;
+    font-weight: 400;
+    font-family: Titillium Web,sans-serif;
+    color: #3b4151;
+}
+
+.parameter-key .name.required {
+    font-weight: 700;
+}
+
+.parameter-key .type {
+    font-size: 12px;
+    padding: 5px 0;
+    font-family: Source Code Pro,monospace;
+    font-weight: 600;
+    color: #3b4151;
+}
+
+.tab {
+    display: flex;
+    margin: 20px 0 10px;
+    padding: 0;
+    list-style: none;
+    cursor: pointer;
+    font-family: Titillium Web,sans-serif;
+    color: #3b4151;
+    font-size: 12px;
+}
+
+.tab li {
+       margin: 0px 2px;
+}
+
+.tab .active {
+    font-weight: 700;
+}
+
+.tab li:not(:last-child):after {
+    content: " -";
+    font-weight:400;
+    box-sizing: inherit;
+}
+
+.tab li:hover {
+    font-weight:700;
+}
+
+.example {
+    font-size: 12px;
+    margin: 0;
+    padding: 5px 20px;
+    white-space: pre-wrap;
+    word-wrap: break-word;
+    hyphens: auto;
+    border-radius: 4px;
+    background: #41444e;
+    overflow-wrap: break-word;
+    font-family: Source Code Pro,monospace;
+    font-weight: 400;
+    color: #fff;
+       display:none;
+}
+
+.example.active {
+       display:block;
+}
+
+.section {
+       font-size: 12px;
+    font-weight: 700;
+    padding: 5px 0;
+    text-align: left;
+    font-family: Open Sans,sans-serif;
+    color: #3b4151;
+}
+
+.headers .name {
+    font-size: 12px;
+    padding: 5px 0;
+    font-family: Source Code Pro,monospace;
+    font-weight: 600;
+    color: #3b4151;
+}
+
+div.headers {
+       margin: 20px 0px;
+}
+
+.headers .type {
+    font-size: 12px;
+    padding: 5px 0;
+    font-family: Source Code Pro,monospace;
+    font-weight: 600;
+    color: #3b4151;
+}
+
+.section-name {
+       display: inline-block;
+       vertical-align: top;
+       margin-right: 20px;
+       font-size: 12px;
+    font-weight: 700;
+    padding: 5px 0;
+    text-align: left;
+    font-family: Open Sans,sans-serif;
+    color: #3b4151;
+       
+}
+
+.section-table {
+       display: inline-block;
+}
+
+.responses .section-table td {
+       padding: 5px 20px 5px 0px;
+       text-align: left;
+    border-bottom: 1px solid rgba(59,65,81,.2);
+}
+
+
+       </style>
+       <script>
+
+       function toggleOpBlock(e) {
+               e = e.parentNode;
+               var isOpen = e.classList.contains("is-op-block-open");
+               if (isOpen) {
+                       e.classList.add("is-op-block-closed");
+                       e.classList.remove("is-op-block-open");
+               } else {
+                       e.classList.add("is-op-block-open");
+                       e.classList.remove("is-op-block-closed");
+               }
+               window.getSelection().removeAllRanges();
+       }
+       
+       function toggleTagBlock(e) {
+               e = e.parentNode;
+               var isOpen = e.classList.contains("is-tag-block-open");
+               if (isOpen) {
+                       e.classList.add("is-tag-block-closed");
+                       e.classList.remove("is-tag-block-open");
+               } else {
+                       e.classList.add("is-tag-block-open");
+                       e.classList.remove("is-tag-block-closed");
+               }
+               window.getSelection().removeAllRanges();
+       }
+
+       function selectExample(e) {
+               var dataName = e.getAttribute("data-name");
+               var examplesNode = e.parentNode.parentNode;
+               var lis = examplesNode.getElementsByTagName("li");
+               var divs = examplesNode.getElementsByTagName("div");
+               
+               for (var i in lis) {
+                       var li = lis[i], div = divs[i];
+                       if (li.getAttribute("data-name") == dataName) {
+                               li.classList.add("active");
+                               div.classList.add("active");
+                       } else {
+                               li.classList.remove("active");
+                               div.classList.remove("active");
+                       }
+               }
+       }
+       </script>
+</head>
+<body>
+
+<div class='tag-block is-tag-block-open'>
+       <div class='tag-block-summary' onclick='toggleTagBlock(this)'>
+               <span class='name'>pet</span>
+               <span class='description'>Everything about your Pets</span>
+               <span class='extdocs'><a href='http://apache.org'>Find out 
more</a></span>
+       </div>
+       <div class='tag-block-contents'>
+               <div class='op-block get is-op-block-open'>
+                       <div class='op-block-summary' 
onclick='toggleOpBlock(this)'>
+                               <span class='method-button'>GET</span>
+                               <span class='path'>/pet</span>
+                               <span class='description'>Everything about your 
Pets</span>
+                       </div>
+                       <div class='op-block-contents'>
+                               <div class="table-container">
+                                       <div class="op-block-section-header">
+                                               <h4 
class="title">Parameters</h4>
+                                       </div>  
+                                       <table class="parameters">
+                                               <tr>
+                                                       <th>Name</th>
+                                                       <th>Description</th>
+                                               </tr>
+                                               <tr>
+                                                       <td 
class='parameter-key'>
+                                                               <div 
class='name required'>body</div>
+                                                               <div 
class='type'>integer</div>
+                                                               <div 
class='deprecated'></div>
+                                                               <div 
class='in'>(body)</div>
+                                                       </td>
+                                                       <td 
class='parameter-value'>
+                                                               <div 
class='description'>Pet object that needs to be added to the store.</div>
+                                                               <div 
class='examples'>
+                                                                       <ul 
class="tab">
+                                                                               
<li class="active" data-name='model' onclick='selectExample(this)'>Model</li>
+                                                                               
<li data-name='application/json' 
onclick='selectExample(this)'>application/json</li>
+                                                                               
<li data-name='text/xml' onclick='selectExample(this)'>text/xml</li>
+                                                                               
<li data-name='text/html' onclick='selectExample(this)'>text/html</li>
+                                                                               
<li data-name='octal/messagepack' 
onclick='selectExample(this)'>octal/messagepack</li>
+                                                                       </ul>
+                                                                       <div 
data-name='model' class='example active'>
+               MODEL
+                                                                       </div>
+                                                                       <div 
data-name='application/json' class='example'>
+               APPLICATION/JSON
+                                                                       </div>
+                                                                       <div 
data-name='text/xml' class='example'>
+               TEXT/XML
+                                                                       </div>
+                                                                       <div 
data-name='text/html' class='example'>
+               TEXT/HTML
+                                                                       </div>
+                                                                       <div 
data-name='octal/messagepack' class='example'>
+               OCTAL/MESSAGEPACK
+                                                                       </div>
+                                                               </div>
+                                                       </td>
+                                               </tr>
+                                       </table>
+                                       <div class="op-block-section-header">
+                                               <h4 class="title">Responses</h4>
+                                       </div>  
+                                       <table class="responses">
+                                               <tr>
+                                                       <th>Code</th>
+                                                       <th>Description</th>
+                                               </tr>
+                                               <tr>
+                                                       <td>200</td>
+                                                       <td>
+                                                               <div 
class='description'>Successful operation</div>
+                                                               <div 
class='examples'>
+                                                                       <ul 
class="tab">
+                                                                               
<li class="active" data-name='model' onclick='selectExample(this)'>Model</li>
+                                                                               
<li data-name='application/json' 
onclick='selectExample(this)'>application/json</li>
+                                                                               
<li data-name='text/xml' onclick='selectExample(this)'>text/xml</li>
+                                                                               
<li data-name='text/html' onclick='selectExample(this)'>text/html</li>
+                                                                               
<li data-name='octal/messagepack' 
onclick='selectExample(this)'>octal/messagepack</li>
+                                                                       </ul>
+                                                                       <div 
data-name='model' class='example active'>
+               MODEL
+                                                                       </div>
+                                                                       <div 
data-name='application/json' class='example'>
+               APPLICATION/JSON
+                                                                       </div>
+                                                                       <div 
data-name='text/xml' class='example'>
+               TEXT/XML
+                                                                       </div>
+                                                                       <div 
data-name='text/html' class='example'>
+               TEXT/HTML
+                                                                       </div>
+                                                                       <div 
data-name='octal/messagepack' class='example'>
+               OCTAL/MESSAGEPACK
+                                                                       </div>
+                                                               </div>
+                                                               <div 
class='headers'>
+                                                                       <div 
class='section-name'>Headers:</div>
+                                                                       <table 
class='section-table'>
+                                                                               
<tr>
+                                                                               
        <th>Name</th>
+                                                                               
        <th>Description</th>
+                                                                               
        <th>Type</th>
+                                                                               
</tr>
+                                                                               
<tr>
+                                                                               
        <td class='name'>X-Rate-Limit</td>
+                                                                               
        <td class='description'>Calls per hour allowed by the user</td>
+                                                                               
        <td class='type'>integer</td>
+                                                                               
</tr>
+                                                                       </table>
+                                                               </div>
+                                                       </td>
+                                               </tr>
+                                               <tr>
+                                                       <td>400</td>
+                                                       <td>
+                                                               <div 
class='description'>Bad thing happened</div>
+                                                       </td>
+                                               </tr>
+                                       </table>
+                               </div>
+                       </div>
+                       
+               </div>
+               
+               <div class='op-block put is-closed' onclick='toggle(this)'>
+                       <div class='op-block-summary'>
+                               <span class='method-button'>PUT</span>
+                               <span class='path'>/pet</span>
+                               <span class='description'>Everything about your 
Pets</span>
+                       </div>
+               </div>
+               
+               <div class='op-block post is-closed' onclick='toggle(this)'>
+                       <div class='op-block-summary'>
+                               <span class='method-button'>POST</span>
+                               <span class='path'>/pet</span>
+                               <span class='description'>Everything about your 
Pets</span>
+                       </div>
+               </div>
+       </div>
+</div>
+<div class='tag-block is-tag-block-open'>
+       <div class='tag-block-summary' onclick='toggleTagBlock(this)'>
+               <span class='name'>owner</span>
+               <span class='description'>Everything about your Owner</span>
+               <span class='extdocs'><a href='http://apache.org'>Find out 
more</a></span>
+       </div>
+       <div class='tag-block-contents'>
+               <div class='op-block delete is-closed' onclick='toggle(this)'>
+                       <div class='op-block-summary'>
+                               <span class='method-button'>DELETE</span>
+                               <span class='path'>/pet</span>
+                               <span class='description'>Everything about your 
Pets</span>
+                       </div>
+               </div>
+               <div class='op-block deprecated is-closed' 
onclick='toggle(this)'>
+                       <div class='op-block-summary'>
+                               <span class='method-button'>GET</span>
+                               <span class='path'>/pet</span>
+                               <span class='description'>Everything about your 
Pets</span>
+                       </div>
+               </div>
+               
+               <div class='op-block other is-closed' onclick='toggle(this)'>
+                       <div class='op-block-summary'>
+                               <span class='method-button'>OTHER</span>
+                               <span class='path'>/pet</span>
+                               <span class='description'>Everything about your 
Pets</span>
+                       </div>
+               </div>
+               
+               <div class='op-block options is-closed' onclick='toggle(this)'>
+                       <div class='op-block-summary'>
+                               <span class='method-button'>OPTIONS</span>
+                               <span class='path'>/pet</span>
+                               <span class='description'>Everything about your 
Pets</span>
+                       </div>
+               </div>
+       </div>
+</div>
+
+</body>
+
+</html>
\ No newline at end of file
diff --git 
a/juneau-examples/juneau-examples-rest/src/main/resources/org/apache/juneau/examples/rest/files/petstore.json
 
b/juneau-examples/juneau-examples-rest/src/main/resources/org/apache/juneau/examples/rest/files/petstore.json
new file mode 100644
index 0000000..54791ba
--- /dev/null
+++ 
b/juneau-examples/juneau-examples-rest/src/main/resources/org/apache/juneau/examples/rest/files/petstore.json
@@ -0,0 +1,1055 @@
+// 
***************************************************************************************************************************
+// * 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.                                              *
+// 
***************************************************************************************************************************
+
+{
+       "swagger": "2.0",
+       "info": {
+               "description": "This is a sample server Petstore server. You 
can find out more about Swagger at [http://swagger.io](http://swagger.io) or on 
[irc.freenode.net, #swagger](http://swagger.io/irc/). For this sample, you can 
use the api key `special-key` to test the authorization filters.",
+               "version": "1.0.0",
+               "title": "Swagger Petstore",
+               "termsOfService": "http://swagger.io/terms/";,
+               "contact": {
+                       "email": "[email protected]"
+               },
+               "license": {
+                       "name": "Apache 2.0",
+                       "url": "http://www.apache.org/licenses/LICENSE-2.0.html";
+               }
+       },
+       "host": "petstore.swagger.io",
+       "basePath": "/v2",
+       "tags": [
+               {
+                       "name": "pet",
+                       "description": "Everything about your Pets",
+                       "externalDocs": {
+                               "description": "Find out more",
+                               "url": "http://swagger.io";
+                       }
+               },
+               {
+                       "name": "store",
+                       "description": "Access to Petstore orders"
+               },
+               {
+                       "name": "user",
+                       "description": "Operations about user",
+                       "externalDocs": {
+                               "description": "Find out more about our store",
+                               "url": "http://swagger.io";
+                       }
+               }
+       ],
+       "schemes": [
+               "http"
+       ],
+       "paths": {
+               "/pet": {
+                       "post": {
+                               "tags": [
+                                       "pet"
+                               ],
+                               "summary": "Add a new pet to the store",
+                               "description": "",
+                               "operationId": "addPet",
+                               "consumes": [
+                                       "application/json",
+                                       "application/xml"
+                               ],
+                               "produces": [
+                                       "application/xml",
+                                       "application/json"
+                               ],
+                               "parameters": [
+                                       {
+                                               "in": "body",
+                                               "name": "body",
+                                               "description": "Pet object that 
needs to be added to the store",
+                                               "required": true,
+                                               "schema": {
+                                                       "$ref": 
"#/definitions/Pet"
+                                               }
+                                       }
+                               ],
+                               "responses": {
+                                       "405": {
+                                               "description": "Invalid input"
+                                       }
+                               },
+                               "security": [
+                                       {
+                                               "petstore_auth": [
+                                                       "write:pets",
+                                                       "read:pets"
+                                               ]
+                                       }
+                               ]
+                       },
+                       "put": {
+                               "tags": [
+                                       "pet"
+                               ],
+                               "summary": "Update an existing pet",
+                               "description": "",
+                               "operationId": "updatePet",
+                               "consumes": [
+                                       "application/json",
+                                       "application/xml"
+                               ],
+                               "produces": [
+                                       "application/xml",
+                                       "application/json"
+                               ],
+                               "parameters": [
+                                       {
+                                               "in": "body",
+                                               "name": "body",
+                                               "description": "Pet object that 
needs to be added to the store",
+                                               "required": true,
+                                               "schema": {
+                                                       "$ref": 
"#/definitions/Pet"
+                                               }
+                                       }
+                               ],
+                               "responses": {
+                                       "400": {
+                                               "description": "Invalid ID 
supplied"
+                                       },
+                                       "404": {
+                                               "description": "Pet not found"
+                                       },
+                                       "405": {
+                                               "description": "Validation 
exception"
+                                       }
+                               },
+                               "security": [
+                                       {
+                                               "petstore_auth": [
+                                                       "write:pets",
+                                                       "read:pets"
+                                               ]
+                                       }
+                               ]
+                       }
+               },
+               "/pet/findByStatus": {
+                       "get": {
+                               "tags": [
+                                       "pet"
+                               ],
+                               "summary": "Finds Pets by status",
+                               "description": "Multiple status values can be 
provided with comma separated strings",
+                               "operationId": "findPetsByStatus",
+                               "produces": [
+                                       "application/xml",
+                                       "application/json"
+                               ],
+                               "parameters": [
+                                       {
+                                               "name": "status",
+                                               "in": "query",
+                                               "description": "Status values 
that need to be considered for filter",
+                                               "required": true,
+                                               "type": "array",
+                                               "items": {
+                                                       "type": "string",
+                                                       "enum": [
+                                                               "available",
+                                                               "pending",
+                                                               "sold"
+                                                       ],
+                                                       "default": "available"
+                                               },
+                                               "collectionFormat": "multi"
+                                       }
+                               ],
+                               "responses": {
+                                       "200": {
+                                               "description": "successful 
operation",
+                                               "schema": {
+                                                       "type": "array",
+                                                       "items": {
+                                                               "$ref": 
"#/definitions/Pet"
+                                                       }
+                                               }
+                                       },
+                                       "400": {
+                                               "description": "Invalid status 
value"
+                                       }
+                               },
+                               "security": [
+                                       {
+                                               "petstore_auth": [
+                                                       "write:pets",
+                                                       "read:pets"
+                                               ]
+                                       }
+                               ]
+                       }
+               },
+               "/pet/findByTags": {
+                       "get": {
+                               "tags": [
+                                       "pet"
+                               ],
+                               "summary": "Finds Pets by tags",
+                               "description": "Muliple tags can be provided 
with comma separated strings. Use tag1, tag2, tag3 for testing.",
+                               "operationId": "findPetsByTags",
+                               "produces": [
+                                       "application/xml",
+                                       "application/json"
+                               ],
+                               "parameters": [
+                                       {
+                                               "name": "tags",
+                                               "in": "query",
+                                               "description": "Tags to filter 
by",
+                                               "required": true,
+                                               "type": "array",
+                                               "items": {
+                                                       "type": "string"
+                                               },
+                                               "collectionFormat": "multi"
+                                       }
+                               ],
+                               "responses": {
+                                       "200": {
+                                               "description": "successful 
operation",
+                                               "schema": {
+                                                       "type": "array",
+                                                       "items": {
+                                                               "$ref": 
"#/definitions/Pet"
+                                                       }
+                                               }
+                                       },
+                                       "400": {
+                                               "description": "Invalid tag 
value"
+                                       }
+                               },
+                               "security": [
+                                       {
+                                               "petstore_auth": [
+                                                       "write:pets",
+                                                       "read:pets"
+                                               ]
+                                       }
+                               ],
+                               "deprecated": true
+                       }
+               },
+               "/pet/{petId}": {
+                       "get": {
+                               "tags": [
+                                       "pet"
+                               ],
+                               "summary": "Find pet by ID",
+                               "description": "Returns a single pet",
+                               "operationId": "getPetById",
+                               "produces": [
+                                       "application/xml",
+                                       "application/json"
+                               ],
+                               "parameters": [
+                                       {
+                                               "name": "petId",
+                                               "in": "path",
+                                               "description": "ID of pet to 
return",
+                                               "required": true,
+                                               "type": "integer",
+                                               "format": "int64"
+                                       }
+                               ],
+                               "responses": {
+                                       "200": {
+                                               "description": "successful 
operation",
+                                               "schema": {
+                                                       "$ref": 
"#/definitions/Pet"
+                                               }
+                                       },
+                                       "400": {
+                                               "description": "Invalid ID 
supplied"
+                                       },
+                                       "404": {
+                                               "description": "Pet not found"
+                                       }
+                               },
+                               "security": [
+                                       {
+                                               "api_key": []
+                                       }
+                               ]
+                       },
+                       "post": {
+                               "tags": [
+                                       "pet"
+                               ],
+                               "summary": "Updates a pet in the store with 
form data",
+                               "description": "",
+                               "operationId": "updatePetWithForm",
+                               "consumes": [
+                                       "application/x-www-form-urlencoded"
+                               ],
+                               "produces": [
+                                       "application/xml",
+                                       "application/json"
+                               ],
+                               "parameters": [
+                                       {
+                                               "name": "petId",
+                                               "in": "path",
+                                               "description": "ID of pet that 
needs to be updated",
+                                               "required": true,
+                                               "type": "integer",
+                                               "format": "int64"
+                                       },
+                                       {
+                                               "name": "name",
+                                               "in": "formData",
+                                               "description": "Updated name of 
the pet",
+                                               "required": false,
+                                               "type": "string"
+                                       },
+                                       {
+                                               "name": "status",
+                                               "in": "formData",
+                                               "description": "Updated status 
of the pet",
+                                               "required": false,
+                                               "type": "string"
+                                       }
+                               ],
+                               "responses": {
+                                       "405": {
+                                               "description": "Invalid input"
+                                       }
+                               },
+                               "security": [
+                                       {
+                                               "petstore_auth": [
+                                                       "write:pets",
+                                                       "read:pets"
+                                               ]
+                                       }
+                               ]
+                       },
+                       "delete": {
+                               "tags": [
+                                       "pet"
+                               ],
+                               "summary": "Deletes a pet",
+                               "description": "",
+                               "operationId": "deletePet",
+                               "produces": [
+                                       "application/xml",
+                                       "application/json"
+                               ],
+                               "parameters": [
+                                       {
+                                               "name": "api_key",
+                                               "in": "header",
+                                               "required": false,
+                                               "type": "string"
+                                       },
+                                       {
+                                               "name": "petId",
+                                               "in": "path",
+                                               "description": "Pet id to 
delete",
+                                               "required": true,
+                                               "type": "integer",
+                                               "format": "int64"
+                                       }
+                               ],
+                               "responses": {
+                                       "400": {
+                                               "description": "Invalid ID 
supplied"
+                                       },
+                                       "404": {
+                                               "description": "Pet not found"
+                                       }
+                               },
+                               "security": [
+                                       {
+                                               "petstore_auth": [
+                                                       "write:pets",
+                                                       "read:pets"
+                                               ]
+                                       }
+                               ]
+                       }
+               },
+               "/pet/{petId}/uploadImage": {
+                       "post": {
+                               "tags": [
+                                       "pet"
+                               ],
+                               "summary": "uploads an image",
+                               "description": "",
+                               "operationId": "uploadFile",
+                               "consumes": [
+                                       "multipart/form-data"
+                               ],
+                               "produces": [
+                                       "application/json"
+                               ],
+                               "parameters": [
+                                       {
+                                               "name": "petId",
+                                               "in": "path",
+                                               "description": "ID of pet to 
update",
+                                               "required": true,
+                                               "type": "integer",
+                                               "format": "int64"
+                                       },
+                                       {
+                                               "name": "additionalMetadata",
+                                               "in": "formData",
+                                               "description": "Additional data 
to pass to server",
+                                               "required": false,
+                                               "type": "string"
+                                       },
+                                       {
+                                               "name": "file",
+                                               "in": "formData",
+                                               "description": "file to upload",
+                                               "required": false,
+                                               "type": "file"
+                                       }
+                               ],
+                               "responses": {
+                                       "200": {
+                                               "description": "successful 
operation",
+                                               "schema": {
+                                                       "$ref": 
"#/definitions/ApiResponse"
+                                               }
+                                       }
+                               },
+                               "security": [
+                                       {
+                                               "petstore_auth": [
+                                                       "write:pets",
+                                                       "read:pets"
+                                               ]
+                                       }
+                               ]
+                       }
+               },
+               "/store/inventory": {
+                       "get": {
+                               "tags": [
+                                       "store"
+                               ],
+                               "summary": "Returns pet inventories by status",
+                               "description": "Returns a map of status codes 
to quantities",
+                               "operationId": "getInventory",
+                               "produces": [
+                                       "application/json"
+                               ],
+                               "parameters": [],
+                               "responses": {
+                                       "200": {
+                                               "description": "successful 
operation",
+                                               "schema": {
+                                                       "type": "object",
+                                                       "additionalProperties": 
{
+                                                               "type": 
"integer",
+                                                               "format": 
"int32"
+                                                       }
+                                               }
+                                       }
+                               },
+                               "security": [
+                                       {
+                                               "api_key": []
+                                       }
+                               ]
+                       }
+               },
+               "/store/order": {
+                       "post": {
+                               "tags": [
+                                       "store"
+                               ],
+                               "summary": "Place an order for a pet",
+                               "description": "",
+                               "operationId": "placeOrder",
+                               "produces": [
+                                       "application/xml",
+                                       "application/json"
+                               ],
+                               "parameters": [
+                                       {
+                                               "in": "body",
+                                               "name": "body",
+                                               "description": "order placed 
for purchasing the pet",
+                                               "required": true,
+                                               "schema": {
+                                                       "$ref": 
"#/definitions/Order"
+                                               }
+                                       }
+                               ],
+                               "responses": {
+                                       "200": {
+                                               "description": "successful 
operation",
+                                               "schema": {
+                                                       "$ref": 
"#/definitions/Order"
+                                               }
+                                       },
+                                       "400": {
+                                               "description": "Invalid Order"
+                                       }
+                               }
+                       }
+               },
+               "/store/order/{orderId}": {
+                       "get": {
+                               "tags": [
+                                       "store"
+                               ],
+                               "summary": "Find purchase order by ID",
+                               "description": "For valid response try integer 
IDs with value >= 1 and <= 10. Other values will generated exceptions",
+                               "operationId": "getOrderById",
+                               "produces": [
+                                       "application/xml",
+                                       "application/json"
+                               ],
+                               "parameters": [
+                                       {
+                                               "name": "orderId",
+                                               "in": "path",
+                                               "description": "ID of pet that 
needs to be fetched",
+                                               "required": true,
+                                               "type": "integer",
+                                               "maximum": 10.0,
+                                               "minimum": 1.0,
+                                               "format": "int64"
+                                       }
+                               ],
+                               "responses": {
+                                       "200": {
+                                               "description": "successful 
operation",
+                                               "schema": {
+                                                       "$ref": 
"#/definitions/Order"
+                                               }
+                                       },
+                                       "400": {
+                                               "description": "Invalid ID 
supplied"
+                                       },
+                                       "404": {
+                                               "description": "Order not found"
+                                       }
+                               }
+                       },
+                       "delete": {
+                               "tags": [
+                                       "store"
+                               ],
+                               "summary": "Delete purchase order by ID",
+                               "description": "For valid response try integer 
IDs with positive integer value. Negative or non-integer values will generate 
API errors",
+                               "operationId": "deleteOrder",
+                               "produces": [
+                                       "application/xml",
+                                       "application/json"
+                               ],
+                               "parameters": [
+                                       {
+                                               "name": "orderId",
+                                               "in": "path",
+                                               "description": "ID of the order 
that needs to be deleted",
+                                               "required": true,
+                                               "type": "integer",
+                                               "minimum": 1.0,
+                                               "format": "int64"
+                                       }
+                               ],
+                               "responses": {
+                                       "400": {
+                                               "description": "Invalid ID 
supplied"
+                                       },
+                                       "404": {
+                                               "description": "Order not found"
+                                       }
+                               }
+                       }
+               },
+               "/user": {
+                       "post": {
+                               "tags": [
+                                       "user"
+                               ],
+                               "summary": "Create user",
+                               "description": "This can only be done by the 
logged in user.",
+                               "operationId": "createUser",
+                               "produces": [
+                                       "application/xml",
+                                       "application/json"
+                               ],
+                               "parameters": [
+                                       {
+                                               "in": "body",
+                                               "name": "body",
+                                               "description": "Created user 
object",
+                                               "required": true,
+                                               "schema": {
+                                                       "$ref": 
"#/definitions/User"
+                                               }
+                                       }
+                               ],
+                               "responses": {
+                                       "default": {
+                                               "description": "successful 
operation"
+                                       }
+                               }
+                       }
+               },
+               "/user/createWithArray": {
+                       "post": {
+                               "tags": [
+                                       "user"
+                               ],
+                               "summary": "Creates list of users with given 
input array",
+                               "description": "",
+                               "operationId": "createUsersWithArrayInput",
+                               "produces": [
+                                       "application/xml",
+                                       "application/json"
+                               ],
+                               "parameters": [
+                                       {
+                                               "in": "body",
+                                               "name": "body",
+                                               "description": "List of user 
object",
+                                               "required": true,
+                                               "schema": {
+                                                       "type": "array",
+                                                       "items": {
+                                                               "$ref": 
"#/definitions/User"
+                                                       }
+                                               }
+                                       }
+                               ],
+                               "responses": {
+                                       "default": {
+                                               "description": "successful 
operation"
+                                       }
+                               }
+                       }
+               },
+               "/user/createWithList": {
+                       "post": {
+                               "tags": [
+                                       "user"
+                               ],
+                               "summary": "Creates list of users with given 
input array",
+                               "description": "",
+                               "operationId": "createUsersWithListInput",
+                               "produces": [
+                                       "application/xml",
+                                       "application/json"
+                               ],
+                               "parameters": [
+                                       {
+                                               "in": "body",
+                                               "name": "body",
+                                               "description": "List of user 
object",
+                                               "required": true,
+                                               "schema": {
+                                                       "type": "array",
+                                                       "items": {
+                                                               "$ref": 
"#/definitions/User"
+                                                       }
+                                               }
+                                       }
+                               ],
+                               "responses": {
+                                       "default": {
+                                               "description": "successful 
operation"
+                                       }
+                               }
+                       }
+               },
+               "/user/login": {
+                       "get": {
+                               "tags": [
+                                       "user"
+                               ],
+                               "summary": "Logs user into the system",
+                               "description": "",
+                               "operationId": "loginUser",
+                               "produces": [
+                                       "application/xml",
+                                       "application/json"
+                               ],
+                               "parameters": [
+                                       {
+                                               "name": "username",
+                                               "in": "query",
+                                               "description": "The user name 
for login",
+                                               "required": true,
+                                               "type": "string"
+                                       },
+                                       {
+                                               "name": "password",
+                                               "in": "query",
+                                               "description": "The password 
for login in clear text",
+                                               "required": true,
+                                               "type": "string"
+                                       }
+                               ],
+                               "responses": {
+                                       "200": {
+                                               "description": "successful 
operation",
+                                               "schema": {
+                                                       "type": "string"
+                                               },
+                                               "headers": {
+                                                       "X-Rate-Limit": {
+                                                               "type": 
"integer",
+                                                               "format": 
"int32",
+                                                               "description": 
"calls per hour allowed by the user"
+                                                       },
+                                                       "X-Expires-After": {
+                                                               "type": 
"string",
+                                                               "format": 
"date-time",
+                                                               "description": 
"date in UTC when token expires"
+                                                       }
+                                               }
+                                       },
+                                       "400": {
+                                               "description": "Invalid 
username/password supplied"
+                                       }
+                               }
+                       }
+               },
+               "/user/logout": {
+                       "get": {
+                               "tags": [
+                                       "user"
+                               ],
+                               "summary": "Logs out current logged in user 
session",
+                               "description": "",
+                               "operationId": "logoutUser",
+                               "produces": [
+                                       "application/xml",
+                                       "application/json"
+                               ],
+                               "parameters": [],
+                               "responses": {
+                                       "default": {
+                                               "description": "successful 
operation"
+                                       }
+                               }
+                       }
+               },
+               "/user/{username}": {
+                       "get": {
+                               "tags": [
+                                       "user"
+                               ],
+                               "summary": "Get user by user name",
+                               "description": "",
+                               "operationId": "getUserByName",
+                               "produces": [
+                                       "application/xml",
+                                       "application/json"
+                               ],
+                               "parameters": [
+                                       {
+                                               "name": "username",
+                                               "in": "path",
+                                               "description": "The name that 
needs to be fetched. Use user1 for testing. ",
+                                               "required": true,
+                                               "type": "string"
+                                       }
+                               ],
+                               "responses": {
+                                       "200": {
+                                               "description": "successful 
operation",
+                                               "schema": {
+                                                       "$ref": 
"#/definitions/User"
+                                               }
+                                       },
+                                       "400": {
+                                               "description": "Invalid 
username supplied"
+                                       },
+                                       "404": {
+                                               "description": "User not found"
+                                       }
+                               }
+                       },
+                       "put": {
+                               "tags": [
+                                       "user"
+                               ],
+                               "summary": "Updated user",
+                               "description": "This can only be done by the 
logged in user.",
+                               "operationId": "updateUser",
+                               "produces": [
+                                       "application/xml",
+                                       "application/json"
+                               ],
+                               "parameters": [
+                                       {
+                                               "name": "username",
+                                               "in": "path",
+                                               "description": "name that need 
to be updated",
+                                               "required": true,
+                                               "type": "string"
+                                       },
+                                       {
+                                               "in": "body",
+                                               "name": "body",
+                                               "description": "Updated user 
object",
+                                               "required": true,
+                                               "schema": {
+                                                       "$ref": 
"#/definitions/User"
+                                               }
+                                       }
+                               ],
+                               "responses": {
+                                       "400": {
+                                               "description": "Invalid user 
supplied"
+                                       },
+                                       "404": {
+                                               "description": "User not found"
+                                       }
+                               }
+                       },
+                       "delete": {
+                               "tags": [
+                                       "user"
+                               ],
+                               "summary": "Delete user",
+                               "description": "This can only be done by the 
logged in user.",
+                               "operationId": "deleteUser",
+                               "produces": [
+                                       "application/xml",
+                                       "application/json"
+                               ],
+                               "parameters": [
+                                       {
+                                               "name": "username",
+                                               "in": "path",
+                                               "description": "The name that 
needs to be deleted",
+                                               "required": true,
+                                               "type": "string"
+                                       }
+                               ],
+                               "responses": {
+                                       "400": {
+                                               "description": "Invalid 
username supplied"
+                                       },
+                                       "404": {
+                                               "description": "User not found"
+                                       }
+                               }
+                       }
+               }
+       },
+       "securityDefinitions": {
+               "petstore_auth": {
+                       "type": "oauth2",
+                       "authorizationUrl": 
"http://petstore.swagger.io/oauth/dialog";,
+                       "flow": "implicit",
+                       "scopes": {
+                               "write:pets": "modify pets in your account",
+                               "read:pets": "read your pets"
+                       }
+               },
+               "api_key": {
+                       "type": "apiKey",
+                       "name": "api_key",
+                       "in": "header"
+               }
+       },
+       "definitions": {
+               "Order": {
+                       "type": "object",
+                       "properties": {
+                               "id": {
+                                       "type": "integer",
+                                       "format": "int64"
+                               },
+                               "petId": {
+                                       "type": "integer",
+                                       "format": "int64"
+                               },
+                               "quantity": {
+                                       "type": "integer",
+                                       "format": "int32"
+                               },
+                               "shipDate": {
+                                       "type": "string",
+                                       "format": "date-time"
+                               },
+                               "status": {
+                                       "type": "string",
+                                       "description": "Order Status",
+                                       "enum": [
+                                               "placed",
+                                               "approved",
+                                               "delivered"
+                                       ]
+                               },
+                               "complete": {
+                                       "type": "boolean",
+                                       "default": false
+                               }
+                       },
+                       "xml": {
+                               "name": "Order"
+                       }
+               },
+               "User": {
+                       "type": "object",
+                       "properties": {
+                               "id": {
+                                       "type": "integer",
+                                       "format": "int64"
+                               },
+                               "username": {
+                                       "type": "string"
+                               },
+                               "firstName": {
+                                       "type": "string"
+                               },
+                               "lastName": {
+                                       "type": "string"
+                               },
+                               "email": {
+                                       "type": "string"
+                               },
+                               "password": {
+                                       "type": "string"
+                               },
+                               "phone": {
+                                       "type": "string"
+                               },
+                               "userStatus": {
+                                       "type": "integer",
+                                       "format": "int32",
+                                       "description": "User Status"
+                               }
+                       },
+                       "xml": {
+                               "name": "User"
+                       }
+               },
+               "Category": {
+                       "type": "object",
+                       "properties": {
+                               "id": {
+                                       "type": "integer",
+                                       "format": "int64"
+                               },
+                               "name": {
+                                       "type": "string"
+                               }
+                       },
+                       "xml": {
+                               "name": "Category"
+                       }
+               },
+               "Tag": {
+                       "type": "object",
+                       "properties": {
+                               "id": {
+                                       "type": "integer",
+                                       "format": "int64"
+                               },
+                               "name": {
+                                       "type": "string"
+                               }
+                       },
+                       "xml": {
+                               "name": "Tag"
+                       }
+               },
+               "Pet": {
+                       "type": "object",
+                       "required": [
+                               "name",
+                               "photoUrls"
+                       ],
+                       "properties": {
+                               "id": {
+                                       "type": "integer",
+                                       "format": "int64"
+                               },
+                               "category": {
+                                       "$ref": "#/definitions/Category"
+                               },
+                               "name": {
+                                       "type": "string",
+                                       "example": "doggie"
+                               },
+                               "photoUrls": {
+                                       "type": "array",
+                                       "xml": {
+                                               "name": "photoUrl",
+                                               "wrapped": true
+                                       },
+                                       "items": {
+                                               "type": "string"
+                                       }
+                               },
+                               "tags": {
+                                       "type": "array",
+                                       "xml": {
+                                               "name": "tag",
+                                               "wrapped": true
+                                       },
+                                       "items": {
+                                               "$ref": "#/definitions/Tag"
+                                       }
+                               },
+                               "status": {
+                                       "type": "string",
+                                       "description": "pet status in the 
store",
+                                       "enum": [
+                                               "available",
+                                               "pending",
+                                               "sold"
+                                       ]
+                               }
+                       },
+                       "xml": {
+                               "name": "Pet"
+                       },
+                       "x-examples": {
+                               "model": "{foo:}",
+                               "application/json": "{foo:'bar'}",
+                               "text/xml": "<foo>bar</foo>",
+                               "text/html": "<table>foo</table>",
+                               "octal-messagepack": "123456ABCDEF"
+                       },
+               },
+               "ApiResponse": {
+                       "type": "object",
+                       "properties": {
+                               "code": {
+                                       "type": "integer",
+                                       "format": "int32"
+                               },
+                               "type": {
+                                       "type": "string"
+                               },
+                               "message": {
+                                       "type": "string"
+                               }
+                       }
+               }
+       },
+       "externalDocs": {
+               "description": "Find out more about Swagger",
+               "url": "http://swagger.io";
+       }
+}
\ No newline at end of file
diff --git 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestContext.java
 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestContext.java
index 73cb895..f2be599 100644
--- 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestContext.java
+++ 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestContext.java
@@ -3534,7 +3534,7 @@ public final class RestContext extends BeanContext {
                                                return p.parse(in, c);
                                        }
                                } catch (ParseException e) {
-                                       throw new ServletException("Could not 
parse resource '' as media type '"+mediaType+"'.");
+                                       throw new ServletException("Could not 
parse resource '"+name+" as media type '"+mediaType+"'.", e);
                                }
                        }
                        throw new ServletException("Unknown media type 
'"+mediaType+"'");

-- 
To stop receiving notification emails like this one, please contact
[email protected].

Reply via email to