You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@juneau.apache.org by ja...@apache.org on 2018/10/18 20:51:59 UTC

[juneau] branch master updated: Backward compatibility changes with 7.2.0

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 a23fee4  Backward compatibility changes with 7.2.0
a23fee4 is described below

commit a23fee47bb9726c3349ea2e9fa2304ff874023ee
Author: JamesBognar <ja...@apache.org>
AuthorDate: Thu Oct 18 16:51:45 2018 -0400

    Backward compatibility changes with 7.2.0
---
 .../http/annotation/AnnotationUtilsTest.java       |   5 +-
 .../juneau/httppart/HttpPartSchemaTest_Body.java   |   4 +-
 .../httppart/HttpPartSchemaTest_FormData.java      |   3 +-
 .../juneau/httppart/HttpPartSchemaTest_Header.java |   3 +-
 .../juneau/httppart/HttpPartSchemaTest_Path.java   |   3 +-
 .../juneau/httppart/HttpPartSchemaTest_Query.java  |   3 +-
 .../httppart/HttpPartSchemaTest_Response.java      |   4 +-
 .../HttpPartSchemaTest_ResponseHeader.java         |   3 +-
 juneau-core/juneau-marshall/pom.xml                |  10 +
 .../org/apache/juneau/http/HeaderStringArray.java  |   2 +-
 .../juneau/http/annotation/AnnotationUtils.java    |  80 ++-
 .../org/apache/juneau/http/annotation/Body.java    |   2 +-
 .../annotation/{Tag.java => ExternalDocs.java}     | 334 ++++------
 .../apache/juneau/http/annotation/FormData.java    |   2 +-
 .../org/apache/juneau/http/annotation/Header.java  |   2 +-
 .../org/apache/juneau/http/annotation/Items.java   | 364 +++++++++++
 .../org/apache/juneau/http/annotation/Path.java    |   2 +-
 .../org/apache/juneau/http/annotation/Query.java   |   2 +-
 .../apache/juneau/http/annotation/Response.java    |   2 +-
 .../juneau/http/annotation/ResponseHeader.java     |   2 +-
 .../org/apache/juneau/http/annotation/Schema.java  | 703 +++++++++++++++++++++
 .../apache/juneau/http/annotation/SubItems.java    | 368 +++++++++++
 .../org/apache/juneau/http/annotation/Tag.java     |   2 +-
 .../juneau/httppart/HttpPartSchemaBuilder.java     |   4 +-
 .../apache/juneau/json/SimpleJsonSerializer.java   |   4 +-
 .../juneau/jsonschema/annotation/JsonSchema.java   |  47 +-
 .../juneau/examples/rest/AtomFeedResource.java     |   2 +-
 .../examples/rest/CodeFormatterResource.java       |   2 +-
 .../examples/rest/DockerRegistryResource.java      |   2 +-
 .../juneau/examples/rest/JsonSchemaResource.java   |   2 +-
 .../examples/rest/MethodExampleResource.java       |   2 +-
 .../juneau/examples/rest/PhotosResource.java       |   2 +-
 .../examples/rest/PredefinedLabelsResource.java    |   2 +-
 .../juneau/examples/rest/RequestEchoResource.java  |   2 +-
 .../juneau/examples/rest/SampleRrpcServlet.java    |   2 +-
 .../juneau/examples/rest/SqlQueryResource.java     |   2 +-
 .../examples/rest/SystemPropertiesResource.java    |   2 +-
 .../juneau/examples/rest/TempDirResource.java      |   2 +-
 .../examples/rest/UrlEncodedFormResource.java      |   2 +-
 .../rest/addressbook/AddressBookResource.java      |   2 +-
 .../juneau/examples/rest/petstore/PetStore.java    |   2 +-
 .../examples/rest/petstore/PetStoreResource.java   |   2 +-
 .../org/apache/juneau/rest/client/RestClient.java  |  26 +
 .../rest/client/remote/EndToEndInterfaceTest.java  |   3 +-
 .../org/apache/juneau/rest/SwaggerGenerator.java   |   6 +-
 .../juneau/rest/annotation/ResourceSwagger.java    |   2 +-
 .../apache/juneau/rest/helper/ReaderResource.java  | 150 +++++
 .../juneau/rest/helper/ReaderResourceBuilder.java  | 123 ++++
 .../rest/helper/ResolvingReaderResource.java       |   1 +
 .../juneau/rest/helper/ResourceDescription.java    |   2 +-
 .../apache/juneau/rest/helper/StreamResource.java  | 114 ++++
 .../juneau/rest/helper/StreamResourceBuilder.java  | 111 ++++
 .../juneau/rest/remote/RemoteInterfaceServlet.java | 230 +++++++
 .../juneau/rest/util/FinishablePrintWriter.java    |   8 +
 .../juneau/rest/BasicRestInfoProviderTest.java     |   3 +-
 .../rest/annotation2/ResponseAnnotationTest.java   |   2 +-
 pom.xml                                            |   2 +-
 57 files changed, 2505 insertions(+), 270 deletions(-)

diff --git a/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/http/annotation/AnnotationUtilsTest.java b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/http/annotation/AnnotationUtilsTest.java
index 67b5305..9a5aea9 100644
--- a/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/http/annotation/AnnotationUtilsTest.java
+++ b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/http/annotation/AnnotationUtilsTest.java
@@ -17,10 +17,13 @@ import static java.lang.annotation.ElementType.*;
 import static java.lang.annotation.RetentionPolicy.*;
 import static org.apache.juneau.http.annotation.AnnotationUtils.*;
 
+import org.apache.juneau.jsonschema.annotation.ExternalDocs;
+import org.apache.juneau.jsonschema.annotation.Schema;
+import org.apache.juneau.jsonschema.annotation.SubItems;
+import org.apache.juneau.jsonschema.annotation.Items;
 import java.lang.annotation.*;
 import java.lang.reflect.*;
 
-import org.apache.juneau.jsonschema.annotation.*;
 import org.junit.*;
 import org.junit.runners.*;
 
diff --git a/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/httppart/HttpPartSchemaTest_Body.java b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/httppart/HttpPartSchemaTest_Body.java
index 5ad6414..957afa5 100644
--- a/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/httppart/HttpPartSchemaTest_Body.java
+++ b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/httppart/HttpPartSchemaTest_Body.java
@@ -19,7 +19,9 @@ import static org.apache.juneau.internal.StringUtils.*;
 
 import org.apache.juneau.*;
 import org.apache.juneau.http.annotation.*;
-import org.apache.juneau.jsonschema.annotation.*;
+import org.apache.juneau.jsonschema.annotation.Items;
+import org.apache.juneau.jsonschema.annotation.Schema;
+import org.apache.juneau.jsonschema.annotation.SubItems;
 import org.apache.juneau.utils.*;
 import org.junit.*;
 import org.junit.runners.*;
diff --git a/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/httppart/HttpPartSchemaTest_FormData.java b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/httppart/HttpPartSchemaTest_FormData.java
index f829e56..da5f888 100644
--- a/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/httppart/HttpPartSchemaTest_FormData.java
+++ b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/httppart/HttpPartSchemaTest_FormData.java
@@ -19,7 +19,8 @@ import static org.apache.juneau.internal.StringUtils.*;
 
 import org.apache.juneau.*;
 import org.apache.juneau.http.annotation.*;
-import org.apache.juneau.jsonschema.annotation.*;
+import org.apache.juneau.jsonschema.annotation.Items;
+import org.apache.juneau.jsonschema.annotation.SubItems;
 import org.apache.juneau.utils.*;
 import org.junit.*;
 import org.junit.runners.*;
diff --git a/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/httppart/HttpPartSchemaTest_Header.java b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/httppart/HttpPartSchemaTest_Header.java
index d4333bb..c09e087 100644
--- a/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/httppart/HttpPartSchemaTest_Header.java
+++ b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/httppart/HttpPartSchemaTest_Header.java
@@ -19,7 +19,8 @@ import static org.apache.juneau.internal.StringUtils.*;
 
 import org.apache.juneau.*;
 import org.apache.juneau.http.annotation.*;
-import org.apache.juneau.jsonschema.annotation.*;
+import org.apache.juneau.jsonschema.annotation.Items;
+import org.apache.juneau.jsonschema.annotation.SubItems;
 import org.apache.juneau.utils.*;
 import org.junit.*;
 import org.junit.runners.*;
diff --git a/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/httppart/HttpPartSchemaTest_Path.java b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/httppart/HttpPartSchemaTest_Path.java
index 0d05063..97c4e9d 100644
--- a/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/httppart/HttpPartSchemaTest_Path.java
+++ b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/httppart/HttpPartSchemaTest_Path.java
@@ -19,7 +19,8 @@ import static org.apache.juneau.internal.StringUtils.*;
 
 import org.apache.juneau.*;
 import org.apache.juneau.http.annotation.*;
-import org.apache.juneau.jsonschema.annotation.*;
+import org.apache.juneau.jsonschema.annotation.Items;
+import org.apache.juneau.jsonschema.annotation.SubItems;
 import org.apache.juneau.utils.*;
 import org.junit.*;
 import org.junit.runners.*;
diff --git a/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/httppart/HttpPartSchemaTest_Query.java b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/httppart/HttpPartSchemaTest_Query.java
index 7424e8d..e66ba38 100644
--- a/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/httppart/HttpPartSchemaTest_Query.java
+++ b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/httppart/HttpPartSchemaTest_Query.java
@@ -19,7 +19,8 @@ import static org.apache.juneau.internal.StringUtils.*;
 
 import org.apache.juneau.*;
 import org.apache.juneau.http.annotation.*;
-import org.apache.juneau.jsonschema.annotation.*;
+import org.apache.juneau.jsonschema.annotation.Items;
+import org.apache.juneau.jsonschema.annotation.SubItems;
 import org.apache.juneau.utils.*;
 import org.junit.*;
 import org.junit.runners.*;
diff --git a/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/httppart/HttpPartSchemaTest_Response.java b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/httppart/HttpPartSchemaTest_Response.java
index b91d1c5..4b51b6b 100644
--- a/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/httppart/HttpPartSchemaTest_Response.java
+++ b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/httppart/HttpPartSchemaTest_Response.java
@@ -19,7 +19,9 @@ import static org.junit.Assert.assertEquals;
 
 import org.apache.juneau.*;
 import org.apache.juneau.http.annotation.*;
-import org.apache.juneau.jsonschema.annotation.*;
+import org.apache.juneau.jsonschema.annotation.Items;
+import org.apache.juneau.jsonschema.annotation.Schema;
+import org.apache.juneau.jsonschema.annotation.SubItems;
 import org.apache.juneau.utils.*;
 import org.junit.*;
 import org.junit.runners.*;
diff --git a/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/httppart/HttpPartSchemaTest_ResponseHeader.java b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/httppart/HttpPartSchemaTest_ResponseHeader.java
index d31cb41..8787e83 100644
--- a/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/httppart/HttpPartSchemaTest_ResponseHeader.java
+++ b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/httppart/HttpPartSchemaTest_ResponseHeader.java
@@ -19,7 +19,8 @@ import static org.junit.Assert.assertEquals;
 
 import org.apache.juneau.*;
 import org.apache.juneau.http.annotation.*;
-import org.apache.juneau.jsonschema.annotation.*;
+import org.apache.juneau.jsonschema.annotation.Items;
+import org.apache.juneau.jsonschema.annotation.SubItems;
 import org.apache.juneau.utils.*;
 import org.junit.*;
 import org.junit.runners.*;
diff --git a/juneau-core/juneau-marshall/pom.xml b/juneau-core/juneau-marshall/pom.xml
index b81cf3e..b4938b6 100644
--- a/juneau-core/juneau-marshall/pom.xml
+++ b/juneau-core/juneau-marshall/pom.xml
@@ -127,6 +127,16 @@
 								<compatibilityChange>FIELD_REMOVED_IN_SUPERCLASS</compatibilityChange>
 								<sourceCompatible>true</sourceCompatible>
 							</overrideCompatibilityChangeParameter>
+							<overrideCompatibilityChangeParameter>
+								<binaryCompatible>true</binaryCompatible>
+								<compatibilityChange>METHOD_RETURN_TYPE_CHANGED</compatibilityChange>
+								<sourceCompatible>true</sourceCompatible>
+							</overrideCompatibilityChangeParameter>
+							<overrideCompatibilityChangeParameter>
+								<binaryCompatible>true</binaryCompatible>
+								<compatibilityChange>FIELD_TYPE_CHANGED</compatibilityChange>
+								<sourceCompatible>true</sourceCompatible>
+							</overrideCompatibilityChangeParameter>
 						</overrideCompatibilityChangeParameters>
 					</parameter>
 				</configuration>
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/HeaderStringArray.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/HeaderStringArray.java
index d9d66b6..ae78847 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/HeaderStringArray.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/HeaderStringArray.java
@@ -14,7 +14,7 @@ package org.apache.juneau.http;
 
 import org.apache.juneau.http.annotation.*;
 import org.apache.juneau.internal.*;
-import org.apache.juneau.jsonschema.annotation.*;
+import org.apache.juneau.jsonschema.annotation.Items;
 
 /**
  * Category of headers that consist of a comma-delimited list of string values.
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/AnnotationUtils.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/AnnotationUtils.java
index 16ff4a3..546a4ee 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/AnnotationUtils.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/AnnotationUtils.java
@@ -12,8 +12,6 @@
 // ***************************************************************************************************************************
 package org.apache.juneau.http.annotation;
 
-import org.apache.juneau.jsonschema.annotation.*;
-
 /**
  * Various reusable utility methods when working with annotations.
  */
@@ -113,7 +111,27 @@ public class AnnotationUtils {
 	 * @param a The annotation to check.
 	 * @return <jk>true</jk> if the specified annotation contains all default values.
 	 */
-	public static boolean empty(Schema a) {
+	public static boolean empty(org.apache.juneau.jsonschema.annotation.Schema a) {
+		if (a == null)
+			return true;
+		return
+			allEmpty(a.value(), a.description(), a._default(), a._enum(), a.allOf(), a.properties(), a.additionalProperties(), a.xml(), a.example(), a.examples())
+			&& allEmpty(a.$ref(), a.format(), a.title(), a.multipleOf(), a.maximum(), a.minimum(), a.pattern(), a.type(), a.discriminator())
+			&& allMinusOne(a.maxProperties(), a.minProperties())
+			&& allFalse(a.ignore(), a.exclusiveMaximum(), a.exclusiveMinimum(), a.readOnly(), a.required(), a.uniqueItems())
+			&& allMinusOne(a.maxLength(), a.minLength(), a.maxItems(), a.minItems())
+			&& empty(a.items())
+			&& empty(a.externalDocs());
+	}
+
+	/**
+	 * Returns <jk>true</jk> if the specified annotation contains all default values.
+	 *
+	 * @param a The annotation to check.
+	 * @return <jk>true</jk> if the specified annotation contains all default values.
+	 */
+	@Deprecated
+	public static boolean empty(org.apache.juneau.http.annotation.Schema a) {
 		if (a == null)
 			return true;
 		return
@@ -132,7 +150,22 @@ public class AnnotationUtils {
 	 * @param a The annotation to check.
 	 * @return <jk>true</jk> if the specified annotation contains all default values.
 	 */
-	public static boolean empty(ExternalDocs a) {
+	public static boolean empty(org.apache.juneau.jsonschema.annotation.ExternalDocs a) {
+		if (a == null)
+			return true;
+		return
+			allEmpty(a.value(), a.description())
+			&& allEmpty(a.url());
+	}
+
+	/**
+	 * Returns <jk>true</jk> if the specified annotation contains all default values.
+	 *
+	 * @param a The annotation to check.
+	 * @return <jk>true</jk> if the specified annotation contains all default values.
+	 */
+	@Deprecated
+	public static boolean empty(org.apache.juneau.http.annotation.ExternalDocs a) {
 		if (a == null)
 			return true;
 		return
@@ -189,7 +222,7 @@ public class AnnotationUtils {
 	 * @param a The annotation to check.
 	 * @return <jk>true</jk> if the specified annotation contains all default values.
 	 */
-	public static boolean empty(Items a) {
+	public static boolean empty(org.apache.juneau.jsonschema.annotation.Items a) {
 		if (a == null)
 			return true;
 		return
@@ -206,7 +239,42 @@ public class AnnotationUtils {
 	 * @param a The annotation to check.
 	 * @return <jk>true</jk> if the specified annotation contains all default values.
 	 */
-	public static boolean empty(SubItems a) {
+	@Deprecated
+	public static boolean empty(org.apache.juneau.http.annotation.Items a) {
+		if (a == null)
+			return true;
+		return
+			allEmpty(a.value(), a._default(), a._enum())
+			&& allEmpty(a.type(), a.format(), a.collectionFormat(), a.pattern(), a.$ref(), a.maximum(), a.minimum(), a.multipleOf())
+			&& allFalse(a.exclusiveMaximum(), a.exclusiveMinimum(), a.uniqueItems())
+			&& allMinusOne(a.maxLength(), a.minLength(), a.maxItems(), a.minItems())
+			&& empty(a.items());
+	}
+
+	/**
+	 * Returns <jk>true</jk> if the specified annotation contains all default values.
+	 *
+	 * @param a The annotation to check.
+	 * @return <jk>true</jk> if the specified annotation contains all default values.
+	 */
+	public static boolean empty(org.apache.juneau.jsonschema.annotation.SubItems a) {
+		if (a == null)
+			return true;
+		return
+			allEmpty(a.value(), a._default(), a._enum(), a.items())
+			&& allEmpty(a.type(), a.format(), a.collectionFormat(), a.pattern(), a.$ref(), a.maximum(), a.minimum(), a.multipleOf())
+			&& allFalse(a.exclusiveMaximum(), a.exclusiveMinimum(), a.uniqueItems())
+			&& allMinusOne(a.maxLength(), a.minLength(), a.maxItems(), a.minItems());
+	}
+
+	/**
+	 * Returns <jk>true</jk> if the specified annotation contains all default values.
+	 *
+	 * @param a The annotation to check.
+	 * @return <jk>true</jk> if the specified annotation contains all default values.
+	 */
+	@Deprecated
+	public static boolean empty(org.apache.juneau.http.annotation.SubItems a) {
 		if (a == null)
 			return true;
 		return
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/Body.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/Body.java
index 10d8f8b..dd2d831 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/Body.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/Body.java
@@ -17,12 +17,12 @@ import static java.lang.annotation.RetentionPolicy.*;
 
 import java.lang.annotation.*;
 
+import org.apache.juneau.jsonschema.annotation.Schema;
 import org.apache.juneau.*;
 import org.apache.juneau.annotation.*;
 import org.apache.juneau.httppart.*;
 import org.apache.juneau.json.*;
 import org.apache.juneau.jsonschema.*;
-import org.apache.juneau.jsonschema.annotation.*;
 
 /**
  * REST request body annotation.
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/Tag.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/ExternalDocs.java
similarity index 53%
copy from juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/Tag.java
copy to juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/ExternalDocs.java
index 8617c24..0ae57db 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/Tag.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/ExternalDocs.java
@@ -1,197 +1,137 @@
-// ***************************************************************************************************************************
-// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
-// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
-// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
-// * with the License.  You may obtain a copy of the License at                                                              *
-// *                                                                                                                         *
-// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
-// *                                                                                                                         *
-// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
-// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
-// * specific language governing permissions and limitations under the License.                                              *
-// ***************************************************************************************************************************
-package org.apache.juneau.http.annotation;
-
-import static java.lang.annotation.RetentionPolicy.*;
-
-import java.lang.annotation.*;
-
-import org.apache.juneau.jsonschema.annotation.*;
-
-/**
- * Swagger tag annotation.
- *
- * <p>
- * Allows adding meta data to a single tag that is used by the {@doc SwaggerOperationObject}.
- * It is not mandatory to have a Tag Object per tag used there.
- *
- * <p>
- * Used to populate the auto-generated Swagger documentation and UI for server-side <ja>@RestResource</ja>-annotated classes.
- *
- * <h5 class='section'>Examples:</h5>
- * <p class='bcode w800'>
- * 	<jc>// A response object thats a hex-encoded string</jc>
- * 	<ja>@RestResource</ja>(
- * 		swagger={
- * 			tags={
- * 				<ja>@Tag</ja>(
- * 					name=<js>"utility"</js>,
- * 					description=<js>"Utility methods"</js>
- * 				)
- * 			}
- * 		}
- * 	)
- * </p>
- * <p class='bcode w800'>
- * 	<jc>// Free-form</jc>
- * 	<ja>@RestResource</ja>(
- * 		swagger={
- * 			tags={
- * 				<ja>@Tag</ja>({
- * 					<js>"name:'utility',"</js>,
- * 					<js>"description:'Utility methods'"</js>
- * 				})
- * 			}
- * 		}
- * 	)
- * </p>
- *
- * <h5 class='section'>See Also:</h5>
- * <ul>
- * 	<li class='link'>{@doc juneau-rest-server.Swagger}
- * 	<li class='extlink'>{@doc SwaggerTagObject}
- * </ul>
- */
-@Documented
-@Retention(RUNTIME)
-public @interface Tag {
-
-	/**
-	 * <mk>name</mk> field of the {@doc SwaggerTagObject}.
-	 *
-	 * <h5 class='section'>Notes:</h5>
-	 * <ul class='spaced-list'>
-	 * 	<li>
-	 * 		The format is plain text.
-	 * </ul>
-	 */
-	String name() default "";
-
-	/**
-	 * <mk>description</mk> field of the {@doc SwaggerTagObject}.
-	 *
-	 * <h5 class='section'>Notes:</h5>
-	 * <ul class='spaced-list'>
-	 * 	<li>
-	 * 		The format is a {@doc juneau-marshall.JsonDetails.SimplifiedJson} object.
-	 * 		<br>Multiple lines are concatenated with newlines.
-	 * 	<li>
-	 * 		Supports {@doc DefaultRestSvlVariables}
-	 * 		(e.g. <js>"$L{my.localized.variable}"</js>).
-	 * </ul>
-	 */
-	String[] description() default {};
-
-	/**
-	 * <mk>externalDocs</mk> field of the {@doc SwaggerTagObject}.
-	 *
-	 * <h5 class='section'>Notes:</h5>
-	 * <ul class='spaced-list'>
-	 * 	<li>
-	 * 		The format is a {@doc juneau-marshall.JsonDetails.SimplifiedJson} object.
-	 * 		<br>Multiple lines are concatenated with newlines.
-	 * 	<li>
-	 * 		Supports {@doc DefaultRestSvlVariables}
-	 * 		(e.g. <js>"$L{my.localized.variable}"</js>).
-	 * </ul>
-	 */
-	ExternalDocs externalDocs() default @ExternalDocs;
-
-	/**
-	 * Free-form value for the {@doc SwaggerTagObject}.
-	 *
-	 * <p>
-	 * This is a {@doc juneau-marshall.JsonDetails.SimplifiedJson} object that makes up the swagger information for this Tag object.
-	 *
-	 * <p>
-	 * The following are completely equivalent ways of defining the swagger description of the resource tags:
-	 * <p class='bcode w800'>
-	 * 	<jc>// Normal</jc>
-	 * 	<ja>@RestResource</ja>(
-	 * 		tags={
-	 * 			<ja>@Tag</ja>(
-	 * 				name=<js>"pet"</js>,
-	 * 				description=<js>"Everything about your Pets"</js>,
-	 * 				externalDocs=<ja>@ExternalDocs</ja>(
-	 * 					description="<js>Find out more"</js>,
-	 * 					url=<js>"http://juneau.apache.org"</js>
-	 * 				}
-	 * 			)
-	 * 		}
-	 * 	)
-	 * </p>
-	 * <p class='bcode w800'>
-	 * 	<jc>// Free-form</jc>
-	 * 	<ja>@RestResource</ja>(
-	 * 		tags={
-	 * 			<ja>@Tag</ja>(
-	 * 				name=<js>"pet"</js>,
-	 * 				api={
-	 * 					<js>"name: 'pet',"</js>,
-	 * 					<js>"description: 'Everything about your Pets',"</js>,
-	 * 					<js>"externalDocs: {"</js>,
-	 * 						<js>"description: 'Find out more',"</js>,
-	 * 						<js>"url: 'http://juneau.apache.org'"</js>
-	 * 					<js>"}"</js>
-	 * 				}
-	 * 			)
-	 * 		}
-	 * 	)
-	 * </p>
-	 * <p class='bcode w800'>
-	 * 	<jc>// Free-form with variables</jc>
-	 * 	<ja>@RestResource</ja>(
-	 * 		tags={
-	 * 			<ja>@Tag</ja>(
-	 * 				name=<js>"pet"</js>,
-	 * 				api=<js>"$L{petTagSwagger}"</js>
-	 * 			)
-	 * 		}
-	 * 	)
-	 * </p>
-	 * <p class='bcode w800'>
-	 * 	<mc>// Contents of MyResource.properties</mc>
-	 * 	<mk>petTagSwagger</mk> = <mv>{ name: "pet", description: "Everything about your Pets", externalDocs: { description: "Find out more", url: "http://juneau.apache.org" } }</mv>
-	 * </p>
-	 *
-	 * <p>
-	 * 	The reasons why you may want to use this field include:
-	 * <ul>
-	 * 	<li>You want to pull in the entire Swagger JSON definition for this body from an external source such as a properties file.
-	 * 	<li>You want to add extra fields to the Swagger documentation that are not officially part of the Swagger specification.
-	 * </ul>
-	 *
-	 * <h5 class='section'>Notes:</h5>
-	 * <ul class='spaced-list'>
-	 * 	<li>
-	 * 		The format is a {@doc juneau-marshall.JsonDetails.SimplifiedJson} object.
-	 * 	<li>
-	 * 		The leading/trailing <code>{ }</code> characters are optional.
-	 * 		<br>The following two example are considered equivalent:
-	 * 		<p class='bcode w800'>
-	 * 	<ja>@Tag</ja>(api=<js>"{description: 'Everything about your Pets'}"</js>)
-	 * 		</p>
-	 * 		<p class='bcode w800'>
-	 * 	<ja>@Tag</ja>(api=<js>"description: 'Everything about your Pets'"</js>)
-	 * 		</p>
-	 * 	<li>
-	 * 		Multiple lines are concatenated with newlines so that you can format the value to be readable:
-	 * 	<li>
-	 * 		Supports {@doc DefaultRestSvlVariables}
-	 * 		(e.g. <js>"$L{my.localized.variable}"</js>).
-	 * 	<li>
-	 * 		Values defined in this field supersede values pulled from the Swagger JSON file and are superseded by individual values defined on this annotation.
-	 * </ul>
-	 */
-	String[] value() default {};
-}
+// ***************************************************************************************************************************
+// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
+// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
+// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
+// * with the License.  You may obtain a copy of the License at                                                              *
+// *                                                                                                                         *
+// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
+// *                                                                                                                         *
+// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
+// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
+// * specific language governing permissions and limitations under the License.                                              *
+// ***************************************************************************************************************************
+package org.apache.juneau.http.annotation;
+
+import static java.lang.annotation.RetentionPolicy.*;
+
+import java.lang.annotation.*;
+
+/**
+ * @deprecated Use {@link org.apache.juneau.jsonschema.annotation.ExternalDocs}
+ */
+@Documented
+@Retention(RUNTIME)
+@Deprecated
+public @interface ExternalDocs {
+
+	/**
+	 * <mk>description</mk> field of the {@doc SwaggerExternalDocumentationObject}.
+	 *
+	 * <p>
+	 * A short description of the target documentation.
+	 *
+	 * <h5 class='section'>Notes:</h5>
+	 * <ul class='spaced-list'>
+	 * 	<li>
+	 * 		The format is a plain-text string.
+	 * 		<br>Multiple lines are concatenated with newlines.
+	 * 	<li>
+	 * 		Supports {@doc DefaultRestSvlVariables}
+	 * 		(e.g. <js>"$L{my.localized.variable}"</js>).
+	 * </ul>
+	 */
+	String[] description() default {};
+
+	/**
+	 * <mk>url</mk> field of the {@doc SwaggerExternalDocumentationObject}.
+	 *
+	 * <p>
+	 * The URL for the target documentation. Value MUST be in the format of a URL.
+	 *
+	 * <h5 class='section'>Notes:</h5>
+	 * <ul class='spaced-list'>
+	 * 	<li>
+	 * 		The value is required.
+	 * 	<li>
+	 * 		The format is a URL string.
+	 * 	<li>
+	 * 		Supports {@doc DefaultRestSvlVariables}
+	 * 		(e.g. <js>"$L{my.localized.variable}"</js>).
+	 * </ul>
+	 */
+	String url() default "";
+
+	/**
+	 * Free-form value for the {@doc SwaggerExternalDocumentationObject}.
+	 *
+	 * <p>
+	 * This is a {@doc juneau-marshall.JsonDetails.SimplifiedJson} object that makes up the swagger information for this field.
+	 *
+	 * <p>
+	 * The following are completely equivalent ways of defining the swagger description of documentation:
+	 * <p class='bcode w800'>
+	 * 	<jc>// Normal</jc>
+	 * 	<ja>@RestResource</ja>(
+	 * 		swagger=<ja>@ResourceSwagger</ja>(
+	 * 			externalDocs=<ja>@ExternalDocs</ja>(
+	 * 				description=<js>"Find out more about Juneau"</js>,
+	 * 				url=<js>"http://juneau.apache.org"</js>
+	 * 			)
+	 * 		)
+	 * 	)
+	 * </p>
+	 * <p class='bcode w800'>
+	 * 	<jc>// Free-form</jc>
+	 * 	<ja>@RestResource</ja>(
+	 * 		swagger=<ja>@ResourceSwagger</ja>(
+	 * 			externalDocs=<ja>@ExternalDocs</ja>({
+	 * 				<js>"description: 'Find out more about Juneau',"</js>,
+	 * 				<js>"url: 'http://juneau.apache.org'"</js>
+	 * 			})
+	 * 		)
+	 * 	)
+	 * </p>
+	 * <p class='bcode w800'>
+	 * 	<jc>// Free-form with variables</jc>
+	 * 	<ja>@RestResource</ja>(
+	 * 		swagger=<ja>@ResourceSwagger</ja>(
+	 * 			externalDocs=<ja>@ExternalDocs</ja>(<js>"$L{externalDocsSwagger}"</js>)
+	 * 		)
+	 * 	)
+	 * </p>
+	 * <p class='bcode w800'>
+	 * 	<mc>// Contents of MyResource.properties</mc>
+	 * 	<mk>externalDocsSwagger</mk> = <mv>{ description: "Find out more about Juneau", url: "http://juneau.apache.org" }</mv>
+	 * </p>
+	 *
+	 * <p>
+	 * 	The reasons why you may want to use this field include:
+	 * <ul>
+	 * 	<li>You want to pull in the entire Swagger JSON definition for this field from an external source such as a properties file.
+	 * 	<li>You want to add extra fields to the Swagger documentation that are not officially part of the Swagger specification.
+	 * </ul>
+	 *
+	 * <h5 class='section'>Notes:</h5>
+	 * <ul class='spaced-list'>
+	 * 	<li>
+	 * 		The format is a {@doc juneau-marshall.JsonDetails.SimplifiedJson} object.
+	 * 	<li>
+	 * 		The leading/trailing <code>{ }</code> characters are optional.
+	 * 		<br>The following two example are considered equivalent:
+	 * 		<p class='bcode w800'>
+	 * 	<ja>@ExternalDocs</ja>(<js>"{url:'http://juneau.apache.org'}"</js>)
+	 * 		</p>
+	 * 		<p class='bcode w800'>
+	 * 	<ja>@ExternalDocs</ja>(<js>"url:'http://juneau.apache.org'"</js>)
+	 * 		</p>
+	 * 	<li>
+	 * 		Multiple lines are concatenated with newlines so that you can format the value to be readable.
+	 * 	<li>
+	 * 		Supports {@doc DefaultRestSvlVariables}
+	 * 		(e.g. <js>"$L{my.localized.variable}"</js>).
+	 * 	<li>
+	 * 		Values defined in this field supersede values pulled from the Swagger JSON file and are superseded by individual values defined on this annotation.
+	 * </ul>
+	 */
+	String[] value() default {};
+}
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/FormData.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/FormData.java
index bb5d290..506ec6f 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/FormData.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/FormData.java
@@ -18,12 +18,12 @@ import static java.lang.annotation.RetentionPolicy.*;
 import java.lang.annotation.*;
 import java.util.*;
 
+import org.apache.juneau.jsonschema.annotation.Items;
 import org.apache.juneau.*;
 import org.apache.juneau.annotation.*;
 import org.apache.juneau.httppart.*;
 import org.apache.juneau.json.*;
 import org.apache.juneau.jsonschema.*;
-import org.apache.juneau.jsonschema.annotation.*;
 import org.apache.juneau.oapi.*;
 
 /**
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/Header.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/Header.java
index 55672fa..fec98b8 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/Header.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/Header.java
@@ -18,12 +18,12 @@ import static java.lang.annotation.RetentionPolicy.*;
 import java.lang.annotation.*;
 import java.util.*;
 
+import org.apache.juneau.jsonschema.annotation.Items;
 import org.apache.juneau.*;
 import org.apache.juneau.annotation.*;
 import org.apache.juneau.httppart.*;
 import org.apache.juneau.json.*;
 import org.apache.juneau.jsonschema.*;
-import org.apache.juneau.jsonschema.annotation.*;
 import org.apache.juneau.oapi.*;
 
 /**
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/Items.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/Items.java
new file mode 100644
index 0000000..c52d014
--- /dev/null
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/Items.java
@@ -0,0 +1,364 @@
+// ***************************************************************************************************************************
+// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
+// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
+// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
+// * with the License.  You may obtain a copy of the License at                                                              *
+// *                                                                                                                         *
+// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
+// *                                                                                                                         *
+// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
+// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
+// * specific language governing permissions and limitations under the License.                                              *
+// ***************************************************************************************************************************
+package org.apache.juneau.http.annotation;
+
+import static java.lang.annotation.RetentionPolicy.*;
+
+import java.lang.annotation.*;
+
+/**
+ * @deprecated Use {@link org.apache.juneau.jsonschema.annotation.Items}
+ */
+@Documented
+@Retention(RUNTIME)
+@Deprecated
+public @interface Items {
+
+	/**
+	 * <mk>type</mk> field of the {@doc SwaggerItemsObject}.
+	 *
+	 * <h5 class='section'>Notes:</h5>
+	 * <ul class='spaced-list'>
+	 * 	<li>
+	 * 		The format is a plain-text string.
+	 * 	<li>
+	 * 		Supports {@doc DefaultRestSvlVariables}
+	 * 		(e.g. <js>"$L{my.localized.variable}"</js>).
+	 * </ul>
+	 */
+	String type() default "";
+
+	/**
+	 * <mk>format</mk> field of the {@doc SwaggerItemsObject}.
+	 *
+	 * <h5 class='section'>Notes:</h5>
+	 * <ul class='spaced-list'>
+	 * 	<li>
+	 * 		The format is a plain-text string.
+	 * 	<li>
+	 * 		Supports {@doc DefaultRestSvlVariables}
+	 * 		(e.g. <js>"$L{my.localized.variable}"</js>).
+	 * </ul>
+	 */
+	String format() default "";
+
+	/**
+	 * <mk>collectionFormat</mk> field of the {@doc SwaggerItemsObject}.
+	 *
+	 * <h5 class='section'>Notes:</h5>
+	 * <ul class='spaced-list'>
+	 * 	<li>
+	 * 		The format is a plain-text string.
+	 * 	<li>
+	 * 		Supports {@doc DefaultRestSvlVariables}
+	 * 		(e.g. <js>"$L{my.localized.variable}"</js>).
+	 * </ul>
+	 */
+	String collectionFormat() default "";
+
+	/**
+	 * <mk>pattern</mk> field of the {@doc SwaggerItemsObject}.
+	 *
+	 * <h5 class='section'>Notes:</h5>
+	 * <ul class='spaced-list'>
+	 * 	<li>
+	 * 		The format is a plain-text string.
+	 * 	<li>
+	 * 		Supports {@doc DefaultRestSvlVariables}
+	 * 		(e.g. <js>"$L{my.localized.variable}"</js>).
+	 * </ul>
+	 */
+	String pattern() default "";
+
+	/**
+	 * <mk>maximum</mk> field of the {@doc SwaggerItemsObject}.
+	 *
+	 * <h5 class='section'>Notes:</h5>
+	 * <ul class='spaced-list'>
+	 * 	<li>
+	 * 		The format is a plain-text string.
+	 * 	<li>
+	 * 		Supports {@doc DefaultRestSvlVariables}
+	 * 		(e.g. <js>"$L{my.localized.variable}"</js>).
+	 * </ul>
+	 */
+	String maximum() default "";
+
+	/**
+	 * <mk>minimum</mk> field of the {@doc SwaggerItemsObject}.
+	 *
+	 * <h5 class='section'>Notes:</h5>
+	 * <ul class='spaced-list'>
+	 * 	<li>
+	 * 		The format is a plain-text string.
+	 * 	<li>
+	 * 		Supports {@doc DefaultRestSvlVariables}
+	 * 		(e.g. <js>"$L{my.localized.variable}"</js>).
+	 * </ul>
+	 */
+	String minimum() default "";
+
+	/**
+	 * <mk>multipleOf</mk> field of the {@doc SwaggerItemsObject}.
+	 *
+	 * <h5 class='section'>Notes:</h5>
+	 * <ul class='spaced-list'>
+	 * 	<li>
+	 * 		The format is a plain-text string.
+	 * 	<li>
+	 * 		Supports {@doc DefaultRestSvlVariables}
+	 * 		(e.g. <js>"$L{my.localized.variable}"</js>).
+	 * </ul>
+	 */
+	String multipleOf() default "";
+
+	/**
+	 * <mk>maxLength</mk> field of the {@doc SwaggerItemsObject}.
+	 *
+	 * <h5 class='section'>Notes:</h5>
+	 * <ul class='spaced-list'>
+	 * 	<li>
+	 * 		The format is a plain-text string.
+	 * 	<li>
+	 * 		Supports {@doc DefaultRestSvlVariables}
+	 * 		(e.g. <js>"$L{my.localized.variable}"</js>).
+	 * </ul>
+	 */
+	long maxLength() default -1;
+
+	/**
+	 * <mk>minLength</mk> field of the {@doc SwaggerItemsObject}.
+	 *
+	 * <h5 class='section'>Notes:</h5>
+	 * <ul class='spaced-list'>
+	 * 	<li>
+	 * 		The format is a plain-text string.
+	 * 	<li>
+	 * 		Supports {@doc DefaultRestSvlVariables}
+	 * 		(e.g. <js>"$L{my.localized.variable}"</js>).
+	 * </ul>
+	 */
+	long minLength() default -1;
+
+	/**
+	 * <mk>maxItems</mk> field of the {@doc SwaggerItemsObject}.
+	 *
+	 * <h5 class='section'>Notes:</h5>
+	 * <ul class='spaced-list'>
+	 * 	<li>
+	 * 		The format is a plain-text string.
+	 * 	<li>
+	 * 		Supports {@doc DefaultRestSvlVariables}
+	 * 		(e.g. <js>"$L{my.localized.variable}"</js>).
+	 * </ul>
+	 */
+	long maxItems() default -1;
+
+	/**
+	 * <mk>minItems</mk> field of the {@doc SwaggerItemsObject}.
+	 *
+	 * <h5 class='section'>Notes:</h5>
+	 * <ul class='spaced-list'>
+	 * 	<li>
+	 * 		The format is a plain-text string.
+	 * 	<li>
+	 * 		Supports {@doc DefaultRestSvlVariables}
+	 * 		(e.g. <js>"$L{my.localized.variable}"</js>).
+	 * </ul>
+	 */
+	long minItems() default -1;
+
+	/**
+	 * <mk>exclusiveMaximum</mk> field of the {@doc SwaggerItemsObject}.
+	 *
+	 * <h5 class='section'>Notes:</h5>
+	 * <ul class='spaced-list'>
+	 * 	<li>
+	 * 		The format is a plain-text string.
+	 * 	<li>
+	 * 		Supports {@doc DefaultRestSvlVariables}
+	 * 		(e.g. <js>"$L{my.localized.variable}"</js>).
+	 * </ul>
+	 */
+	boolean exclusiveMaximum() default false;
+
+	/**
+	 * <mk>exclusiveMinimum</mk> field of the {@doc SwaggerItemsObject}.
+	 *
+	 * <h5 class='section'>Notes:</h5>
+	 * <ul class='spaced-list'>
+	 * 	<li>
+	 * 		The format is a plain-text string.
+	 * 	<li>
+	 * 		Supports {@doc DefaultRestSvlVariables}
+	 * 		(e.g. <js>"$L{my.localized.variable}"</js>).
+	 * </ul>
+	 */
+	boolean exclusiveMinimum() default false;
+
+	/**
+	 * <mk>uniqueItems</mk> field of the {@doc SwaggerItemsObject}.
+	 *
+	 * <h5 class='section'>Notes:</h5>
+	 * <ul class='spaced-list'>
+	 * 	<li>
+	 * 		The format is a plain-text string.
+	 * 	<li>
+	 * 		Supports {@doc DefaultRestSvlVariables}
+	 * 		(e.g. <js>"$L{my.localized.variable}"</js>).
+	 * </ul>
+	 */
+	boolean uniqueItems() default false;
+
+	/**
+	 * <mk>default</mk> field of the {@doc SwaggerItemsObject}.
+	 *
+	 * <h5 class='section'>Notes:</h5>
+	 * <ul class='spaced-list'>
+	 * 	<li>
+	 * 		The format is a plain-text string.
+	 * 	<li>
+	 * 		Supports {@doc DefaultRestSvlVariables}
+	 * 		(e.g. <js>"$L{my.localized.variable}"</js>).
+	 * </ul>
+	 */
+	String[] _default() default {};
+
+	/**
+	 * <mk>enum</mk> field of the {@doc SwaggerItemsObject}.
+	 *
+	 * <h5 class='section'>Notes:</h5>
+	 * <ul class='spaced-list'>
+	 * 	<li>
+	 * 		The format is a plain-text string.
+	 * 	<li>
+	 * 		Supports {@doc DefaultRestSvlVariables}
+	 * 		(e.g. <js>"$L{my.localized.variable}"</js>).
+	 * </ul>
+	 */
+	String[] _enum() default {};
+
+	/**
+	 * <mk>$ref</mk> field of the {@doc SwaggerItemsObject}.
+	 *
+	 * <h5 class='section'>Notes:</h5>
+	 * <ul class='spaced-list'>
+	 * 	<li>
+	 * 		The format is a plain-text string.
+	 * 	<li>
+	 * 		Supports {@doc DefaultRestSvlVariables}
+	 * 		(e.g. <js>"$L{my.localized.variable}"</js>).
+	 * </ul>
+	 */
+	String $ref() default "";
+
+	/**
+	 * <mk>items</mk> field of the {@doc SwaggerItemsObject}.
+	 *
+	 * <p>
+	 * Describes the type of items in the array.
+	 */
+	SubItems items() default @SubItems;
+
+	/**
+	 * Free-form value for the {@doc SwaggerItemsObject}.
+	 *
+	 * <p>
+	 * This is a {@doc juneau-marshall.JsonDetails.SimplifiedJson} object that makes up the swagger information for this field.
+	 *
+	 * <p>
+	 * The following are completely equivalent ways of defining the swagger description of an Items object:
+	 * <p class='bcode w800'>
+	 * 	<jc>// Normal</jc>
+	 * 	<ja>@Query</ja>(
+	 * 		name=<js>"status"</js>,
+	 * 		type=<js>"array"</js>,
+	 * 		items=<ja>@Items</ja>(
+	 * 			type=<js>"string"</js>,
+	 * 			_enum=<js>"AVAILABLE,PENDING,SOLD"</js>,
+	 * 			_default=<js>"AVAILABLE"</js>
+	 * 		)
+	 * 	)
+	 * </p>
+	 * <p class='bcode w800'>
+	 * 	<jc>// Free-form</jc>
+	 * 	<ja>@Query</ja>(
+	 * 		name=<js>"status"</js>,
+	 * 		type=<js>"array"</js>,
+	 * 		items=<ja>@Items</ja>({
+	 * 			<js>"type: 'string'"</js>,
+	 * 			<js>"enum: ['AVAILABLE','PENDING','SOLD'],"</js>,
+	 * 			<js>"default: 'AVAILABLE'"</js>
+	 * 		})
+	 * 	)
+	 * </p>
+	 * <p class='bcode w800'>
+	 * 	<jc>// Free-form as part of parent</jc>
+	 * 	<ja>@Query</ja>(
+	 * 		name=<js>"status"</js>,
+	 * 		api={
+	 * 			<js>"type:'array',"</js>,
+	 * 			<js>"items: {"</js>,
+	 * 				<js>"type: 'string',"</js>,
+	 * 				<js>"enum: ['AVAILABLE','PENDING','SOLD'],"</js>,
+	 * 				<js>"default: 'AVAILABLE'"</js>,
+	 * 			<js>"}"</js>)
+	 * 		}
+	 * 	)
+	 * </p>
+	 * <p class='bcode w800'>
+	 * 	<jc>// Free-form with variables</jc>
+	 * 	<ja>@Query</ja>(
+	 * 		name=<js>"status"</js>,
+	 * 		type=<js>"array"</js>,
+	 * 		items=<ja>@Items</ja>(<js>"$L{statusItemsSwagger}"</js>)
+	 * 	)
+	 * </p>
+	 * <p class='bcode w800'>
+	 * 	<mc>// Contents of MyResource.properties</mc>
+	 * 	<mk>statusItemsSwagger</mk> = <mv>{ type: "string", enum: ["AVAILABLE","PENDING","SOLD"], default: "AVAILABLE" }</mv>
+	 * </p>
+	 *
+	 * <p>
+	 * 	The reasons why you may want to use this field include:
+	 * <ul>
+	 * 	<li>You want to pull in the entire Swagger JSON definition for this field from an external source such as a properties file.
+	 * 	<li>You want to add extra fields to the Swagger documentation that are not officially part of the Swagger specification.
+	 * </ul>
+	 *
+	 * <h5 class='section'>Notes:</h5>
+	 * <ul class='spaced-list'>
+	 * 	<li>
+	 * 		Note that the only swagger field you can't specify using this value is <js>"name"</js> whose value needs to be known during servlet initialization.
+	 * 	<li>
+	 * 		The format is a {@doc juneau-marshall.JsonDetails.SimplifiedJson} object.
+	 * 	<li>
+	 * 		The leading/trailing <code>{ }</code> characters are optional.
+	 * 		<br>The following two example are considered equivalent:
+	 * 		<p class='bcode w800'>
+	 * 	<ja>@Items</ja>(api=<js>"{type: 'string'}"</js>)
+	 * 		</p>
+	 * 		<p class='bcode w800'>
+	 * 	<ja>@Items</ja>(api=<js>"type: 'string'"</js>)
+	 * 		</p>
+	 * 	<li>
+	 * 		Multiple lines are concatenated with newlines so that you can format the value to be readable.
+	 * 	<li>
+	 * 		Supports {@doc DefaultRestSvlVariables}
+	 * 		(e.g. <js>"$L{my.localized.variable}"</js>).
+	 * 	<li>
+	 * 		Values defined in this field supersede values pulled from the Swagger JSON file and are superseded by individual values defined on this annotation.
+	 * </ul>
+	 */
+	String[] value() default {};
+}
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/Path.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/Path.java
index 8881a2a..b258095 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/Path.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/Path.java
@@ -18,12 +18,12 @@ import static java.lang.annotation.RetentionPolicy.*;
 import java.lang.annotation.*;
 import java.util.*;
 
+import org.apache.juneau.jsonschema.annotation.Items;
 import org.apache.juneau.*;
 import org.apache.juneau.annotation.*;
 import org.apache.juneau.httppart.*;
 import org.apache.juneau.json.*;
 import org.apache.juneau.jsonschema.*;
-import org.apache.juneau.jsonschema.annotation.*;
 import org.apache.juneau.oapi.*;
 
 /**
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/Query.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/Query.java
index a875586..eadec1b 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/Query.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/Query.java
@@ -18,12 +18,12 @@ import static java.lang.annotation.RetentionPolicy.*;
 import java.lang.annotation.*;
 import java.util.*;
 
+import org.apache.juneau.jsonschema.annotation.Items;
 import org.apache.juneau.*;
 import org.apache.juneau.annotation.*;
 import org.apache.juneau.httppart.*;
 import org.apache.juneau.json.*;
 import org.apache.juneau.jsonschema.*;
-import org.apache.juneau.jsonschema.annotation.*;
 import org.apache.juneau.oapi.*;
 
 /**
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/Response.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/Response.java
index 2cd2a90..63cefe3 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/Response.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/Response.java
@@ -17,12 +17,12 @@ import static java.lang.annotation.RetentionPolicy.*;
 
 import java.lang.annotation.*;
 
+import org.apache.juneau.jsonschema.annotation.Schema;
 import org.apache.juneau.*;
 import org.apache.juneau.annotation.*;
 import org.apache.juneau.httppart.*;
 import org.apache.juneau.json.*;
 import org.apache.juneau.jsonschema.*;
-import org.apache.juneau.jsonschema.annotation.*;
 import org.apache.juneau.oapi.*;
 
 /**
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/ResponseHeader.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/ResponseHeader.java
index dc81978..fa78432 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/ResponseHeader.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/ResponseHeader.java
@@ -17,9 +17,9 @@ import static java.lang.annotation.RetentionPolicy.*;
 
 import java.lang.annotation.*;
 
+import org.apache.juneau.jsonschema.annotation.Items;
 import org.apache.juneau.*;
 import org.apache.juneau.httppart.*;
-import org.apache.juneau.jsonschema.annotation.*;
 import org.apache.juneau.oapi.*;
 
 /**
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/Schema.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/Schema.java
new file mode 100644
index 0000000..c92415e
--- /dev/null
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/Schema.java
@@ -0,0 +1,703 @@
+// ***************************************************************************************************************************
+// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
+// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
+// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
+// * with the License.  You may obtain a copy of the License at                                                              *
+// *                                                                                                                         *
+// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
+// *                                                                                                                         *
+// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
+// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
+// * specific language governing permissions and limitations under the License.                                              *
+// ***************************************************************************************************************************
+package org.apache.juneau.http.annotation;
+
+import static java.lang.annotation.RetentionPolicy.*;
+
+import java.lang.annotation.*;
+
+/**
+ * @deprecated Use {@link org.apache.juneau.jsonschema.annotation.Schema}
+ */
+@Documented
+@Retention(RUNTIME)
+@Deprecated
+public @interface Schema {
+
+	/**
+	 * <mk>$ref</mk> field of the {@doc SwaggerSchemaObject}.
+	 *
+	 * <p>
+	 * 	A JSON reference to the schema definition.
+	 *
+	 * <h5 class='section'>Notes:</h5>
+	 * <ul class='spaced-list'>
+	 * 	<li>
+	 * 		The format is a <a href='https://tools.ietf.org/html/draft-pbryan-zyp-json-ref-03'>JSON Reference</a>.
+	 * 	<li>
+	 * 		Supports {@doc DefaultRestSvlVariables}
+	 * 		(e.g. <js>"$L{my.localized.variable}"</js>).
+	 * </ul>
+	 */
+	String $ref() default "";
+
+	/**
+	 * <mk>format</mk> field of the {@doc SwaggerSchemaObject}.
+	 *
+	 * <h5 class='section'>Examples:</h5>
+	 * <p class='bcode w800'>
+	 * 	<jc>// Used on parameter</jc>
+	 * 	<ja>@RestMethod</ja>(name=<jsf>PUT</jsf>)
+	 * 	<jk>public void</jk> setAge(
+	 * 		<ja>@Body</ja>(type=<js>"integer"</js>, format=<js>"int32"</js>) String input
+	 * 	) {...}
+	 * </p>
+	 *
+	 * <h5 class='section'>Notes:</h5>
+	 * <ul class='spaced-list'>
+	 * 	<li>
+	 * 		The format is plain text.
+	 * 	<li>
+	 * 		Supports {@doc DefaultRestSvlVariables}
+	 * 		(e.g. <js>"$L{my.localized.variable}"</js>).
+	 * </ul>
+	 *
+	 * <h5 class='section'>See Also:</h5>
+	 * <ul class='doctree'>
+	 * 	<li class='extlink'>{@doc SwaggerDataTypeFormats}
+	 * </ul>
+	 */
+	String format() default "";
+
+	/**
+	 * <mk>title</mk> field of the {@doc SwaggerSchemaObject}.
+	 *
+	 * <h5 class='section'>Notes:</h5>
+	 * <ul class='spaced-list'>
+	 * 	<li>
+	 * 		The format is plain text.
+	 * 	<li>
+	 * 		Supports {@doc DefaultRestSvlVariables}
+	 * 		(e.g. <js>"$L{my.localized.variable}"</js>).
+	 * </ul>
+	 */
+	String title() default "";
+
+	/**
+	 * <mk>description</mk> field of the {@doc SwaggerSchemaObject}.
+	 *
+	 * <p>
+	 * A brief description of the body. This could contain examples of use.
+	 *
+	 * <h5 class='section'>Examples:</h5>
+	 * <p class='bcode w800'>
+	 * 	<jc>// Used on parameter</jc>
+	 * 	<ja>@RestMethod</ja>(name=<jsf>POST</jsf>)
+	 * 	<jk>public void</jk> addPet(
+	 * 		<ja>@Body</ja>(description=<js>"Pet object to add to the store"</js>) Pet input
+	 * 	) {...}
+	 * </p>
+	 * <p class='bcode w800'>
+	 * 	<jc>// Used on class</jc>
+	 * 	<ja>@RestMethod</ja>(name=<jsf>POST</jsf>)
+	 * 	<jk>public void</jk> addPet(Pet input) {...}
+	 *
+	 * 	<ja>@Body</ja>(description=<js>"Pet object to add to the store"</js>)
+	 * 	<jk>public class</jk> Pet {...}
+	 * </p>
+	 *
+	 * <h5 class='section'>Notes:</h5>
+	 * <ul class='spaced-list'>
+	 * 	<li>
+	 * 		The format is plain text.
+	 * 		<br>Multiple lines are concatenated with newlines.
+	 * 	<li>
+	 * 		Supports {@doc DefaultRestSvlVariables}
+	 * 		(e.g. <js>"$L{my.localized.variable}"</js>).
+	 * </ul>
+	 */
+	String[] description() default {};
+
+	/**
+	 * <mk>default</mk> field of the {@doc SwaggerSchemaObject}.
+	 *
+	 * <h5 class='section'>Notes:</h5>
+	 * <ul class='spaced-list'>
+	 * 	<li>
+	 * 		The format is any {@doc juneau-marshall.JsonDetails.SimplifiedJson}.
+	 * 		<br>Multiple lines are concatenated with newlines.
+	 * 	<li>
+	 * 		Supports {@doc DefaultRestSvlVariables}
+	 * 		(e.g. <js>"$L{my.localized.variable}"</js>).
+	 * </ul>
+	 */
+	String[] _default() default {};
+
+	/**
+	 * <mk>multipleOf</mk> field of the {@doc SwaggerSchemaObject}.
+	 *
+	 * <h5 class='section'>Notes:</h5>
+	 * <ul class='spaced-list'>
+	 * 	<li>
+	 * 		The format is numeric.
+	 * 	<li>
+	 * 		Supports {@doc DefaultRestSvlVariables}
+	 * 		(e.g. <js>"$L{my.localized.variable}"</js>).
+	 * </ul>
+	 */
+	String multipleOf() default "";
+
+	/**
+	 * <mk>maximum</mk> field of the {@doc SwaggerSchemaObject}.
+	 *
+	 * <h5 class='section'>Notes:</h5>
+	 * <ul class='spaced-list'>
+	 * 	<li>
+	 * 		The format is numeric.
+	 * 	<li>
+	 * 		Supports {@doc DefaultRestSvlVariables}
+	 * 		(e.g. <js>"$L{my.localized.variable}"</js>).
+	 * </ul>
+	 */
+	String maximum() default "";
+
+	/**
+	 * <mk>exclusiveMaximum</mk> field of the {@doc SwaggerSchemaObject}.
+	 *
+	 * <h5 class='section'>Notes:</h5>
+	 * <ul class='spaced-list'>
+	 * 	<li>
+	 * 		The format is numeric.
+	 * 	<li>
+	 * 		Supports {@doc DefaultRestSvlVariables}
+	 * 		(e.g. <js>"$L{my.localized.variable}"</js>).
+	 * </ul>
+	 */
+	boolean exclusiveMaximum() default false;
+
+	/**
+	 * <mk>minimum</mk> field of the {@doc SwaggerSchemaObject}.
+	 *
+	 * <h5 class='section'>Notes:</h5>
+	 * <ul class='spaced-list'>
+	 * 	<li>
+	 * 		The format is numeric.
+	 * 	<li>
+	 * 		Supports {@doc DefaultRestSvlVariables}
+	 * 		(e.g. <js>"$L{my.localized.variable}"</js>).
+	 * </ul>
+	 */
+	String minimum() default "";
+
+	/**
+	 * <mk>exclusiveMinimum</mk> field of the {@doc SwaggerSchemaObject}.
+	 *
+	 * <h5 class='section'>Notes:</h5>
+	 * <ul class='spaced-list'>
+	 * 	<li>
+	 * 		The format is numeric.
+	 * 	<li>
+	 * 		Supports {@doc DefaultRestSvlVariables}
+	 * 		(e.g. <js>"$L{my.localized.variable}"</js>).
+	 * </ul>
+	 */
+	boolean exclusiveMinimum() default false;
+
+	/**
+	 * <mk>maxLength</mk> field of the {@doc SwaggerSchemaObject}.
+	 *
+	 * <h5 class='section'>Notes:</h5>
+	 * <ul class='spaced-list'>
+	 * 	<li>
+	 * 		The format is numeric.
+	 * 	<li>
+	 * 		Supports {@doc DefaultRestSvlVariables}
+	 * 		(e.g. <js>"$L{my.localized.variable}"</js>).
+	 * </ul>
+	 */
+	long maxLength() default -1;
+
+	/**
+	 * <mk>minLength</mk> field of the {@doc SwaggerSchemaObject}.
+	 *
+	 * <h5 class='section'>Notes:</h5>
+	 * <ul class='spaced-list'>
+	 * 	<li>
+	 * 		The format is numeric.
+	 * 	<li>
+	 * 		Supports {@doc DefaultRestSvlVariables}
+	 * 		(e.g. <js>"$L{my.localized.variable}"</js>).
+	 * </ul>
+	 */
+	long minLength() default -1;
+
+	/**
+	 * <mk>pattern</mk> field of the {@doc SwaggerSchemaObject}.
+	 *
+	 * <h5 class='section'>Example:</h5>
+	 * <p class='bcode w800'>
+	 * 	<ja>@RestMethod</ja>(name=<jsf>PUT</jsf>)
+	 * 	<jk>public void</jk> doPut(<ja>@Body</ja>(format=<js>"/\\w+\\.\\d+/"</js>) String input) {...}
+	 * </p>
+	 *
+	 * <h5 class='section'>Notes:</h5>
+	 * <ul class='spaced-list'>
+	 * 	<li>
+	 * 		The format is plain text.
+	 * 	<li>
+	 * 		This string SHOULD be a valid regular expression.
+	 * 	<li>
+	 * 		Supports {@doc DefaultRestSvlVariables}
+	 * 		(e.g. <js>"$L{my.localized.variable}"</js>).
+	 * </ul>
+	 */
+	String pattern() default "";
+
+	/**
+	 * <mk>maxItems</mk> field of the {@doc SwaggerSchemaObject}.
+	 *
+	 * <h5 class='section'>Notes:</h5>
+	 * <ul class='spaced-list'>
+	 * 	<li>
+	 * 		The format is numeric.
+	 * 	<li>
+	 * 		Supports {@doc DefaultRestSvlVariables}
+	 * 		(e.g. <js>"$L{my.localized.variable}"</js>).
+	 * </ul>
+	 */
+	long maxItems() default -1;
+
+	/**
+	 * <mk>minItems</mk> field of the {@doc SwaggerSchemaObject}.
+	 *
+	 * <h5 class='section'>Notes:</h5>
+	 * <ul class='spaced-list'>
+	 * 	<li>
+	 * 		The format is numeric.
+	 * 	<li>
+	 * 		Supports {@doc DefaultRestSvlVariables}
+	 * 		(e.g. <js>"$L{my.localized.variable}"</js>).
+	 * </ul>
+	 */
+	long minItems() default -1;
+
+	/**
+	 * <mk>uniqueItems</mk> field of the {@doc SwaggerSchemaObject}.
+	 *
+	 * <h5 class='section'>Notes:</h5>
+	 * <ul class='spaced-list'>
+	 * 	<li>
+	 * 		The format is boolean.
+	 * 	<li>
+	 * 		Supports {@doc DefaultRestSvlVariables}
+	 * 		(e.g. <js>"$L{my.localized.variable}"</js>).
+	 * </ul>
+	 */
+	boolean uniqueItems() default false;
+
+
+	/**
+	 * <mk>maxProperties</mk> field of the {@doc SwaggerSchemaObject}.
+	 *
+	 * <h5 class='section'>Notes:</h5>
+	 * <ul class='spaced-list'>
+	 * 	<li>
+	 * 		The format is a {@doc juneau-marshall.JsonDetails.SimplifiedJson} object.
+	 * 		<br>Multiple lines are concatenated with newlines.
+	 * 	<li>
+	 * 		Supports {@doc DefaultRestSvlVariables}
+	 * 		(e.g. <js>"$L{my.localized.variable}"</js>).
+	 * </ul>
+	 */
+	long maxProperties() default -1;
+
+
+	/**
+	 * <mk>minProperties</mk> field of the {@doc SwaggerSchemaObject}.
+	 *
+	 * <h5 class='section'>Notes:</h5>
+	 * <ul class='spaced-list'>
+	 * 	<li>
+	 * 		The format is a {@doc juneau-marshall.JsonDetails.SimplifiedJson} object.
+	 * 		<br>Multiple lines are concatenated with newlines.
+	 * 	<li>
+	 * 		Supports {@doc DefaultRestSvlVariables}
+	 * 		(e.g. <js>"$L{my.localized.variable}"</js>).
+	 * </ul>
+	 */
+	long minProperties() default -1;
+
+	/**
+	 * <mk>required</mk> field of the {@doc SwaggerSchemaObject}.
+	 *
+	 * <p>
+	 * 	Determines whether this parameter is mandatory.
+	 *  <br>The property MAY be included and its default value is false.
+	 *
+	 * <h5 class='section'>Examples:</h5>
+	 * <p class='bcode w800'>
+	 * 	<jc>// Used on parameter</jc>
+	 * 	<ja>@RestMethod</ja>(name=<jsf>POST</jsf>)
+	 * 	<jk>public void</jk> addPet(
+	 * 		<ja>@Body</ja>(required=<jk>true</jk>) Pet input
+	 * 	) {...}
+	 * </p>
+	 * <p class='bcode w800'>
+	 * 	<jc>// Used on class</jc>
+	 * 	<ja>@RestMethod</ja>(name=<jsf>POST</jsf>)
+	 * 	<jk>public void</jk> addPet(Pet input) {...}
+	 *
+	 * 	<ja>@Body</ja>(required=<jk>true</jk>)
+	 * 	<jk>public class</jk> Pet {...}
+	 * </p>
+	 *
+	 * <h5 class='section'>Notes:</h5>
+	 * <ul class='spaced-list'>
+	 * 	<li>
+	 * 		The format is boolean.
+	 * 	<li>
+	 * 		Supports {@doc DefaultRestSvlVariables}
+	 * 		(e.g. <js>"$L{my.localized.variable}"</js>).
+	 * </ul>
+	 */
+	boolean required() default false;
+
+	/**
+	 * <mk>enum</mk> field of the {@doc SwaggerSchemaObject}.
+	 *
+	 * <h5 class='section'>Notes:</h5>
+	 * <ul class='spaced-list'>
+	 * 	<li>
+	 * 		The format is a {@doc juneau-marshall.JsonDetails.SimplifiedJson} array or comma-delimited list.
+	 * 		<br>Multiple lines are concatenated with newlines.
+	 * 	<li>
+	 * 		Supports {@doc DefaultRestSvlVariables}
+	 * 		(e.g. <js>"$L{my.localized.variable}"</js>).
+	 * </ul>
+	 */
+	String[] _enum() default {};
+
+	/**
+	 * <mk>type</mk> field of the {@doc SwaggerSchemaObject}.
+	 *
+	 * <h5 class='section'>Examples:</h5>
+	 * <p class='bcode w800'>
+	 * 	<jc>// Used on parameter</jc>
+	 * 	<ja>@RestMethod</ja>(name=<jsf>POST</jsf>)
+	 * 	<jk>public void</jk> addPet(
+	 * 		<ja>@Body</ja>(type=<js>"object"</js>) Pet input
+	 * 	) {...}
+	 * </p>
+	 * <p class='bcode w800'>
+	 * 	<jc>// Used on class</jc>
+	 * 	<ja>@RestMethod</ja>(name=<jsf>POST</jsf>)
+	 * 	<jk>public void</jk> addPet(Pet input) {...}
+	 *
+	 * 	<ja>@Body</ja>(type=<js>"object"</js>)
+	 * 	<jk>public class</jk> Pet {...}
+	 * </p>
+	 *
+	 * <h5 class='section'>Notes:</h5>
+	 * <ul class='spaced-list'>
+	 * 	<li>
+	 * 		The format is plain text.
+	 * 	<li>
+	 * 		The possible values are:
+	 * 		<ul>
+	 * 			<li><js>"object"</js>
+	 * 			<li><js>"string"</js>
+	 * 			<li><js>"number"</js>
+	 * 			<li><js>"integer"</js>
+	 * 			<li><js>"boolean"</js>
+	 * 			<li><js>"array"</js>
+	 * 			<li><js>"file"</js>
+	 * 		</ul>
+	 * 	<li>
+	 * 		Supports {@doc DefaultRestSvlVariables}
+	 * 		(e.g. <js>"$L{my.localized.variable}"</js>).
+	 * </ul>
+	 *
+	 * <h5 class='section'>See Also:</h5>
+	 * <ul class='doctree'>
+	 * 	<li class='extlink'>{@doc SwaggerDataTypes}
+	 * </ul>
+	 *
+	 */
+	String type() default "";
+
+	/**
+	 * <mk>items</mk> field of the {@doc SwaggerSchemaObject}.
+	 *
+	 * <h5 class='section'>Notes:</h5>
+	 * <ul class='spaced-list'>
+	 * 	<li>
+	 * 		The format is a {@doc juneau-marshall.JsonDetails.SimplifiedJson} object.
+	 * 		<br>Multiple lines are concatenated with newlines.
+	 * 	<li>
+	 * 		Supports {@doc DefaultRestSvlVariables}
+	 * 		(e.g. <js>"$L{my.localized.variable}"</js>).
+	 * </ul>
+	 */
+	Items items() default @Items;
+
+	/**
+	 * <mk>collectionFormat</mk> field.
+	 *
+	 * <p>
+	 * Note that this field isn't part of the Swagger 2.0 specification, but the specification does not specify how
+	 * items are supposed to be represented.
+	 *
+	 * <p>
+	 * Determines the format of the array if <code>type</code> <js>"array"</js> is used.
+	 * <br>Can only be used if <code>type</code> is <js>"array"</js>.
+	 *
+	 * <br>Possible values are:
+	 * <ul class='spaced-list'>
+	 * 	<li>
+	 * 		<js>"csv"</js> (default) - Comma-separated values (e.g. <js>"foo,bar"</js>).
+	 * 	<li>
+	 * 		<js>"ssv"</js> - Space-separated values (e.g. <js>"foo bar"</js>).
+	 * 	<li>
+	 * 		<js>"tsv"</js> - Tab-separated values (e.g. <js>"foo\tbar"</js>).
+	 * 	<li>
+	 * 		<js>"pipes</js> - Pipe-separated values (e.g. <js>"foo|bar"</js>).
+	 * 	<li>
+	 * 		<js>"multi"</js> - Corresponds to multiple parameter instances instead of multiple values for a single instance (e.g. <js>"foo=bar&amp;foo=baz"</js>).
+	 * 	<li>
+	 * 		<js>"uon"</js> - UON notation (e.g. <js>"@(foo,bar)"</js>).
+	 * </ul>
+	 *
+	 * <p>
+	 * Static strings are defined in {@link CollectionFormatType}.
+	 *
+	 * <p>
+	 * Note that for collections/arrays parameters with POJO element types, the input is broken into a string array before being converted into POJO elements.
+	 *
+	 * <h5 class='section'>Used for:</h5>
+	 * <ul class='spaced-list'>
+	 * 	<li>
+	 * 		Server-side schema-based parsing.
+	 * 	<li>
+	 * 		Server-side generated Swagger documentation.
+	 * 	<li>
+	 * 		Client-side schema-based serializing.
+	 * </ul>
+	 */
+	String collectionFormat() default "";
+
+	/**
+	 * <mk>allOf</mk> field of the {@doc SwaggerSchemaObject}.
+	 *
+	 * <h5 class='section'>Notes:</h5>
+	 * <ul class='spaced-list'>
+	 * 	<li>
+	 * 		The format is a {@doc juneau-marshall.JsonDetails.SimplifiedJson} object.
+	 * 		<br>Multiple lines are concatenated with newlines.
+	 * 	<li>
+	 * 		Supports {@doc DefaultRestSvlVariables}
+	 * 		(e.g. <js>"$L{my.localized.variable}"</js>).
+	 * </ul>
+	 */
+	String[] allOf() default {};
+
+	/**
+	 * <mk>properties</mk> field of the {@doc SwaggerSchemaObject}.
+	 *
+	 * <h5 class='section'>Notes:</h5>
+	 * <ul class='spaced-list'>
+	 * 	<li>
+	 * 		The format is a {@doc juneau-marshall.JsonDetails.SimplifiedJson} object.
+	 * 		<br>Multiple lines are concatenated with newlines.
+	 * 	<li>
+	 * 		Supports {@doc DefaultRestSvlVariables}
+	 * 		(e.g. <js>"$L{my.localized.variable}"</js>).
+	 * </ul>
+	 */
+	String[] properties() default {};
+
+	/**
+	 * <mk>additionalProperties</mk> field of the {@doc SwaggerSchemaObject}.
+	 *
+	 * <h5 class='section'>Notes:</h5>
+	 * <ul class='spaced-list'>
+	 * 	<li>
+	 * 		The format is a {@doc juneau-marshall.JsonDetails.SimplifiedJson} object.
+	 * 		<br>Multiple lines are concatenated with newlines.
+	 * 	<li>
+	 * 		Supports {@doc DefaultRestSvlVariables}
+	 * 		(e.g. <js>"$L{my.localized.variable}"</js>).
+	 * </ul>
+	 */
+	String[] additionalProperties() default {};
+
+	/**
+	 * <mk>discriminator</mk> field of the {@doc SwaggerSchemaObject}.
+	 *
+	 * <h5 class='section'>Notes:</h5>
+	 * <ul class='spaced-list'>
+	 * 	<li>
+	 * 		The format is a {@doc juneau-marshall.JsonDetails.SimplifiedJson} object.
+	 * 		<br>Multiple lines are concatenated with newlines.
+	 * 	<li>
+	 * 		Supports {@doc DefaultRestSvlVariables}
+	 * 		(e.g. <js>"$L{my.localized.variable}"</js>).
+	 * </ul>
+	 */
+	String discriminator() default "";
+
+	/**
+	 * <mk>readOnly</mk> field of the {@doc SwaggerSchemaObject}.
+	 *
+	 * <h5 class='section'>Notes:</h5>
+	 * <ul class='spaced-list'>
+	 * 	<li>
+	 * 		The format is a {@doc juneau-marshall.JsonDetails.SimplifiedJson} object.
+	 * 		<br>Multiple lines are concatenated with newlines.
+	 * 	<li>
+	 * 		Supports {@doc DefaultRestSvlVariables}
+	 * 		(e.g. <js>"$L{my.localized.variable}"</js>).
+	 * </ul>
+	 */
+	boolean readOnly() default false;
+
+	/**
+	 * <mk>xml</mk> field of the {@doc SwaggerSchemaObject}.
+	 *
+	 * <h5 class='section'>Notes:</h5>
+	 * <ul class='spaced-list'>
+	 * 	<li>
+	 * 		The format is a {@doc juneau-marshall.JsonDetails.SimplifiedJson} object.
+	 * 		<br>Multiple lines are concatenated with newlines.
+	 * 	<li>
+	 * 		Supports {@doc DefaultRestSvlVariables}
+	 * 		(e.g. <js>"$L{my.localized.variable}"</js>).
+	 * </ul>
+	 */
+	String[] xml() default {};
+
+	/**
+	 * <mk>externalDocs</mk> field of the {@doc SwaggerSchemaObject}.
+	 *
+	 * <h5 class='section'>Notes:</h5>
+	 * <ul class='spaced-list'>
+	 * 	<li>
+	 * 		The format is a {@doc juneau-marshall.JsonDetails.SimplifiedJson} object.
+	 * 		<br>Multiple lines are concatenated with newlines.
+	 * 	<li>
+	 * 		Supports {@doc DefaultRestSvlVariables}
+	 * 		(e.g. <js>"$L{my.localized.variable}"</js>).
+	 * </ul>
+	 */
+	ExternalDocs externalDocs() default @ExternalDocs;
+
+	/**
+	 * <mk>example</mk> field of the {@doc SwaggerSchemaObject}.
+	 *
+	 * <p>
+	 * A free-form property to include an example of an instance for this schema.
+	 *
+	 * <p>
+	 * This attribute defines a JSON representation of the body value that is used by <code>BasicRestInfoProvider</code> to construct
+	 * media-type-based examples of the body of the request.
+	 *
+	 * <h5 class='section'>Notes:</h5>
+	 * <ul class='spaced-list'>
+	 * 	<li>
+	 * 		The format is a {@doc juneau-marshall.JsonDetails.SimplifiedJson} object or plain text string.
+	 * 		<br>Multiple lines are concatenated with newlines.
+	 * 	<li>
+	 * 		Supports {@doc DefaultRestSvlVariables}
+	 * 		(e.g. <js>"$L{my.localized.variable}"</js>).
+	 * </ul>
+	 */
+	String[] example() default {};
+
+	/**
+	 * <mk>x-examples</mk> field of the {@doc SwaggerSchemaObject}.
+	 *
+	 * <p>
+	 * This is a JSON object whose keys are media types and values are string representations of that value.
+	 *
+	 * <h5 class='section'>Notes:</h5>
+	 * <ul class='spaced-list'>
+	 * 	<li>
+	 * 		The format is a {@doc juneau-marshall.JsonDetails.SimplifiedJson} object.
+	 * 		<br>Multiple lines are concatenated with newlines.
+	 * 	<li>
+	 * 		Supports {@doc DefaultRestSvlVariables}
+	 * 		(e.g. <js>"$L{my.localized.variable}"</js>).
+	 * </ul>
+	 */
+	String[] examples() default {};
+
+	/**
+	 * Specifies that schema information for this part should not be shown in the generated Swagger documentation.
+	 */
+	boolean ignore() default false;
+
+	/**
+	 * Free-form value for the {@doc SwaggerSchemaObject}.
+	 *
+	 * <p>
+	 * This is a JSON object that makes up the swagger information for this field.
+	 *
+	 * <p>
+	 * The following are completely equivalent ways of defining the swagger description of a Schema object:
+	 * <p class='bcode w800'>
+	 * 	<jc>// Normal</jc>
+	 * 	<ja>@Schema</ja>(
+	 * 		type=<js>"array"</js>,
+	 * 		items=<ja>@Items</ja>(
+	 * 			$ref=<js>"#/definitions/Pet"</js>
+	 * 		)
+	 * 	)
+	 * </p>
+	 * <p class='bcode w800'>
+	 * 	<jc>// Free-form</jc>
+	 * 	<ja>@Schema</ja>(
+	 * 		<js>"type: 'array',"</js>,
+	 * 		<js>"items: {"</js>,
+	 * 			<js>"$ref: '#/definitions/Pet'"</js>,
+	 * 		<js>"}"</js>
+	 * 	)
+	 * </p>
+	 * <p class='bcode w800'>
+	 * 	<jc>// Free-form using variables</jc>
+	 * 	<ja>@Schema</ja>(<js>"$L{petArraySwagger}"</js>)
+	 * </p>
+	 * <p class='bcode w800'>
+	 * 	<mc>// Contents of MyResource.properties</mc>
+	 * 	<mk>petArraySwagger</mk> = <mv>{ type: "array", items: { $ref: "#/definitions/Pet" } }</mv>
+	 * </p>
+	 *
+	 * <p>
+	 * 	The reasons why you may want to use this field include:
+	 * <ul>
+	 * 	<li>You want to pull in the entire Swagger JSON definition for this field from an external source such as a properties file.
+	 * 	<li>You want to add extra fields to the Swagger documentation that are not officially part of the Swagger specification.
+	 * </ul>
+	 *
+	 * <h5 class='section'>Notes:</h5>
+	 * <ul class='spaced-list'>
+	 * 	<li>
+	 * 		The format is a {@doc juneau-marshall.JsonDetails.SimplifiedJson} object.
+	 * 	<li>
+	 * 		The leading/trailing <code>{ }</code> characters are optional.
+	 * 		<br>The following two example are considered equivalent:
+	 * 		<p class='bcode w800'>
+	 * 	<ja>@Schema</ja>(<js>"{type: 'array'}"</js>)
+	 * 		</p>
+	 * 		<p class='bcode w800'>
+	 * 	<ja>@Schema</ja>(<js>"type: 'array'"</js>)
+	 * 		</p>
+	 * 	<li>
+	 * 		Multiple lines are concatenated with newlines so that you can format the value to be readable.
+	 * 	<li>
+	 * 		Supports {@doc DefaultRestSvlVariables}
+	 * 		(e.g. <js>"$L{my.localized.variable}"</js>).
+	 * 	<li>
+	 * 		Values defined in this field supersede values pulled from the Swagger JSON file and are superseded by individual values defined on this annotation.
+	 * </ul>
+	 */
+	String[] value() default {};
+}
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/SubItems.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/SubItems.java
new file mode 100644
index 0000000..44c1059
--- /dev/null
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/SubItems.java
@@ -0,0 +1,368 @@
+// ***************************************************************************************************************************
+// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
+// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
+// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
+// * with the License.  You may obtain a copy of the License at                                                              *
+// *                                                                                                                         *
+// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
+// *                                                                                                                         *
+// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
+// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
+// * specific language governing permissions and limitations under the License.                                              *
+// ***************************************************************************************************************************
+package org.apache.juneau.http.annotation;
+
+import static java.lang.annotation.RetentionPolicy.*;
+
+import java.lang.annotation.*;
+
+/**
+ * @deprecated Use {@link org.apache.juneau.jsonschema.annotation.SubItems}
+ */
+@Documented
+@Retention(RUNTIME)
+@Deprecated
+public @interface SubItems {
+
+	/**
+	 * <mk>type</mk> field of the {@doc SwaggerItemsObject}.
+	 *
+	 * <h5 class='section'>Notes:</h5>
+	 * <ul class='spaced-list'>
+	 * 	<li>
+	 * 		The format is a plain-text string.
+	 * 	<li>
+	 * 		Supports {@doc DefaultRestSvlVariables}
+	 * 		(e.g. <js>"$L{my.localized.variable}"</js>).
+	 * </ul>
+	 */
+	String type() default "";
+
+	/**
+	 * <mk>format</mk> field of the {@doc SwaggerItemsObject}.
+	 *
+	 * <h5 class='section'>Notes:</h5>
+	 * <ul class='spaced-list'>
+	 * 	<li>
+	 * 		The format is a plain-text string.
+	 * 	<li>
+	 * 		Supports {@doc DefaultRestSvlVariables}
+	 * 		(e.g. <js>"$L{my.localized.variable}"</js>).
+	 * </ul>
+	 */
+	String format() default "";
+
+	/**
+	 * <mk>collectionFormat</mk> field of the {@doc SwaggerItemsObject}.
+	 *
+	 * <h5 class='section'>Notes:</h5>
+	 * <ul class='spaced-list'>
+	 * 	<li>
+	 * 		The format is a plain-text string.
+	 * 	<li>
+	 * 		Supports {@doc DefaultRestSvlVariables}
+	 * 		(e.g. <js>"$L{my.localized.variable}"</js>).
+	 * </ul>
+	 */
+	String collectionFormat() default "";
+
+	/**
+	 * <mk>pattern</mk> field of the {@doc SwaggerItemsObject}.
+	 *
+	 * <h5 class='section'>Notes:</h5>
+	 * <ul class='spaced-list'>
+	 * 	<li>
+	 * 		The format is a plain-text string.
+	 * 	<li>
+	 * 		Supports {@doc DefaultRestSvlVariables}
+	 * 		(e.g. <js>"$L{my.localized.variable}"</js>).
+	 * </ul>
+	 */
+	String pattern() default "";
+
+	/**
+	 * <mk>maximum</mk> field of the {@doc SwaggerItemsObject}.
+	 *
+	 * <h5 class='section'>Notes:</h5>
+	 * <ul class='spaced-list'>
+	 * 	<li>
+	 * 		The format is a plain-text string.
+	 * 	<li>
+	 * 		Supports {@doc DefaultRestSvlVariables}
+	 * 		(e.g. <js>"$L{my.localized.variable}"</js>).
+	 * </ul>
+	 */
+	String maximum() default "";
+
+	/**
+	 * <mk>minimum</mk> field of the {@doc SwaggerItemsObject}.
+	 *
+	 * <h5 class='section'>Notes:</h5>
+	 * <ul class='spaced-list'>
+	 * 	<li>
+	 * 		The format is a plain-text string.
+	 * 	<li>
+	 * 		Supports {@doc DefaultRestSvlVariables}
+	 * 		(e.g. <js>"$L{my.localized.variable}"</js>).
+	 * </ul>
+	 */
+	String minimum() default "";
+
+	/**
+	 * <mk>multipleOf</mk> field of the {@doc SwaggerItemsObject}.
+	 *
+	 * <h5 class='section'>Notes:</h5>
+	 * <ul class='spaced-list'>
+	 * 	<li>
+	 * 		The format is a plain-text string.
+	 * 	<li>
+	 * 		Supports {@doc DefaultRestSvlVariables}
+	 * 		(e.g. <js>"$L{my.localized.variable}"</js>).
+	 * </ul>
+	 */
+	String multipleOf() default "";
+
+	/**
+	 * <mk>maxLength</mk> field of the {@doc SwaggerItemsObject}.
+	 *
+	 * <h5 class='section'>Notes:</h5>
+	 * <ul class='spaced-list'>
+	 * 	<li>
+	 * 		The format is a plain-text string.
+	 * 	<li>
+	 * 		Supports {@doc DefaultRestSvlVariables}
+	 * 		(e.g. <js>"$L{my.localized.variable}"</js>).
+	 * </ul>
+	 */
+	long maxLength() default -1;
+
+	/**
+	 * <mk>minLength</mk> field of the {@doc SwaggerItemsObject}.
+	 *
+	 * <h5 class='section'>Notes:</h5>
+	 * <ul class='spaced-list'>
+	 * 	<li>
+	 * 		The format is a plain-text string.
+	 * 	<li>
+	 * 		Supports {@doc DefaultRestSvlVariables}
+	 * 		(e.g. <js>"$L{my.localized.variable}"</js>).
+	 * </ul>
+	 */
+	long minLength() default -1;
+
+	/**
+	 * <mk>maxItems</mk> field of the {@doc SwaggerItemsObject}.
+	 *
+	 * <h5 class='section'>Notes:</h5>
+	 * <ul class='spaced-list'>
+	 * 	<li>
+	 * 		The format is a plain-text string.
+	 * 	<li>
+	 * 		Supports {@doc DefaultRestSvlVariables}
+	 * 		(e.g. <js>"$L{my.localized.variable}"</js>).
+	 * </ul>
+	 */
+	long maxItems() default -1;
+
+	/**
+	 * <mk>minItems</mk> field of the {@doc SwaggerItemsObject}.
+	 *
+	 * <h5 class='section'>Notes:</h5>
+	 * <ul class='spaced-list'>
+	 * 	<li>
+	 * 		The format is a plain-text string.
+	 * 	<li>
+	 * 		Supports {@doc DefaultRestSvlVariables}
+	 * 		(e.g. <js>"$L{my.localized.variable}"</js>).
+	 * </ul>
+	 */
+	long minItems() default -1;
+
+	/**
+	 * <mk>exclusiveMaximum</mk> field of the {@doc SwaggerItemsObject}.
+	 *
+	 * <h5 class='section'>Notes:</h5>
+	 * <ul class='spaced-list'>
+	 * 	<li>
+	 * 		The format is a plain-text string.
+	 * 	<li>
+	 * 		Supports {@doc DefaultRestSvlVariables}
+	 * 		(e.g. <js>"$L{my.localized.variable}"</js>).
+	 * </ul>
+	 */
+	boolean exclusiveMaximum() default false;
+
+	/**
+	 * <mk>exclusiveMinimum</mk> field of the {@doc SwaggerItemsObject}.
+	 *
+	 * <h5 class='section'>Notes:</h5>
+	 * <ul class='spaced-list'>
+	 * 	<li>
+	 * 		The format is a plain-text string.
+	 * 	<li>
+	 * 		Supports {@doc DefaultRestSvlVariables}
+	 * 		(e.g. <js>"$L{my.localized.variable}"</js>).
+	 * </ul>
+	 */
+	boolean exclusiveMinimum() default false;
+
+	/**
+	 * <mk>uniqueItems</mk> field of the {@doc SwaggerItemsObject}.
+	 *
+	 * <h5 class='section'>Notes:</h5>
+	 * <ul class='spaced-list'>
+	 * 	<li>
+	 * 		The format is a plain-text string.
+	 * 	<li>
+	 * 		Supports {@doc DefaultRestSvlVariables}
+	 * 		(e.g. <js>"$L{my.localized.variable}"</js>).
+	 * </ul>
+	 */
+	boolean uniqueItems() default false;
+
+	/**
+	 * <mk>default</mk> field of the {@doc SwaggerItemsObject}.
+	 *
+	 * <h5 class='section'>Notes:</h5>
+	 * <ul class='spaced-list'>
+	 * 	<li>
+	 * 		The format is a plain-text string.
+	 * 	<li>
+	 * 		Supports {@doc DefaultRestSvlVariables}
+	 * 		(e.g. <js>"$L{my.localized.variable}"</js>).
+	 * </ul>
+	 */
+	String[] _default() default {};
+
+	/**
+	 * <mk>enum</mk> field of the {@doc SwaggerItemsObject}.
+	 *
+	 * <h5 class='section'>Notes:</h5>
+	 * <ul class='spaced-list'>
+	 * 	<li>
+	 * 		The format is a plain-text string.
+	 * 	<li>
+	 * 		Supports {@doc DefaultRestSvlVariables}
+	 * 		(e.g. <js>"$L{my.localized.variable}"</js>).
+	 * </ul>
+	 */
+	String[] _enum() default {};
+
+	/**
+	 * <mk>$ref</mk> field of the {@doc SwaggerItemsObject}.
+	 *
+	 * <h5 class='section'>Notes:</h5>
+	 * <ul class='spaced-list'>
+	 * 	<li>
+	 * 		The format is a plain-text string.
+	 * 	<li>
+	 * 		Supports {@doc DefaultRestSvlVariables}
+	 * 		(e.g. <js>"$L{my.localized.variable}"</js>).
+	 * </ul>
+	 */
+	String $ref() default "";
+
+	/**
+	 * <mk>items</mk> field of the {@doc SwaggerItemsObject}.
+	 *
+	 * <p>
+	 * Describes the type of items in the array.
+	 *
+	 * <p>
+	 * This is a {@doc juneau-marshall.JsonDetails.SimplifiedJson} object.
+	 * <br>It must be declared free-form because it's not possible to nest annotations in Java.
+	 */
+	String[] items() default {};
+
+	/**
+	 * Free-form value for the {@doc SwaggerItemsObject}.
+	 *
+	 * <p>
+	 * This is a {@doc juneau-marshall.JsonDetails.SimplifiedJson} object that makes up the swagger information for this field.
+	 *
+	 * <p>
+	 * The following are completely equivalent ways of defining the swagger description of an Items object:
+	 * <p class='bcode w800'>
+	 * 	<jc>// Normal</jc>
+	 * 	<ja>@Query</ja>(
+	 * 		name=<js>"status"</js>,
+	 * 		type=<js>"array"</js>,
+	 * 		items=<ja>@Items</ja>(
+	 * 			type=<js>"string"</js>,
+	 * 			_enum=<js>"AVAILABLE,PENDING,SOLD"</js>,
+	 * 			_default=<js>"AVAILABLE"</js>
+	 * 		)
+	 * 	)
+	 * </p>
+	 * <p class='bcode w800'>
+	 * 	<jc>// Free-form</jc>
+	 * 	<ja>@Query</ja>(
+	 * 		name=<js>"status"</js>,
+	 * 		type=<js>"array"</js>,
+	 * 		items=<ja>@Items</ja>({
+	 * 			<js>"type: 'string'"</js>,
+	 * 			<js>"enum: ['AVAILABLE','PENDING','SOLD'],"</js>,
+	 * 			<js>"default: 'AVAILABLE'"</js>
+	 * 		})
+	 * 	)
+	 * </p>
+	 * <p class='bcode w800'>
+	 * 	<jc>// Free-form as part of parent</jc>
+	 * 	<ja>@Query</ja>(
+	 * 		name=<js>"status"</js>,
+	 * 		api={
+	 * 			<js>"type:'array',"</js>,
+	 * 			<js>"items: {"</js>,
+	 * 				<js>"type: 'string',"</js>,
+	 * 				<js>"enum: ['AVAILABLE','PENDING','SOLD'],"</js>,
+	 * 				<js>"default: 'AVAILABLE'"</js>,
+	 * 			<js>"}"</js>)
+	 * 		}
+	 * 	)
+	 * </p>
+	 * <p class='bcode w800'>
+	 * 	<jc>// Free-form with variables</jc>
+	 * 	<ja>@Query</ja>(
+	 * 		name=<js>"status"</js>,
+	 * 		type=<js>"array"</js>,
+	 * 		items=<ja>@Items</ja>(<js>"$L{statusItemsSwagger}"</js>)
+	 * 	)
+	 * </p>
+	 * <p class='bcode w800'>
+	 * 	<mc>// Contents of MyResource.properties</mc>
+	 * 	<mk>statusItemsSwagger</mk> = <mv>{ type: "string", enum: ["AVAILABLE","PENDING","SOLD"], default: "AVAILABLE" }</mv>
+	 * </p>
+	 *
+	 * <p>
+	 * 	The reasons why you may want to use this field include:
+	 * <ul>
+	 * 	<li>You want to pull in the entire Swagger JSON definition for this field from an external source such as a properties file.
+	 * 	<li>You want to add extra fields to the Swagger documentation that are not officially part of the Swagger specification.
+	 * </ul>
+	 *
+	 * <h5 class='section'>Notes:</h5>
+	 * <ul class='spaced-list'>
+	 * 	<li>
+	 * 		Note that the only swagger field you can't specify using this value is <js>"name"</js> whose value needs to be known during servlet initialization.
+	 * 	<li>
+	 * 		The format is a {@doc juneau-marshall.JsonDetails.SimplifiedJson} object.
+	 * 	<li>
+	 * 		The leading/trailing <code>{ }</code> characters are optional.
+	 * 		<br>The following two example are considered equivalent:
+	 * 		<p class='bcode w800'>
+	 * 	<ja>@Items</ja>(api=<js>"{type: 'string'}"</js>)
+	 * 		</p>
+	 * 		<p class='bcode w800'>
+	 * 	<ja>@Items</ja>(api=<js>"type: 'string'"</js>)
+	 * 		</p>
+	 * 	<li>
+	 * 		Multiple lines are concatenated with newlines so that you can format the value to be readable.
+	 * 	<li>
+	 * 		Supports {@doc DefaultRestSvlVariables}
+	 * 		(e.g. <js>"$L{my.localized.variable}"</js>).
+	 * 	<li>
+	 * 		Values defined in this field supersede values pulled from the Swagger JSON file and are superseded by individual values defined on this annotation.
+	 * </ul>
+	 */
+	String[] value() default {};
+}
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/Tag.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/Tag.java
index 8617c24..9162a98 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/Tag.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/Tag.java
@@ -16,7 +16,7 @@ import static java.lang.annotation.RetentionPolicy.*;
 
 import java.lang.annotation.*;
 
-import org.apache.juneau.jsonschema.annotation.*;
+import org.apache.juneau.jsonschema.annotation.ExternalDocs;
 
 /**
  * Swagger tag annotation.
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/httppart/HttpPartSchemaBuilder.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/httppart/HttpPartSchemaBuilder.java
index 793c8e4..00a083c 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/httppart/HttpPartSchemaBuilder.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/httppart/HttpPartSchemaBuilder.java
@@ -21,10 +21,12 @@ import java.util.regex.*;
 
 import org.apache.juneau.*;
 import org.apache.juneau.http.annotation.*;
+import org.apache.juneau.jsonschema.annotation.Schema;
+import org.apache.juneau.jsonschema.annotation.Items;
+import org.apache.juneau.jsonschema.annotation.SubItems;
 import org.apache.juneau.httppart.HttpPartSchema.*;
 import org.apache.juneau.httppart.HttpPartSchema.Type;
 import org.apache.juneau.internal.*;
-import org.apache.juneau.jsonschema.annotation.*;
 import org.apache.juneau.utils.*;
 
 /**
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/json/SimpleJsonSerializer.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/json/SimpleJsonSerializer.java
index b66d72f..7f84971 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/json/SimpleJsonSerializer.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/json/SimpleJsonSerializer.java
@@ -43,10 +43,10 @@ public class SimpleJsonSerializer extends JsonSerializer {
 	//-------------------------------------------------------------------------------------------------------------------
 
 	/** Default serializer, single quotes, {@link #JSON_simpleMode simple mode}. */
-	public static final SimpleJsonSerializer DEFAULT = new SimpleJsonSerializer(PropertyStore.DEFAULT);
+	public static final JsonSerializer DEFAULT = new SimpleJsonSerializer(PropertyStore.DEFAULT);
 
 	/** Default serializer, single quotes, simple mode, with whitespace. */
-	public static final SimpleJsonSerializer DEFAULT_READABLE = new Readable(PropertyStore.DEFAULT);
+	public static final JsonSerializer DEFAULT_READABLE = new Readable(PropertyStore.DEFAULT);
 
 	//-------------------------------------------------------------------------------------------------------------------
 	// Predefined subclasses
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/util/FinishablePrintWriter.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/jsonschema/annotation/JsonSchema.java
similarity index 60%
copy from juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/util/FinishablePrintWriter.java
copy to juneau-core/juneau-marshall/src/main/java/org/apache/juneau/jsonschema/annotation/JsonSchema.java
index 63495c5..3a9c9b8 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/util/FinishablePrintWriter.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/jsonschema/annotation/JsonSchema.java
@@ -10,42 +10,43 @@
 // * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
 // * specific language governing permissions and limitations under the License.                                              *
 // ***************************************************************************************************************************
-package org.apache.juneau.rest.util;
+package org.apache.juneau.jsonschema.annotation;
 
-import java.io.*;
+import static java.lang.annotation.ElementType.*;
+import static java.lang.annotation.RetentionPolicy.*;
 
-import org.apache.juneau.encoders.*;
+import java.lang.annotation.*;
 
 /**
- * A wrapped {@link PrintWriter} with an added <code>finish()</code> method.
+ * @deprecated Use {@link Schema}
  */
-public class FinishablePrintWriter extends PrintWriter implements Finishable {
+@Documented
+@Target({TYPE,METHOD,FIELD})
+@Retention(RUNTIME)
+@Inherited
+@Deprecated
+public @interface JsonSchema {
 
-	final Finishable f;
+	/**
+	 * Defines the type for the class or property.
+	 */
+	String type() default "";
 
 	/**
-	 * Constructor.
-	 *
-	 * @param out The wrapped output stream.
-	 * @param characterEncoding The character encoding of the output stream.
-	 * @param autoFlush Automatically flush after every println.
-	 * @throws IOException
+	 * Defines the format for the class or property.
 	 */
-	public FinishablePrintWriter(OutputStream out, String characterEncoding, boolean autoFlush) throws IOException {
-		super(new OutputStreamWriter(out, characterEncoding), autoFlush);
-		f = (out instanceof Finishable ? (Finishable)out : null);
-	}
+	String format() default "";
 
+	/**
+	 * Defines the description for the class or property.
+	 */
+	String description() default "";
 
 	/**
-	 * Calls {@link Finishable#finish()} on the underlying output stream.
+	 * Defines the example for the class or property.
 	 *
 	 * <p>
-	 * A no-op if the underlying output stream does not implement the {@link Finishable} interface.
+	 * The format of the value is Lax-JSON.
 	 */
-	@Override /* Finishable */
-	public void finish() throws IOException {
-		if (f != null)
-			f.finish();
-	}
+	String example() default "";
 }
diff --git a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/AtomFeedResource.java b/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/AtomFeedResource.java
index 97bddad..be7622f 100644
--- a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/AtomFeedResource.java
+++ b/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/AtomFeedResource.java
@@ -18,11 +18,11 @@ import static org.apache.juneau.jena.RdfSerializer.*;
 
 import java.net.*;
 
+import org.apache.juneau.jsonschema.annotation.ExternalDocs;
 import org.apache.juneau.dto.atom.*;
 import org.apache.juneau.encoders.*;
 import org.apache.juneau.http.annotation.*;
 import org.apache.juneau.http.annotation.Body;
-import org.apache.juneau.jsonschema.annotation.*;
 import org.apache.juneau.microservice.*;
 import org.apache.juneau.rest.annotation.*;
 import org.apache.juneau.rest.widget.*;
diff --git a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/CodeFormatterResource.java b/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/CodeFormatterResource.java
index ef514ca..003aa9e 100644
--- a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/CodeFormatterResource.java
+++ b/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/CodeFormatterResource.java
@@ -15,10 +15,10 @@ package org.apache.juneau.examples.rest;
 import static org.apache.juneau.dto.html5.HtmlBuilder.*;
 import static org.apache.juneau.http.HttpMethodName.*;
 
+import org.apache.juneau.jsonschema.annotation.ExternalDocs;
 import org.apache.juneau.dto.html5.*;
 import org.apache.juneau.http.annotation.*;
 import org.apache.juneau.http.annotation.FormData;
-import org.apache.juneau.jsonschema.annotation.*;
 import org.apache.juneau.rest.*;
 import org.apache.juneau.rest.annotation.*;
 
diff --git a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/DockerRegistryResource.java b/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/DockerRegistryResource.java
index 639e468..1f606df 100644
--- a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/DockerRegistryResource.java
+++ b/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/DockerRegistryResource.java
@@ -16,10 +16,10 @@ import static org.apache.juneau.rest.annotation.HookEvent.*;
 
 import java.util.*;
 
+import org.apache.juneau.jsonschema.annotation.ExternalDocs;
 import org.apache.juneau.config.*;
 import org.apache.juneau.http.annotation.*;
 import org.apache.juneau.http.annotation.Query;
-import org.apache.juneau.jsonschema.annotation.*;
 import org.apache.juneau.rest.*;
 import org.apache.juneau.rest.annotation.*;
 import org.apache.juneau.rest.client.*;
diff --git a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/JsonSchemaResource.java b/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/JsonSchemaResource.java
index 5fda93a..b5e264e 100644
--- a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/JsonSchemaResource.java
+++ b/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/JsonSchemaResource.java
@@ -14,10 +14,10 @@ package org.apache.juneau.examples.rest;
 
 import static org.apache.juneau.BeanContext.*;
 
+import org.apache.juneau.jsonschema.annotation.ExternalDocs;
 import org.apache.juneau.dto.jsonschema.*;
 import org.apache.juneau.http.annotation.*;
 import org.apache.juneau.http.annotation.Body;
-import org.apache.juneau.jsonschema.annotation.*;
 import org.apache.juneau.microservice.*;
 import org.apache.juneau.rest.annotation.*;
 import org.apache.juneau.rest.widget.*;
diff --git a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/MethodExampleResource.java b/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/MethodExampleResource.java
index 8733ad1..ded7145 100644
--- a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/MethodExampleResource.java
+++ b/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/MethodExampleResource.java
@@ -14,12 +14,12 @@ package org.apache.juneau.examples.rest;
 
 import java.util.*;
 
+import org.apache.juneau.jsonschema.annotation.ExternalDocs;
 import org.apache.juneau.http.*;
 import org.apache.juneau.http.annotation.*;
 import org.apache.juneau.http.annotation.Header;
 import org.apache.juneau.http.annotation.Path;
 import org.apache.juneau.http.annotation.Query;
-import org.apache.juneau.jsonschema.annotation.*;
 import org.apache.juneau.rest.*;
 import org.apache.juneau.rest.annotation.*;
 import org.apache.juneau.rest.helper.*;
diff --git a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/PhotosResource.java b/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/PhotosResource.java
index 34f932c..8f26e0e 100644
--- a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/PhotosResource.java
+++ b/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/PhotosResource.java
@@ -15,6 +15,7 @@ package org.apache.juneau.examples.rest;
 import static org.apache.juneau.html.HtmlSerializer.*;
 import static org.apache.juneau.http.HttpMethodName.*;
 
+import org.apache.juneau.jsonschema.annotation.ExternalDocs;
 import java.awt.image.*;
 import java.io.*;
 import java.net.*;
@@ -26,7 +27,6 @@ import org.apache.juneau.*;
 import org.apache.juneau.http.annotation.*;
 import org.apache.juneau.http.annotation.Body;
 import org.apache.juneau.http.annotation.Path;
-import org.apache.juneau.jsonschema.annotation.*;
 import org.apache.juneau.parser.*;
 import org.apache.juneau.rest.*;
 import org.apache.juneau.rest.annotation.*;
diff --git a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/PredefinedLabelsResource.java b/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/PredefinedLabelsResource.java
index 80ef270..56af271 100644
--- a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/PredefinedLabelsResource.java
+++ b/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/PredefinedLabelsResource.java
@@ -12,10 +12,10 @@
 // ***************************************************************************************************************************
 package org.apache.juneau.examples.rest;
 
+import org.apache.juneau.jsonschema.annotation.ExternalDocs;
 import org.apache.juneau.dto.*;
 import org.apache.juneau.examples.addressbook.*;
 import org.apache.juneau.http.annotation.*;
-import org.apache.juneau.jsonschema.annotation.*;
 import org.apache.juneau.rest.*;
 import org.apache.juneau.rest.annotation.*;
 import org.apache.juneau.rest.helper.*;
diff --git a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/RequestEchoResource.java b/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/RequestEchoResource.java
index 50cd9bd..5878c63 100644
--- a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/RequestEchoResource.java
+++ b/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/RequestEchoResource.java
@@ -17,8 +17,8 @@ import static org.apache.juneau.serializer.Serializer.*;
 import javax.servlet.*;
 import javax.servlet.http.*;
 
+import org.apache.juneau.jsonschema.annotation.ExternalDocs;
 import org.apache.juneau.http.annotation.*;
-import org.apache.juneau.jsonschema.annotation.*;
 import org.apache.juneau.rest.*;
 import org.apache.juneau.rest.annotation.*;
 import org.apache.juneau.rest.converters.*;
diff --git a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/SampleRrpcServlet.java b/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/SampleRrpcServlet.java
index 1f6f706..69dd800 100644
--- a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/SampleRrpcServlet.java
+++ b/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/SampleRrpcServlet.java
@@ -15,9 +15,9 @@ package org.apache.juneau.examples.rest;
 import java.util.*;
 import java.util.Map;
 
+import org.apache.juneau.jsonschema.annotation.ExternalDocs;
 import org.apache.juneau.examples.addressbook.*;
 import org.apache.juneau.http.annotation.*;
-import org.apache.juneau.jsonschema.annotation.*;
 import org.apache.juneau.rest.annotation.*;
 import org.apache.juneau.rest.remote.*;
 
diff --git a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/SqlQueryResource.java b/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/SqlQueryResource.java
index 6d90767..993fc88 100644
--- a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/SqlQueryResource.java
+++ b/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/SqlQueryResource.java
@@ -20,13 +20,13 @@ import static org.apache.juneau.rest.annotation.HookEvent.*;
 import java.sql.*;
 import java.util.*;
 
+import org.apache.juneau.jsonschema.annotation.ExternalDocs;
 import org.apache.juneau.config.*;
 import org.apache.juneau.dto.*;
 import org.apache.juneau.dto.html5.*;
 import org.apache.juneau.http.annotation.*;
 import org.apache.juneau.http.annotation.Body;
 import org.apache.juneau.http.annotation.Query;
-import org.apache.juneau.jsonschema.annotation.*;
 import org.apache.juneau.rest.*;
 import org.apache.juneau.rest.annotation.*;
 import org.apache.juneau.rest.exception.*;
diff --git a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/SystemPropertiesResource.java b/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/SystemPropertiesResource.java
index 8c24a1d..022e2fc 100644
--- a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/SystemPropertiesResource.java
+++ b/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/SystemPropertiesResource.java
@@ -19,6 +19,7 @@ import static org.apache.juneau.serializer.WriterSerializer.*;
 import java.util.*;
 import java.util.Map;
 
+import org.apache.juneau.jsonschema.annotation.ExternalDocs;
 import org.apache.juneau.dto.html5.*;
 import org.apache.juneau.encoders.*;
 import org.apache.juneau.http.annotation.*;
@@ -27,7 +28,6 @@ import org.apache.juneau.http.annotation.FormData;
 import org.apache.juneau.http.annotation.Path;
 import org.apache.juneau.http.annotation.Query;
 import org.apache.juneau.http.annotation.Response;
-import org.apache.juneau.jsonschema.annotation.*;
 import org.apache.juneau.rest.*;
 import org.apache.juneau.rest.annotation.*;
 import org.apache.juneau.rest.exception.*;
diff --git a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/TempDirResource.java b/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/TempDirResource.java
index 120c1d6..f7f34f6 100644
--- a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/TempDirResource.java
+++ b/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/TempDirResource.java
@@ -19,12 +19,12 @@ import static org.apache.juneau.microservice.resources.DirectoryResource.*;
 
 import java.io.*;
 
+import org.apache.juneau.jsonschema.annotation.ExternalDocs;
 import org.apache.commons.fileupload.*;
 import org.apache.commons.fileupload.servlet.*;
 import org.apache.commons.io.*;
 import org.apache.juneau.dto.html5.*;
 import org.apache.juneau.http.annotation.*;
-import org.apache.juneau.jsonschema.annotation.*;
 import org.apache.juneau.microservice.resources.*;
 import org.apache.juneau.rest.*;
 import org.apache.juneau.rest.annotation.*;
diff --git a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/UrlEncodedFormResource.java b/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/UrlEncodedFormResource.java
index 265918a..0b082f4 100644
--- a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/UrlEncodedFormResource.java
+++ b/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/UrlEncodedFormResource.java
@@ -17,11 +17,11 @@ import static org.apache.juneau.http.HttpMethodName.*;
 
 import java.util.*;
 
+import org.apache.juneau.jsonschema.annotation.ExternalDocs;
 import org.apache.juneau.annotation.*;
 import org.apache.juneau.dto.html5.*;
 import org.apache.juneau.http.annotation.*;
 import org.apache.juneau.http.annotation.Body;
-import org.apache.juneau.jsonschema.annotation.*;
 import org.apache.juneau.rest.*;
 import org.apache.juneau.rest.annotation.*;
 import org.apache.juneau.rest.widget.*;
diff --git a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/addressbook/AddressBookResource.java b/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/addressbook/AddressBookResource.java
index 9e49db7..6e01c6a 100644
--- a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/addressbook/AddressBookResource.java
+++ b/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/addressbook/AddressBookResource.java
@@ -28,7 +28,7 @@ import org.apache.juneau.examples.rest.*;
 import org.apache.juneau.http.annotation.*;
 import org.apache.juneau.http.annotation.Body;
 import org.apache.juneau.http.annotation.Path;
-import org.apache.juneau.jsonschema.annotation.*;
+import org.apache.juneau.jsonschema.annotation.ExternalDocs;
 import org.apache.juneau.microservice.*;
 import org.apache.juneau.rest.*;
 import org.apache.juneau.rest.annotation.*;
diff --git a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/PetStore.java b/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/PetStore.java
index 24c0cfc..77cb2ea 100644
--- a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/PetStore.java
+++ b/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/PetStore.java
@@ -16,10 +16,10 @@ import static org.apache.juneau.http.HttpMethodName.*;
 
 import java.util.*;
 
+import org.apache.juneau.jsonschema.annotation.Items;
 import org.apache.juneau.*;
 import org.apache.juneau.examples.rest.petstore.dto.*;
 import org.apache.juneau.http.annotation.*;
-import org.apache.juneau.jsonschema.annotation.*;
 import org.apache.juneau.rest.*;
 import org.apache.juneau.rest.client.remote.*;
 import org.apache.juneau.rest.exception.*;
diff --git a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/PetStoreResource.java b/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/PetStoreResource.java
index 91ca786..ed583df 100644
--- a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/PetStoreResource.java
+++ b/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/PetStoreResource.java
@@ -21,6 +21,7 @@ import static org.apache.juneau.rest.response.Ok.*;
 import java.util.*;
 import java.util.Map;
 
+import org.apache.juneau.jsonschema.annotation.ExternalDocs;
 import org.apache.juneau.*;
 import org.apache.juneau.dto.html5.*;
 import org.apache.juneau.examples.rest.petstore.dto.*;
@@ -28,7 +29,6 @@ import org.apache.juneau.http.annotation.*;
 import org.apache.juneau.http.annotation.FormData;
 import org.apache.juneau.http.annotation.Path;
 import org.apache.juneau.internal.*;
-import org.apache.juneau.jsonschema.annotation.*;
 import org.apache.juneau.microservice.*;
 import org.apache.juneau.rest.*;
 import org.apache.juneau.rest.annotation.*;
diff --git a/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestClient.java b/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestClient.java
index 5082e9f..9c56e5d 100644
--- a/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestClient.java
+++ b/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestClient.java
@@ -1260,6 +1260,32 @@ public class RestClient extends BeanContext implements Closeable {
 		}
 	}
 
+	/**
+	 * @deprecated Use {@link #getRrpcInterface(Class)}
+	 */
+	@SuppressWarnings("javadoc")
+	@Deprecated
+	public <T> T getRemoteInterface(final Class<T> interfaceClass) {
+		return getRrpcInterface(interfaceClass, null);
+	}
+
+	/**
+	 * @deprecated Use {@link #getRrpcInterface(Class,Object)}
+	 */
+	@SuppressWarnings("javadoc")
+	@Deprecated
+	public <T> T getRemoteInterface(final Class<T> interfaceClass, final Object restUrl) {
+		return getRrpcInterface(interfaceClass, restUrl, serializer, parser);
+	}
+
+	/**
+	 * @deprecated Use {@link #getRrpcInterface(Class,Object,Serializer,Parser)}
+	 */
+	@SuppressWarnings("javadoc")
+	@Deprecated
+	public <T> T getRemoteInterface(final Class<T> interfaceClass, Object restUrl, final Serializer serializer, final Parser parser) {
+		return getRrpcInterface(interfaceClass, restUrl, serializer, parser);
+	}
 
 	static final String getName(String name1, String name2, BeanPropertyMeta pMeta) {
 		String n = name1.isEmpty() ? name2 : name1;
diff --git a/juneau-rest/juneau-rest-client/src/test/java/org/apache/juneau/rest/client/remote/EndToEndInterfaceTest.java b/juneau-rest/juneau-rest-client/src/test/java/org/apache/juneau/rest/client/remote/EndToEndInterfaceTest.java
index 55d3523..987c5e4 100644
--- a/juneau-rest/juneau-rest-client/src/test/java/org/apache/juneau/rest/client/remote/EndToEndInterfaceTest.java
+++ b/juneau-rest/juneau-rest-client/src/test/java/org/apache/juneau/rest/client/remote/EndToEndInterfaceTest.java
@@ -17,7 +17,8 @@ import static org.junit.Assert.*;
 
 import java.io.*;
 
-import org.apache.juneau.http.*;
+import org.apache.juneau.http.ReaderResource;
+import org.apache.juneau.http.StreamResource;
 import org.apache.juneau.http.annotation.Body;
 import org.apache.juneau.http.annotation.Header;
 import org.apache.juneau.http.annotation.Query;
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/SwaggerGenerator.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/SwaggerGenerator.java
index 4f3c927..c4564c2 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/SwaggerGenerator.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/SwaggerGenerator.java
@@ -21,6 +21,10 @@ import java.lang.reflect.*;
 import java.lang.reflect.Method;
 import java.util.*;
 
+import org.apache.juneau.jsonschema.annotation.ExternalDocs;
+import org.apache.juneau.jsonschema.annotation.Schema;
+import org.apache.juneau.jsonschema.annotation.SubItems;
+import org.apache.juneau.jsonschema.annotation.Items;
 import org.apache.juneau.*;
 import org.apache.juneau.dto.swagger.*;
 import org.apache.juneau.http.*;
@@ -37,8 +41,6 @@ import org.apache.juneau.http.annotation.Tag;
 import org.apache.juneau.internal.*;
 import org.apache.juneau.json.*;
 import org.apache.juneau.jsonschema.*;
-import org.apache.juneau.jsonschema.annotation.*;
-import org.apache.juneau.jsonschema.annotation.Items;
 import org.apache.juneau.parser.*;
 import org.apache.juneau.rest.annotation.*;
 import org.apache.juneau.rest.util.RestUtils;
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/ResourceSwagger.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/ResourceSwagger.java
index 1aae95b..784c1cf 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/ResourceSwagger.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/ResourceSwagger.java
@@ -12,8 +12,8 @@
 // ***************************************************************************************************************************
 package org.apache.juneau.rest.annotation;
 
+import org.apache.juneau.jsonschema.annotation.ExternalDocs;
 import org.apache.juneau.http.annotation.*;
-import org.apache.juneau.jsonschema.annotation.*;
 
 /**
  * Extended annotation for {@link RestResource#swagger() @RestResource(swagger)}.
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/helper/ReaderResource.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/helper/ReaderResource.java
new file mode 100644
index 0000000..587e21b
--- /dev/null
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/helper/ReaderResource.java
@@ -0,0 +1,150 @@
+// ***************************************************************************************************************************
+// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
+// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
+// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
+// * with the License.  You may obtain a copy of the License at                                                              *
+// *                                                                                                                         *
+// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
+// *                                                                                                                         *
+// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
+// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
+// * specific language governing permissions and limitations under the License.                                              *
+// ***************************************************************************************************************************
+package org.apache.juneau.rest.helper;
+
+import static org.apache.juneau.internal.CollectionUtils.*;
+import static org.apache.juneau.internal.IOUtils.*;
+
+import java.io.*;
+import java.util.*;
+
+import org.apache.juneau.*;
+import org.apache.juneau.http.*;
+import org.apache.juneau.http.annotation.*;
+import org.apache.juneau.svl.*;
+
+/**
+ * @deprecated Use {@link org.apache.juneau.http.ReaderResource}
+ */
+@Response
+@Deprecated
+public class ReaderResource implements Writable {
+
+	private final MediaType mediaType;
+	private final String[] contents;
+	private final VarResolverSession varSession;
+	private final Map<String,Object> headers;
+
+	/**
+	 * Creates a new instance of a {@link ReaderResourceBuilder}
+	 *
+	 * @return A new instance of a {@link ReaderResourceBuilder}
+	 */
+	public static ReaderResourceBuilder create() {
+		return new ReaderResourceBuilder();
+	}
+
+	/**
+	 * Constructor.
+	 *
+	 * @param mediaType The resource media type.
+	 * @param headers The HTTP response headers for this streamed resource.
+	 * @param varSession Optional variable resolver for resolving variables in the string.
+	 * @param contents
+	 * 	The resource contents.
+	 * 	<br>If multiple contents are specified, the results will be concatenated.
+	 * 	<br>Contents can be any of the following:
+	 * 	<ul>
+	 * 		<li><code>InputStream</code>
+	 * 		<li><code>Reader</code> - Converted to UTF-8 bytes.
+	 * 		<li><code>File</code>
+	 * 		<li><code>CharSequence</code> - Converted to UTF-8 bytes.
+	 * 	</ul>
+	 * @throws IOException
+	 */
+	public ReaderResource(MediaType mediaType, Map<String,Object> headers, VarResolverSession varSession, Object...contents) throws IOException {
+		this.mediaType = mediaType;
+		this.varSession = varSession;
+
+		this.headers = immutableMap(headers);
+
+		this.contents = new String[contents.length];
+		for (int i = 0; i < contents.length; i++) {
+			Object c = contents[i];
+			if (c == null)
+				this.contents[i] = "";
+			else if (c instanceof InputStream)
+				this.contents[i] = read((InputStream)c);
+			else if (c instanceof File)
+				this.contents[i] = read((File)c);
+			else if (c instanceof Reader)
+				this.contents[i] = read((Reader)c);
+			else if (c instanceof CharSequence)
+				this.contents[i] = ((CharSequence)c).toString();
+			else
+				throw new IOException("Invalid class type passed to ReaderResource: " + c.getClass().getName());
+		}
+	}
+
+	/**
+	 * Get the HTTP response headers.
+	 *
+	 * @return
+	 * 	The HTTP response headers.
+	 * 	<br>An unmodifiable map.
+	 * 	<br>Never <jk>null</jk>.
+	 */
+	@ResponseHeader("*")
+	public Map<String,Object> getHeaders() {
+		return headers;
+	}
+
+	@ResponseBody
+	@Override /* Writeable */
+	public Writer writeTo(Writer w) throws IOException {
+		for (String s : contents) {
+			if (varSession != null)
+				varSession.resolveTo(s, w);
+			else
+				w.write(s);
+		}
+		return w;
+	}
+
+	@ResponseHeader("Content-Type")
+	@Override /* Writeable */
+	public MediaType getMediaType() {
+		return mediaType;
+	}
+
+	@Override /* Object */
+	public String toString() {
+		if (contents.length == 1 && varSession == null)
+			return contents[0];
+		StringWriter sw = new StringWriter();
+		for (String s : contents) {
+			if (varSession != null)
+				return varSession.resolve(s);
+			sw.write(s);
+		}
+		return sw.toString();
+	}
+
+	/**
+	 * Same as {@link #toString()} but strips comments from the text before returning it.
+	 *
+	 * <p>
+	 * Supports stripping comments from the following media types: HTML, XHTML, XML, JSON, Javascript, CSS.
+	 *
+	 * @return The resource contents stripped of any comments.
+	 */
+	public String toCommentStrippedString() {
+		String s = toString();
+		String subType = mediaType.getSubType();
+		if ("html".equals(subType) || "xhtml".equals(subType) || "xml".equals(subType))
+			s = s.replaceAll("(?s)<!--(.*?)-->\\s*", "");
+		else if ("json".equals(subType) || "javascript".equals(subType) || "css".equals(subType))
+			s = s.replaceAll("(?s)\\/\\*(.*?)\\*\\/\\s*", "");
+		return s;
+	}
+}
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/helper/ReaderResourceBuilder.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/helper/ReaderResourceBuilder.java
new file mode 100644
index 0000000..a607de3
--- /dev/null
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/helper/ReaderResourceBuilder.java
@@ -0,0 +1,123 @@
+// ***************************************************************************************************************************
+// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
+// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
+// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
+// * with the License.  You may obtain a copy of the License at                                                              *
+// *                                                                                                                         *
+// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
+// *                                                                                                                         *
+// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
+// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
+// * specific language governing permissions and limitations under the License.                                              *
+// ***************************************************************************************************************************
+package org.apache.juneau.rest.helper;
+
+import java.io.*;
+import java.util.*;
+
+import org.apache.juneau.http.*;
+import org.apache.juneau.svl.*;
+
+/**
+ * @deprecated Use {@link org.apache.juneau.http.ReaderResource#create()}
+ */
+@Deprecated
+public final class ReaderResourceBuilder {
+	ArrayList<Object> contents = new ArrayList<>();
+	MediaType mediaType;
+	VarResolverSession varResolver;
+	Map<String,Object> headers = new LinkedHashMap<>();
+
+	/**
+	 * Specifies the resource media type string.
+	 *
+	 * @param mediaType The resource media type string.
+	 * @return This object (for method chaining).
+	 */
+	public ReaderResourceBuilder mediaType(String mediaType) {
+		this.mediaType = MediaType.forString(mediaType);
+		return this;
+	}
+
+	/**
+	 * Specifies the resource media type string.
+	 *
+	 * @param mediaType The resource media type string.
+	 * @return This object (for method chaining).
+	 */
+	public ReaderResourceBuilder mediaType(MediaType mediaType) {
+		this.mediaType = mediaType;
+		return this;
+	}
+
+	/**
+	 * Specifies the contents for this resource.
+	 *
+	 * <p>
+	 * This method can be called multiple times to add more content.
+	 *
+	 * @param contents
+	 * 	The resource contents.
+	 * 	<br>If multiple contents are specified, the results will be concatenated.
+	 * 	<br>Contents can be any of the following:
+	 * 	<ul>
+	 * 		<li><code>InputStream</code>
+	 * 		<li><code>Reader</code> - Converted to UTF-8 bytes.
+	 * 		<li><code>File</code>
+	 * 		<li><code>CharSequence</code> - Converted to UTF-8 bytes.
+	 * 	</ul>
+	 * @return This object (for method chaining).
+	 */
+	public ReaderResourceBuilder contents(Object...contents) {
+		this.contents.addAll(Arrays.asList(contents));
+		return this;
+	}
+
+	/**
+	 * Specifies an HTTP response header value.
+	 *
+	 * @param name The HTTP header name.
+	 * @param value
+	 * 	The HTTP header value.
+	 * 	<br>Will be converted to a <code>String</code> using {@link Object#toString()}.
+	 * @return This object (for method chaining).
+	 */
+	public ReaderResourceBuilder header(String name, Object value) {
+		this.headers.put(name, value);
+		return this;
+	}
+
+	/**
+	 * Specifies HTTP response header values.
+	 *
+	 * @param headers
+	 * 	The HTTP headers.
+	 * 	<br>Values will be converted to <code>Strings</code> using {@link Object#toString()}.
+	 * @return This object (for method chaining).
+	 */
+	public ReaderResourceBuilder headers(Map<String,Object> headers) {
+		this.headers.putAll(headers);
+		return this;
+	}
+
+	/**
+	 * Specifies the variable resolver to use for this resource.
+	 *
+	 * @param varResolver The variable resolver.
+	 * @return This object (for method chaining).
+	 */
+	public ReaderResourceBuilder varResolver(VarResolverSession varResolver) {
+		this.varResolver = varResolver;
+		return this;
+	}
+
+	/**
+	 * Create a new {@link ReaderResource} using values in this builder.
+	 *
+	 * @return A new immutable {@link ReaderResource} object.
+	 * @throws IOException
+	 */
+	public ReaderResource build() throws IOException {
+		return new ReaderResource(mediaType, headers, varResolver, contents.toArray());
+	}
+}
\ No newline at end of file
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/helper/ResolvingReaderResource.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/helper/ResolvingReaderResource.java
index 08a291b..5a17752 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/helper/ResolvingReaderResource.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/helper/ResolvingReaderResource.java
@@ -14,6 +14,7 @@ package org.apache.juneau.rest.helper;
 
 import static org.apache.juneau.internal.IOUtils.*;
 
+import org.apache.juneau.http.ReaderResource;
 import java.io.*;
 import java.util.*;
 
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/helper/ResourceDescription.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/helper/ResourceDescription.java
index 65c8cef..2ac77a8 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/helper/ResourceDescription.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/helper/ResourceDescription.java
@@ -15,7 +15,7 @@ package org.apache.juneau.rest.helper;
 import org.apache.juneau.annotation.*;
 import org.apache.juneau.html.annotation.*;
 import org.apache.juneau.http.annotation.*;
-import org.apache.juneau.jsonschema.annotation.*;
+import org.apache.juneau.jsonschema.annotation.Schema;
 
 /**
  * Shortcut label for child resources.
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/helper/StreamResource.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/helper/StreamResource.java
new file mode 100644
index 0000000..5833079
--- /dev/null
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/helper/StreamResource.java
@@ -0,0 +1,114 @@
+// ***************************************************************************************************************************
+// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
+// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
+// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
+// * with the License.  You may obtain a copy of the License at                                                              *
+// *                                                                                                                         *
+// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
+// *                                                                                                                         *
+// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
+// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
+// * specific language governing permissions and limitations under the License.                                              *
+// ***************************************************************************************************************************
+package org.apache.juneau.rest.helper;
+
+import static org.apache.juneau.internal.CollectionUtils.*;
+import static org.apache.juneau.internal.IOUtils.*;
+
+import java.io.*;
+import java.util.*;
+
+import org.apache.juneau.*;
+import org.apache.juneau.http.*;
+import org.apache.juneau.http.annotation.*;
+
+/**
+ * @deprecated Use {@link org.apache.juneau.http.StreamResource}
+ */
+@Response
+@Deprecated
+public class StreamResource implements Streamable {
+
+	private final MediaType mediaType;
+	private final byte[][] contents;
+	private final Map<String,Object> headers;
+
+	/**
+	 * Creates a new instance of a {@link StreamResourceBuilder}
+	 *
+	 * @return A new instance of a {@link StreamResourceBuilder}
+	 */
+	public static StreamResourceBuilder create() {
+		return new StreamResourceBuilder();
+	}
+
+	/**
+	 * Constructor.
+	 *
+	 * @param mediaType The resource media type.
+	 * @param headers The HTTP response headers for this streamed resource.
+	 * @param contents
+	 * 	The resource contents.
+	 * 	<br>If multiple contents are specified, the results will be concatenated.
+	 * 	<br>Contents can be any of the following:
+	 * 	<ul>
+	 * 		<li><code><jk>byte</jk>[]</code>
+	 * 		<li><code>InputStream</code>
+	 * 		<li><code>Reader</code> - Converted to UTF-8 bytes.
+	 * 		<li><code>File</code>
+	 * 		<li><code>CharSequence</code> - Converted to UTF-8 bytes.
+	 * 	</ul>
+	 * @throws IOException
+	 */
+	public StreamResource(MediaType mediaType, Map<String,Object> headers, Object...contents) throws IOException {
+		this.mediaType = mediaType;
+
+		this.headers = immutableMap(headers);
+
+		this.contents = new byte[contents.length][];
+		for (int i = 0; i < contents.length; i++) {
+			Object c = contents[i];
+			if (c == null)
+				this.contents[i] = new byte[0];
+			else if (c instanceof byte[])
+				this.contents[i] = (byte[])c;
+			else if (c instanceof InputStream)
+				this.contents[i] = readBytes((InputStream)c, 1024);
+			else if (c instanceof File)
+				this.contents[i] = readBytes((File)c);
+			else if (c instanceof Reader)
+				this.contents[i] = read((Reader)c).getBytes(UTF8);
+			else if (c instanceof CharSequence)
+				this.contents[i] = ((CharSequence)c).toString().getBytes(UTF8);
+			else
+				throw new IOException("Invalid class type passed to StreamResource: " + c.getClass().getName());
+		}
+	}
+
+	/**
+	 * Get the HTTP response headers.
+	 *
+	 * @return
+	 * 	The HTTP response headers.
+	 * 	<br>An unmodifiable map.
+	 * 	<br>Never <jk>null</jk>.
+	 */
+	@ResponseHeader("*")
+	public Map<String,Object> getHeaders() {
+		return headers;
+	}
+
+	@ResponseBody
+	@Override /* Streamable */
+	public void streamTo(OutputStream os) throws IOException {
+		for (byte[] b : contents)
+			os.write(b);
+		os.flush();
+	}
+
+	@ResponseHeader("Content-Type")
+	@Override /* Streamable */
+	public MediaType getMediaType() {
+		return mediaType;
+	}
+}
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/helper/StreamResourceBuilder.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/helper/StreamResourceBuilder.java
new file mode 100644
index 0000000..a9d62fa
--- /dev/null
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/helper/StreamResourceBuilder.java
@@ -0,0 +1,111 @@
+// ***************************************************************************************************************************
+// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
+// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
+// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
+// * with the License.  You may obtain a copy of the License at                                                              *
+// *                                                                                                                         *
+// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
+// *                                                                                                                         *
+// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
+// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
+// * specific language governing permissions and limitations under the License.                                              *
+// ***************************************************************************************************************************
+package org.apache.juneau.rest.helper;
+
+import java.io.*;
+import java.util.*;
+
+import org.apache.juneau.http.*;
+
+/**
+ * @deprecated Use {@link org.apache.juneau.http.StreamResource#create()}
+ */
+@Deprecated
+public final class StreamResourceBuilder {
+	ArrayList<Object> contents = new ArrayList<>();
+	MediaType mediaType;
+	Map<String,Object> headers = new LinkedHashMap<>();
+
+	/**
+	 * Specifies the resource media type string.
+	 *
+	 * @param mediaType The resource media type string.
+	 * @return This object (for method chaining).
+	 */
+	public StreamResourceBuilder mediaType(String mediaType) {
+		this.mediaType = MediaType.forString(mediaType);
+		return this;
+	}
+
+	/**
+	 * Specifies the resource media type string.
+	 *
+	 * @param mediaType The resource media type string.
+	 * @return This object (for method chaining).
+	 */
+	public StreamResourceBuilder mediaType(MediaType mediaType) {
+		this.mediaType = mediaType;
+		return this;
+	}
+
+	/**
+	 * Specifies the contents for this resource.
+	 *
+	 * <p>
+	 * This method can be called multiple times to add more content.
+	 *
+	 * @param contents
+	 * 	The resource contents.
+	 * 	<br>If multiple contents are specified, the results will be concatenated.
+	 * 	<br>Contents can be any of the following:
+	 * 	<ul>
+	 * 		<li><code><jk>byte</jk>[]</code>
+	 * 		<li><code>InputStream</code>
+	 * 		<li><code>Reader</code> - Converted to UTF-8 bytes.
+	 * 		<li><code>File</code>
+	 * 		<li><code>CharSequence</code> - Converted to UTF-8 bytes.
+	 * 	</ul>
+	 * @return This object (for method chaining).
+	 */
+	public StreamResourceBuilder contents(Object...contents) {
+		this.contents.addAll(Arrays.asList(contents));
+		return this;
+	}
+
+	/**
+	 * Specifies an HTTP response header value.
+	 *
+	 * @param name The HTTP header name.
+	 * @param value
+	 * 	The HTTP header value.
+	 * 	<br>Will be converted to a <code>String</code> using {@link Object#toString()}.
+	 * @return This object (for method chaining).
+	 */
+	public StreamResourceBuilder header(String name, Object value) {
+		this.headers.put(name, value);
+		return this;
+	}
+
+	/**
+	 * Specifies HTTP response header values.
+	 *
+	 * @param headers
+	 * 	The HTTP headers.
+	 * 	<br>Values will be converted to <code>Strings</code> using {@link Object#toString()}.
+	 * @return This object (for method chaining).
+	 */
+	public StreamResourceBuilder headers(Map<String,Object> headers) {
+		this.headers.putAll(headers);
+		return this;
+	}
+
+	/**
+	 * Create a new {@link StreamResource} using values in this builder.
+	 *
+	 * @return A new immutable {@link StreamResource} object.
+	 * @throws IOException
+	 */
+	public StreamResource build() throws IOException {
+		return new StreamResource(mediaType, headers, contents.toArray());
+	}
+}
\ No newline at end of file
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/remote/RemoteInterfaceServlet.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/remote/RemoteInterfaceServlet.java
new file mode 100644
index 0000000..b555b2d
--- /dev/null
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/remote/RemoteInterfaceServlet.java
@@ -0,0 +1,230 @@
+// ***************************************************************************************************************************
+// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
+// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
+// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
+// * with the License.  You may obtain a copy of the License at                                                              *
+// *                                                                                                                         *
+// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
+// *                                                                                                                         *
+// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
+// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
+// * specific language governing permissions and limitations under the License.                                              *
+// ***************************************************************************************************************************
+package org.apache.juneau.rest.remote;
+
+import static org.apache.juneau.dto.html5.HtmlBuilder.*;
+import static org.apache.juneau.http.HttpMethodName.*;
+import static org.apache.juneau.internal.StringUtils.*;
+
+import java.io.*;
+import java.lang.reflect.*;
+import java.util.*;
+import java.util.Map;
+import java.util.concurrent.*;
+
+import org.apache.juneau.dto.*;
+import org.apache.juneau.dto.html5.*;
+import org.apache.juneau.http.*;
+import org.apache.juneau.http.annotation.Header;
+import org.apache.juneau.http.annotation.Path;
+import org.apache.juneau.internal.*;
+import org.apache.juneau.parser.*;
+import org.apache.juneau.remote.*;
+import org.apache.juneau.rest.*;
+import org.apache.juneau.rest.annotation.*;
+import org.apache.juneau.rest.exception.*;
+
+/**
+ * @deprecated Use {@link RrpcServlet}
+ * </ul>
+ */
+@SuppressWarnings({"serial","javadoc"})
+@Deprecated
+public abstract class RemoteInterfaceServlet extends BasicRestServlet {
+
+	private final Map<String,RemoteInterfaceMeta> serviceMap = new ConcurrentHashMap<>();
+
+	//-----------------------------------------------------------------------------------------------------------------
+	// Abstract methods
+	//-----------------------------------------------------------------------------------------------------------------
+
+	/**
+	 * Returns the list of interfaces to their implementation objects.
+	 *
+	 * <p>
+	 * This class is called often and not cached, so any caching should occur in the subclass if necessary.
+	 *
+	 * @return The service map.
+	 * @throws Exception
+	 */
+	protected abstract Map<Class<?>,Object> getServiceMap() throws Exception;
+
+	//-----------------------------------------------------------------------------------------------------------------
+	// REST methods
+	//-----------------------------------------------------------------------------------------------------------------
+
+	@RestMethod(
+		name=GET,
+		path="/",
+		summary="List of available remote interfaces",
+		description="Shows a list of the interfaces registered with this remote interface servlet."
+	)
+	public List<LinkString> getInterfaces() throws Exception {
+		List<LinkString> l = new LinkedList<>();
+		for (Class<?> c : getServiceMap().keySet())
+			l.add(new LinkString(c.getName(), "servlet:/{0}", urlEncode(c.getName())));
+		return l;
+	}
+
+	@RestMethod(
+		name=GET,
+		path="/{javaInterface}",
+		summary="List of available methods on interface",
+		description="Shows a list of all the exposed methods on an interface.",
+		htmldoc=@HtmlDoc(
+			nav="<h5>Interface:  $RP{javaInterface}</h5>"
+		)
+	)
+	public Collection<LinkString> listMethods(
+			@Path(name="javaInterface", description="Java interface name", example="com.foo.MyInterface") String javaInterface
+		) throws Exception {
+
+		List<LinkString> l = new ArrayList<>();
+		for (String s : getMethods(javaInterface).keySet())
+			l.add(new LinkString(s, "servlet:/{0}/{1}", urlEncode(javaInterface), urlEncode(s)));
+		return l;
+	}
+
+	@RestMethod(
+		name=GET,
+		path="/{javaInterface}/{javaMethod}",
+		summary="Form entry for interface method call",
+		description="Shows a form entry page for executing a remote interface method.",
+		htmldoc=@HtmlDoc(
+			nav={
+				"<h5>Interface:  $RP{javaInterface}</h5>",
+				"<h5>Method:  $RP{javaMethod}</h5>"
+			}
+		)
+	)
+	public Div showEntryForm(
+			@Path(name="javaInterface", description="Java interface name", example="com.foo.MyInterface") String javaInterface,
+			@Path(name="javaMethod", description="Java method name", example="myMethod") String javaMethod
+		) throws NotFound, Exception {
+
+		// Find the method.
+		RemoteInterfaceMethod rmm = getMethods(javaInterface).get(javaMethod);
+		if (rmm == null)
+			throw new NotFound("Method not found");
+
+		Table t = table();
+
+		Type[] types = rmm.getJavaMethod().getGenericParameterTypes();
+		if (types.length == 0) {
+			t.child(tr(td("No arguments").colspan(3).style("text-align:center")));
+		} else {
+			t.child(tr(th("Index"),th("Type"),th("Value")));
+			for (int i = 0; i < types.length; i++) {
+				String type = ClassUtils.toString(types[i]);
+				t.child(tr(td(i), td(type), td(input().name(String.valueOf(i)).type("text"))));
+			}
+		}
+
+		t.child(
+			tr(
+				td().colspan(3).style("text-align:right").children(
+					types.length == 0 ? null : button("reset", "Reset"),
+					button("button","Cancel").onclick("window.location.href='/'"),
+					button("submit", "Submit")
+				)
+			)
+		);
+
+		return div(form().id("form").action("request:/").method(POST).children(t));
+	}
+
+	@RestMethod(
+		name=POST,
+		path="/{javaInterface}/{javaMethod}",
+		summary="Invoke an interface method",
+		description="Invoke a Java method by passing in the arguments as an array of serialized objects.\nThe returned object is then serialized to the response.",
+		htmldoc=@HtmlDoc(
+			nav= {
+				"<h5>Interface:  $RP{javaInterface}</h5>",
+				"<h5>Method:  $RP{javaMethod}</h5>"
+			}
+		),
+		swagger=@MethodSwagger(
+			parameters= {
+				"{",
+					"in: 'body',",
+					"description: 'Serialized array of Java objects',",
+					"schema: {",
+						"type': 'array'",
+					"},",
+					"x-examples: {",
+						"'application/json+lax': '[\\'foo\\', 123, true]'",
+					"}",
+				"}"
+			},
+			responses= {
+				"200:{ description:'The return object serialized', schema:{type:'any'},'x-example':{foo:123} }",
+			}
+		)
+	)
+	public Object invoke(
+			Reader r,
+			ReaderParser p,
+			@Header("Content-Type") ContentType contentType,
+			@Path(name="javaInterface", description="Java interface name", example="com.foo.MyInterface") String javaInterface,
+			@Path(name="javaMethod", description="Java method name", example="myMethod") String javaMethod
+		) throws UnsupportedMediaType, NotFound, Exception {
+
+		// Find the parser.
+		if (p == null)
+			throw new UnsupportedMediaType("Could not find parser for media type ''{0}''", contentType);
+		RemoteInterfaceMeta rim = getInterfaceClass(javaInterface);
+
+		// Find the service.
+		Object service = getServiceMap().get(rim.getJavaClass());
+		if (service == null)
+			throw new NotFound("Service not found");
+
+		// Find the method.
+		RemoteInterfaceMethod rmm = getMethods(javaInterface).get(javaMethod);
+		if (rmm == null)
+			throw new NotFound("Method not found");
+
+		// Parse the args and invoke the method.
+		java.lang.reflect.Method m = rmm.getJavaMethod();
+		Object[] params = p.parseArgs(r, m.getGenericParameterTypes());
+		return m.invoke(service, params);
+	}
+
+
+	//-----------------------------------------------------------------------------------------------------------------
+	// Other methods
+	//-----------------------------------------------------------------------------------------------------------------
+
+	private Map<String,RemoteInterfaceMethod> getMethods(String javaInterface) throws Exception {
+		return getInterfaceClass(javaInterface).getMethodsByPath();
+	}
+
+	/**
+	 * Return the <code>Class</code> given it's name if it exists in the services map.
+	 */
+	private RemoteInterfaceMeta getInterfaceClass(String javaInterface) throws NotFound, Exception {
+		RemoteInterfaceMeta rm = serviceMap.get(javaInterface);
+		if (rm == null) {
+			for (Class<?> c : getServiceMap().keySet()) {
+				if (c.getName().equals(javaInterface)) {
+					rm = new RemoteInterfaceMeta(c, null);
+					serviceMap.put(javaInterface, rm);
+					return rm;
+				}
+			}
+			throw new NotFound("Interface class not found");
+		}
+		return rm;
+	}
+}
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/util/FinishablePrintWriter.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/util/FinishablePrintWriter.java
index 63495c5..840a022 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/util/FinishablePrintWriter.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/util/FinishablePrintWriter.java
@@ -36,6 +36,14 @@ public class FinishablePrintWriter extends PrintWriter implements Finishable {
 		f = (out instanceof Finishable ? (Finishable)out : null);
 	}
 
+	/**
+	 * @deprecated Use {@link #FinishablePrintWriter(OutputStream, String, boolean)}
+	 */
+	@SuppressWarnings("javadoc")
+	@Deprecated
+	public FinishablePrintWriter(OutputStream out, String characterEncoding) throws IOException {
+		this(out, characterEncoding, false);
+	}
 
 	/**
 	 * Calls {@link Finishable#finish()} on the underlying output stream.
diff --git a/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/BasicRestInfoProviderTest.java b/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/BasicRestInfoProviderTest.java
index 47a1b33..f7a2c52 100644
--- a/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/BasicRestInfoProviderTest.java
+++ b/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/BasicRestInfoProviderTest.java
@@ -21,7 +21,8 @@ import java.io.*;
 import java.util.*;
 
 import org.apache.juneau.json.*;
-import org.apache.juneau.jsonschema.annotation.*;
+import org.apache.juneau.jsonschema.annotation.ExternalDocs;
+import org.apache.juneau.jsonschema.annotation.Schema;
 import org.apache.juneau.xml.*;
 import org.apache.juneau.*;
 import org.apache.juneau.annotation.*;
diff --git a/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/annotation2/ResponseAnnotationTest.java b/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/annotation2/ResponseAnnotationTest.java
index deab298..e51a05d 100644
--- a/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/annotation2/ResponseAnnotationTest.java
+++ b/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/annotation2/ResponseAnnotationTest.java
@@ -23,7 +23,7 @@ import org.apache.juneau.http.annotation.*;
 import org.apache.juneau.http.annotation.Body;
 import org.apache.juneau.http.annotation.Response;
 import org.apache.juneau.json.*;
-import org.apache.juneau.jsonschema.annotation.*;
+import org.apache.juneau.jsonschema.annotation.Schema;
 import org.apache.juneau.oapi.*;
 import org.apache.juneau.rest.annotation.*;
 import org.apache.juneau.rest.mock.*;
diff --git a/pom.xml b/pom.xml
index 2428db1..9b0da4b 100644
--- a/pom.xml
+++ b/pom.xml
@@ -38,7 +38,7 @@
 		<servlet.version>3.1.0</servlet.version>
 		<httpclient.version>4.5.6</httpclient.version>
 		<jetty.version>9.4.12.v20180830</jetty.version>
-		<juneau.compare.version>7.1.0</juneau.compare.version>
+		<juneau.compare.version>7.2.0</juneau.compare.version>
 	</properties>
 
 	<dependencyManagement>