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/08/01 18:49:13 UTC

[juneau] branch master updated: Rework REST Response annotations.

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 504877a  Rework REST Response annotations.
504877a is described below

commit 504877a9bf662b1b44325d75a2b3a464459d6752
Author: JamesBognar <ja...@apache.org>
AuthorDate: Wed Aug 1 14:48:55 2018 -0400

    Rework REST Response annotations.
---
 .../src/test/java/org/apache/juneau/ValueTest.java |  58 +--
 .../juneau/httppart/HttpPartSchemaTest_Body.java   |   8 +-
 .../httppart/HttpPartSchemaTest_Response.java      |   4 +-
 .../src/main/java/org/apache/juneau/Value.java     |  54 +++
 .../annotation/InvalidAnnotationException.java     |  60 +--
 .../juneau/http/annotation/AnnotationUtils.java    |  63 +--
 .../org/apache/juneau/http/annotation/RBody.java   |  51 +--
 .../{ResponseStatuses.java => RStatus.java}        |  66 +---
 .../apache/juneau/http/annotation/Response.java    |   2 +-
 .../{Response.java => ResponseBody.java}           | 149 +-------
 .../juneau/http/annotation/ResponseHeader.java     |   2 +-
 .../juneau/http/annotation/ResponseStatus.java     | 195 ++--------
 .../org/apache/juneau/httppart/HttpPartSchema.java |   9 +-
 .../juneau/httppart/HttpPartSchemaBuilder.java     |  38 +-
 .../httppart/{ => bean}/RequestBeanMeta.java       |   3 +-
 .../{ => bean}/RequestBeanPropertyMeta.java        |   3 +-
 .../ResponseBeanMeta.java}                         | 158 ++++----
 .../ResponseBeanPropertyMeta.java}                 |  18 +-
 .../juneau/remoteable/RemoteMethodBeanArg.java     |   1 +
 .../juneau/remoteable/RemoteableMethodMeta.java    |   1 +
 juneau-doc/src/main/javadoc/overview.html          |  16 +-
 .../09.HttpPartAnnotations.html                    |   4 +-
 .../09.HttpPartAnnotations/09.ResponseBody.html    |  17 +
 .../09.HttpPartAnnotations/11.ResponseStatus.html  |  50 +--
 .../{09.Response.html => 12.Response.html}         |   0
 .../12.ResponseStatuses.html                       |  85 -----
 .../examples/rest/petstore/PetStoreResource.java   |  18 +-
 .../org/apache/juneau/rest/client/RestClient.java  |   1 +
 .../apache/juneau/rest/BasicRestInfoProvider.java  | 139 +++++--
 .../org/apache/juneau/rest/ResponsePartMeta.java   |  74 ++--
 .../java/org/apache/juneau/rest/RestContext.java   |  64 +---
 .../org/apache/juneau/rest/RestJavaMethod.java     | 117 ++++--
 .../org/apache/juneau/rest/RestMethodReturn.java   |  82 ----
 .../org/apache/juneau/rest/RestMethodThrown.java   |  80 ----
 .../org/apache/juneau/rest/RestParamDefaults.java  | 145 +++----
 .../java/org/apache/juneau/rest/RestParamType.java |   6 +-
 .../java/org/apache/juneau/rest/RestRequest.java   |  54 +--
 .../java/org/apache/juneau/rest/RestResponse.java  |  39 +-
 .../juneau/rest/reshandlers/DefaultHandler.java    |  74 +++-
 .../org/apache/juneau/rest/response/Found.java     |   2 +-
 .../juneau/rest/response/MovedPermanently.java     |   2 +-
 .../juneau/rest/response/PermanentRedirect.java    |   2 +-
 .../org/apache/juneau/rest/response/SeeOther.java  |   2 +-
 .../juneau/rest/response/TemporaryRedirect.java    |   2 +-
 .../juneau/rest/BasicRestInfoProviderTest.java     | 397 ++++++++++++-------
 .../rest/annotation/ResponseAnnotationTest.java    | 422 ++++++++-------------
 .../annotation/ResponseHeaderAnnotationTest.java   |  73 +++-
 .../annotation/ResponseStatusAnnotationTest.java   | 132 +------
 48 files changed, 1303 insertions(+), 1739 deletions(-)

diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestParamType.java b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/ValueTest.java
similarity index 61%
copy from juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestParamType.java
copy to juneau-core/juneau-core-test/src/test/java/org/apache/juneau/ValueTest.java
index 0ceafb7..55569f9 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestParamType.java
+++ b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/ValueTest.java
@@ -10,53 +10,33 @@
 // * "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;
+package org.apache.juneau;
 
-/**
- * Represents the possible parameter types as defined by the Swagger 2.0 specification.
- *
- * <h5 class='section'>See Also:</h5>
- * <ul>
- * 	<li class='link'><a class="doclink" href="../../../../overview-summary.html#juneau-rest-server.Swagger">Overview &gt; juneau-rest-server &gt; OPTIONS pages</a>
- * </ul>
- */
-public enum RestParamType {
-
-	/** Path variable */
-	PATH("path"),
-
-	/** Header value */
-	HEADER("header"),
-
-	/** Form data entry */
-	FORM_DATA("formData"),
+import static org.junit.Assert.*;
 
-	/** Query parameter */
-	QUERY("query"),
+import org.junit.*;
 
-	/** Request body */
-	BODY("body"),
-
-	/** Response value */
-	RESPONSE("response"),
-
-	/** Response header value */
-	RESPONSE_HEADER("responseHeader"),
+/**
+ * Validates the {@link Value} class.
+ */
+public class ValueTest {
 
-	/** Response status value */
-	RESPONSE_STATUS("responseStatus"),
+	public static class A extends Value<A1>{}
+	public static class A1 {}
 
-	/** Not a standard Swagger-defined field */
-	OTHER("other");
+	@Test
+	public void testSubclass() {
+		assertEquals(A1.class, Value.getValueType(A.class));
+	}
 
-	private final String value;
+	public static class B {
+		public void b(Value<B1> b1) {};
 
-	private RestParamType(String value) {
-		this.value = value;
 	}
+	public static class B1 {}
 
-	@Override /* Object */
-	public String toString() {
-		return value;
+	@Test
+	public void testParameter() throws Exception {
+		assertEquals(B1.class, Value.getValueType(B.class.getMethod("b", Value.class), 0));
 	}
 }
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 d13d06f..6c24bf8 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
@@ -51,7 +51,7 @@ public class HttpPartSchemaTest_Body {
 	public void a02_basic_onClass() throws Exception {
 		HttpPartSchema s = HttpPartSchema.create().apply(Body.class, A02.class).noValidate().build();
 		assertTrue(s.isRequired());
-		assertObjectEquals("{description:'b1\\nb2',example:'f1',required:true,schema:{'$ref':'c1'},_value:'{g1:true}'}", s.getApi());
+		assertObjectEquals("{description:'b1\\nb2',example:'f1',required:true,schema:{'$ref':'c1'},_value:'{g1:true}','$ref':'c1'}", s.getApi());
 	}
 
 	public static class A03 {
@@ -72,7 +72,7 @@ public class HttpPartSchemaTest_Body {
 	public void a03_basic_onParameter() throws Exception {
 		HttpPartSchema s = HttpPartSchema.create().apply(Body.class, A03.class.getMethod("a", String.class), 0).noValidate().build();
 		assertTrue(s.isRequired());
-		assertObjectEquals("{description:'b1\\nb2',example:'f1',required:true,schema:{'$ref':'c1'},_value:'{g1:true}'}", s.getApi());
+		assertObjectEquals("{description:'b1\\nb2',example:'f1',required:true,schema:{'$ref':'c1'},_value:'{g1:true}','$ref':'c1'}", s.getApi());
 	}
 
 	public static class A04 {
@@ -93,7 +93,7 @@ public class HttpPartSchemaTest_Body {
 	public void a04_basic_onParameterAndClass() throws Exception {
 		HttpPartSchema s = HttpPartSchema.create().apply(Body.class, A04.class.getMethod("a", A02.class), 0).noValidate().build();
 		assertTrue(s.isRequired());
-		assertObjectEquals("{description:'b3\\nb3',example:'f2',required:true,schema:{'$ref':'c3'},_value:'{g2:true}'}", s.getApi());
+		assertObjectEquals("{description:'b3\\nb3',example:'f2',required:true,schema:{'$ref':'c3'},_value:'{g2:true}','$ref':'c3'}", s.getApi());
 	}
 
 	@Body(
@@ -250,7 +250,7 @@ public class HttpPartSchemaTest_Body {
 		assertEquals("c7\nc8", items.getDefault());
 
 		assertObjectEquals(
-			"{schema:{'default':'c1\\nc2','enum':['e1','e2'],exclusiveMaximum:true,exclusiveMinimum:true,format:'int32',items:{collectionFormat:'ssv','default':'c3\\nc4','enum':['e3','e4'],format:'int64',items:{collectionFormat:'tsv','default':'c5\\nc6','enum':['e5','e6'],exclusiveMaximum:true,exclusiveMinimum:true,format:'float',items:{type:'array',format:'double',collectionFormat:'pipes',maximum:'13',minimum:'14',multipleOf:'15',pattern:'16',maxLength:13,minLength:14,maxItems:15,minItems:16,exc [...]
+			"{schema:{'default':'c1\\nc2','enum':['e1','e2'],exclusiveMaximum:true,exclusiveMinimum:true,format:'int32',items:{collectionFormat:'ssv','default':'c3\\nc4','enum':['e3','e4'],format:'int64',items:{collectionFormat:'tsv','default':'c5\\nc6','enum':['e5','e6'],exclusiveMaximum:true,exclusiveMinimum:true,format:'float',items:{type:'array',format:'double',collectionFormat:'pipes',maximum:'13',minimum:'14',multipleOf:'15',pattern:'16',maxLength:13,minLength:14,maxItems:15,minItems:16,exc [...]
 			s.getApi()
 		);
 	}
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 03f98ad..0c84d95 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
@@ -49,7 +49,7 @@ public class HttpPartSchemaTest_Response {
 	@Test
 	public void a02_basic_onClass() throws Exception {
 		HttpPartSchema s = HttpPartSchema.create().apply(Response.class, A02.class).noValidate().build();
-		assertObjectEquals("{description:'b1\\nb2',example:'f1',schema:{'$ref':'c1'},_value:'{g1:true}'}", s.getApi());
+		assertObjectEquals("{description:'b1\\nb2',example:'f1',schema:{'$ref':'c1'},_value:'{g1:true}','$ref':'c1'}", s.getApi());
 	}
 
 	@Response(
@@ -206,7 +206,7 @@ public class HttpPartSchemaTest_Response {
 		assertEquals("c7\nc8", items.getDefault());
 
 		assertObjectEquals(
-			"{schema:{'default':'c1\\nc2','enum':['e1','e2'],exclusiveMaximum:true,exclusiveMinimum:true,format:'int32',items:{collectionFormat:'ssv','default':'c3\\nc4','enum':['e3','e4'],format:'int64',items:{collectionFormat:'tsv','default':'c5\\nc6','enum':['e5','e6'],exclusiveMaximum:true,exclusiveMinimum:true,format:'float',items:{type:'array',format:'double',collectionFormat:'pipes',maximum:'13',minimum:'14',multipleOf:'15',pattern:'16',maxLength:13,minLength:14,maxItems:15,minItems:16,exc [...]
+			"{schema:{'default':'c1\\nc2','enum':['e1','e2'],exclusiveMaximum:true,exclusiveMinimum:true,format:'int32',items:{collectionFormat:'ssv','default':'c3\\nc4','enum':['e3','e4'],format:'int64',items:{collectionFormat:'tsv','default':'c5\\nc6','enum':['e5','e6'],exclusiveMaximum:true,exclusiveMinimum:true,format:'float',items:{type:'array',format:'double',collectionFormat:'pipes',maximum:'13',minimum:'14',multipleOf:'15',pattern:'16',maxLength:13,minLength:14,maxItems:15,minItems:16,exc [...]
 			s.getApi()
 		);
 	}
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/Value.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/Value.java
index 4a92954..492050b 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/Value.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/Value.java
@@ -12,6 +12,10 @@
 // ***************************************************************************************************************************
 package org.apache.juneau;
 
+import static org.apache.juneau.internal.ClassUtils.*;
+
+import java.lang.reflect.*;
+
 /**
  * Represents a simple settable value.
  *
@@ -22,6 +26,56 @@ package org.apache.juneau;
  */
 public class Value<T> {
 
+	/**
+	 * Returns the generic parameter type of the Value parameter at the specified position.
+	 *
+	 * <h5 class='figure'>Example:</h5>
+	 * <p class='bcode w800'>
+	 * 	<jk>public class</jk> A {
+	 * 		<jk>public void</jk> doX(Value&lt;Foo&gt; foo) {...}
+	 * 	}
+	 * </p>
+	 * <p class='bcode w800'>
+	 * 	Class<?> t = Value.<jsm>getValueType</jsm>(A.<jk>class</jk>.getMethod(<js>"doX"</js>, Value.<jk>class</jk>));
+	 * 	<jsm>assertTrue</jsm>(t == Foo.<jk>class</jk>);
+	 * </p>
+	 *
+	 * @param m The method containing the parameter.
+	 * @param i The index of the parameter.
+	 * @return The parameter type of the value, or <jk>null</jk> if the method parameter is not of type <code>Value</code>.
+	 */
+	public static Class<?> getValueType(Method m, int i) {
+		return getValueType(m.getGenericParameterTypes()[i]);
+	}
+
+	/**
+	 * Returns the generic parameter type of the Value type.
+	 *
+	 * @param t The type to find the parameter type of.
+	 * @return The parameter type of the value, or <jk>null</jk> if the type is not a subclass of <code>Value</code>.
+	 */
+	public static Class<?> getValueType(Type t) {
+		if (t instanceof ParameterizedType) {
+			ParameterizedType pt = (ParameterizedType)t;
+			if (pt.getRawType() == Value.class) {
+				Type[] ta = pt.getActualTypeArguments();
+				if (ta.length > 0) {
+					Type t2 = ta[0];
+					if (t2 instanceof Class) {
+						return (Class<?>)t2;
+					}
+				}
+			}
+		} else if (t instanceof Class) {
+			Class<?> c = (Class<?>)t;
+			if (Value.class.isAssignableFrom(c)) {
+				return resolveParameterType(Value.class, 0, c);
+			}
+		}
+
+		return null;
+	}
+
 	private T t;
 	private ValueListener<T> listener;
 
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestParamType.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/annotation/InvalidAnnotationException.java
similarity index 61%
copy from juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestParamType.java
copy to juneau-core/juneau-marshall/src/main/java/org/apache/juneau/annotation/InvalidAnnotationException.java
index 0ceafb7..415c7fc 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestParamType.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/annotation/InvalidAnnotationException.java
@@ -10,53 +10,25 @@
 // * "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;
+package org.apache.juneau.annotation;
+
+import org.apache.juneau.*;
 
 /**
- * Represents the possible parameter types as defined by the Swagger 2.0 specification.
+ * Defines an invalid usage of an annotation.
  *
- * <h5 class='section'>See Also:</h5>
- * <ul>
- * 	<li class='link'><a class="doclink" href="../../../../overview-summary.html#juneau-rest-server.Swagger">Overview &gt; juneau-rest-server &gt; OPTIONS pages</a>
- * </ul>
  */
-public enum RestParamType {
-
-	/** Path variable */
-	PATH("path"),
-
-	/** Header value */
-	HEADER("header"),
-
-	/** Form data entry */
-	FORM_DATA("formData"),
-
-	/** Query parameter */
-	QUERY("query"),
-
-	/** Request body */
-	BODY("body"),
-
-	/** Response value */
-	RESPONSE("response"),
-
-	/** Response header value */
-	RESPONSE_HEADER("responseHeader"),
-
-	/** Response status value */
-	RESPONSE_STATUS("responseStatus"),
-
-	/** Not a standard Swagger-defined field */
-	OTHER("other");
-
-	private final String value;
-
-	private RestParamType(String value) {
-		this.value = value;
-	}
-
-	@Override /* Object */
-	public String toString() {
-		return value;
+public class InvalidAnnotationException extends FormattedRuntimeException {
+
+	private static final long serialVersionUID = 1L;
+
+	/**
+	 * Constructor.
+	 *
+	 * @param message Message.
+	 * @param args Arguments.
+	 */
+	public InvalidAnnotationException(String message, Object...args) {
+		super(message, args);
 	}
 }
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 2b51f45..01749d1 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
@@ -65,6 +65,25 @@ public class AnnotationUtils {
 	 * @param a The annotation.
 	 * @return The same map with merged results, or a new map if the map was <jk>null</jk>.
 	 */
+	public static ObjectMap merge(ObjectMap om, ResponseBody a) {
+		if (empty(a))
+			return om;
+		om = newMap(om);
+		return om
+			.appendSkipEmpty("example", joinnl(a.example()))
+			.appendSkipEmpty("examples", joinnl(a.examples()))
+			.appendSkipEmpty("schema", merge(om.getObjectMap("schema"), a.schema()))
+			.appendSkipEmpty("_value", joinnl(a.api()))
+		;
+	}
+
+	/**
+	 * Merges the contents of the specified annotation into the specified map.
+	 *
+	 * @param om The map to add the annotation values to.
+	 * @param a The annotation.
+	 * @return The same map with merged results, or a new map if the map was <jk>null</jk>.
+	 */
 	public static ObjectMap merge(ObjectMap om, ExternalDocs a) {
 		if (empty(a))
 			return om;
@@ -278,22 +297,6 @@ public class AnnotationUtils {
 	 * @param a The annotation.
 	 * @return The same map with merged results, or a new map if the map was <jk>null</jk>.
 	 */
-	public static ObjectMap merge(ObjectMap om, ResponseStatus a) {
-		if (empty(a))
-			return om;
-		om = newMap(om);
-		return om
-			.appendSkipEmpty("_value", joinnl(a.api()))
-			.appendSkipEmpty("description", joinnl(a.description()));
-	}
-
-	/**
-	 * Merges the contents of the specified annotation into the specified map.
-	 *
-	 * @param om The map to add the annotation values to.
-	 * @param a The annotation.
-	 * @return The same map with merged results, or a new map if the map was <jk>null</jk>.
-	 */
 	public static ObjectMap merge(ObjectMap om, Path a) {
 		if (empty(a))
 			return om;
@@ -522,19 +525,6 @@ 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(ResponseStatus a) {
-		if (a == null)
-			return true;
-		return
-			allEmpty(a.description(), a.api());
-	}
-
-	/**
-	 * 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(Schema a) {
 		if (a == null)
 			return true;
@@ -577,6 +567,21 @@ public class AnnotationUtils {
 			&& empty(a.schema());
 	}
 
+
+	/**
+	 * 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(ResponseBody a) {
+		if (a == null)
+			return true;
+		return
+			allEmpty(a.example(), a.examples(), a.api())
+			&& empty(a.schema());
+	}
+
 	/**
 	 * Returns <jk>true</jk> if the specified annotation contains all default values.
 	 *
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestParamType.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/RBody.java
similarity index 58%
copy from juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestParamType.java
copy to juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/RBody.java
index 0ceafb7..ebe9069 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestParamType.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/RBody.java
@@ -2,7 +2,7 @@
 // * 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                                                              *
+// * with the License.  You may obtain a copy of the License at                                                              * 
 // *                                                                                                                         *
 // *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
 // *                                                                                                                         *
@@ -10,53 +10,12 @@
 // * "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;
+package org.apache.juneau.http.annotation;
 
 /**
- * Represents the possible parameter types as defined by the Swagger 2.0 specification.
- *
- * <h5 class='section'>See Also:</h5>
- * <ul>
- * 	<li class='link'><a class="doclink" href="../../../../overview-summary.html#juneau-rest-server.Swagger">Overview &gt; juneau-rest-server &gt; OPTIONS pages</a>
- * </ul>
+ * TODO
+ * 
  */
-public enum RestParamType {
+public class RBody {
 
-	/** Path variable */
-	PATH("path"),
-
-	/** Header value */
-	HEADER("header"),
-
-	/** Form data entry */
-	FORM_DATA("formData"),
-
-	/** Query parameter */
-	QUERY("query"),
-
-	/** Request body */
-	BODY("body"),
-
-	/** Response value */
-	RESPONSE("response"),
-
-	/** Response header value */
-	RESPONSE_HEADER("responseHeader"),
-
-	/** Response status value */
-	RESPONSE_STATUS("responseStatus"),
-
-	/** Not a standard Swagger-defined field */
-	OTHER("other");
-
-	private final String value;
-
-	private RestParamType(String value) {
-		this.value = value;
-	}
-
-	@Override /* Object */
-	public String toString() {
-		return value;
-	}
 }
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/ResponseStatuses.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/RStatus.java
similarity index 56%
rename from juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/ResponseStatuses.java
rename to juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/RStatus.java
index f236867..566e9e6 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/ResponseStatuses.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/RStatus.java
@@ -1,46 +1,20 @@
-// ***************************************************************************************************************************
-// * 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.ElementType.*;
-import static java.lang.annotation.RetentionPolicy.*;
-
-import java.lang.annotation.*;
-
-/**
- * REST response statuses annotation.
- *
- * <p>
- * Used to associate multiple {@link ResponseStatus @ResponseStatus} annotations to the same parameter or class.
- *
- * <p>
- * Since Juneau currently prereq's Java 1.7, we cannot take advantage of annotation duplication support in Java 8.
- * <br>This annotation overcomes that limitation.
- *
- * <h5 class='section'>See Also:</h5>
- * <ul>
- * 	<li class='link'><a class="doclink" href="../../../../../overview-summary.html#juneau-rest-server.HttpPartAnnotations.ResponseStatuses">Overview &gt; juneau-rest-server &gt; @ResponseStatuses</a>
- * 	<li class='link'><a class="doclink" href="../../../../../overview-summary.html#juneau-rest-server.Swagger">Overview &gt; juneau-rest-server &gt; OPTIONS pages and Swagger</a>
- * </ul>
- */
-@Documented
-@Target({PARAMETER,TYPE})
-@Retention(RUNTIME)
-@Inherited
-public @interface ResponseStatuses {
-
-	/**
-	 * Specifies one or more {@link ResponseStatus @ResponseStatus} annotations to apply to the same parameter or class.
-	 */
-	ResponseStatus[] value() default {};
-}
\ No newline at end of file
+// ***************************************************************************************************************************
+// * 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;
+
+/**
+ * TODO
+ *
+ */
+public class RStatus {
+}
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 0c16949..20bd1ec 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
@@ -48,7 +48,7 @@ import org.apache.juneau.jsonschema.*;
  * </ul>
  */
 @Documented
-@Target({PARAMETER,TYPE,METHOD})
+@Target({TYPE})
 @Retention(RUNTIME)
 @Inherited
 public @interface Response {
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/ResponseBody.java
similarity index 70%
copy from juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/Response.java
copy to juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/ResponseBody.java
index 0c16949..271cdfb 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/ResponseBody.java
@@ -24,34 +24,13 @@ import org.apache.juneau.json.*;
 import org.apache.juneau.jsonschema.*;
 
 /**
- * REST response annotation.
- *
- * Identifies the HTTP status code and description about an HTTP response.
- *
- * <p>
- * Can be used in the following locations:
- *  <ul>
- * 	<li>Exception classes thrown from <ja>@RestMethod</ja>-annotated REST Java methods.
- * 	<li>Return type classes of <ja>@RestMethod</ja>-annotated REST Java methods.
- * 	<li><ja>@RestMethod</ja>-annotated REST Java methods themselves.
- * 	<li>Java method arguments and argument-types of <ja>@RestMethod</ja>-annotated REST Java methods.
- * </ul>
- *
- * <p>
- * When applied to exception classes, this annotation defines Swagger information on non-200 return types.
- *
- * <h5 class='section'>See Also:</h5>
- * <ul>
- * 	<li class='link'><a class="doclink" href="../../../../../overview-summary.html#juneau-rest-server.HttpPartAnnotations.Response">Overview &gt; juneau-rest-server &gt; @Response</a>
- * 	<li class='link'><a class="doclink" href="../../../../../overview-summary.html#juneau-rest-server.Swagger">Overview &gt; juneau-rest-server &gt; OPTIONS pages and Swagger</a>
- * 	<li class='link'><a class="doclink" href="https://swagger.io/specification/v2/#responseObject">Swagger Specification &gt; Response Object</a>
- * </ul>
+ * TODO
  */
 @Documented
 @Target({PARAMETER,TYPE,METHOD})
 @Retention(RUNTIME)
 @Inherited
-public @interface Response {
+public @interface ResponseBody {
 
 	/**
 	 * Specifies the {@link HttpPartSerializer} class used for serializing values to strings.
@@ -70,53 +49,6 @@ public @interface Response {
 	public boolean usePartSerializer() default false;
 
 	/**
-	 * The HTTP response code.
-	 *
-	 * The default value is <code>500</code> for exceptions and <code>200</code> for return types.
-	 */
-	int[] code() default {};
-
-	/**
-	 * A synonym for {@link #code()}.
-	 *
-	 * <p>
-	 * Allows you to use shortened notation if you're only specifying the code.
-	 *
-	 * <p>
-	 * The following are completely equivalent ways of defining the response code:
-	 * <p class='bcode w800'>
-	 * 	<ja>@Response</ja>(code=404)
-	 * 	<jk>public class</jk> NotFound <jk>extends</jk> RestException {...}
-	 * </p>
-	 * <p class='bcode w800'>
-	 * 	<ja>@Response</ja>(404)
-	 * 	<jk>public class</jk> NotFound <jk>extends</jk> RestException {...}
-	 * </p>
-	 */
-	int[] value() default {};
-
-	/**
-	 * <mk>description</mk> field of the Swagger <a class="doclink" href="https://swagger.io/specification/v2/#responseObject">Response</a> object.
-	 *
-	 * <h5 class='section'>Used for:</h5>
-	 * <ul class='spaced-list'>
-	 * 	<li>
-	 * 		Server-side generated Swagger documentation.
-	 * </ul>
-	 *
-	 * <h5 class='section'>Notes:</h5>
-	 * <ul class='spaced-list'>
-	 * 	<li>
-	 * 		The format is plain text.
-	 * 		<br>Multiple lines are concatenated with newlines.
-	 * 	<li>
-	 * 		Supports <a class="doclink" href="../../../../../overview-summary.html#DefaultRestSvlVariables">initialization-time and request-time variables</a>
-	 * 		(e.g. <js>"$L{my.localized.variable}"</js>).
-	 * </ul>
-	 */
-	String[] description() default {};
-
-	/**
 	 * <mk>schema</mk> field of the Swagger <a class="doclink" href="https://swagger.io/specification/v2/#responseObject">Response</a> object.
 	 *
 	 * <h5 class='section'>Used for:</h5>
@@ -130,17 +62,6 @@ public @interface Response {
 	Schema schema() default @Schema;
 
 	/**
-	 * <mk>headers</mk> field of the Swagger <a class="doclink" href="https://swagger.io/specification/v2/#responseObject">Response</a> object.
-	 *
-	 * <h5 class='section'>Used for:</h5>
-	 * <ul class='spaced-list'>
-	 * 	<li>
-	 * 		Server-side generated Swagger documentation.
-	 * </ul>
-	 */
-	ResponseHeader[] headers() default {};
-
-	/**
 	 * A serialized example of the body of a response.
 	 *
 	 * <p>
@@ -154,7 +75,7 @@ public @interface Response {
 	 * <h5 class='section'>Example:</h5>
 	 * <p class='bcode w800'>
 	 * 	<jc>// A JSON representation of a PetCreate object.</jc>
-	 * 	<ja>@Response</ja>(
+	 * 	<ja>@ResponseBody</ja>(
 	 * 		example=<js>"{name:'Doggie',price:9.99,species:'Dog',tags:['friendly','cute']}"</js>
 	 * 	)
 	 * </p>
@@ -250,7 +171,7 @@ public @interface Response {
 	 * <ul class='spaced-list'>
 	 * 	<li>
 	 * 		The format is any <a class='doclink' href='../../../../../overview-summary.html#juneau-marshall.JsonDetails.SimplifiedJson'>Simplified JSON</a> if the object can be converted to a POJO using {@link JsonParser#DEFAULT} or a simple String if the object
-	 * 		has a schema associated with it meancan be converted from a String.
+	 * 		has a schema associated with it can be converted from a String.
 	 * 		<br>Multiple lines are concatenated with newlines.
 	 * 	<li>
 	 * 		The format of this object can also be a simple String if the body has a schema associated with it, meaning it's meant to be treated as an HTTP part.
@@ -273,7 +194,7 @@ public @interface Response {
 	 *
 	 * <p class='bcode w800'>
 	 * 	<jc>// A JSON representation of a PetCreate object.</jc>
-	 * 	<ja>@Response</ja>(
+	 * 	<ja>@ResponseBody</ja>(
 	 * 		examples={
 	 * 			<js>"'application/json':'{name:\\'Doggie\\',species:\\'Dog\\'}',"</js>,
 	 * 			<js>"'text/uon':'(name:Doggie,species=Dog)'"</js>
@@ -311,62 +232,6 @@ public @interface Response {
 	 * <p>
 	 * This is a <a class='doclink' href='../../../../../overview-summary.html#juneau-marshall.JsonDetails.SimplifiedJson'>Simplified JSON</a> object that makes up the swagger information for this field.
 	 *
-	 * <p>
-	 * The following are completely equivalent ways of defining the swagger description of the Response object:
-	 * <p class='bcode w800'>
-	 * 	<jc>// Normal</jc>
-	 * 	<ja>@Response</ja>(
-	 * 		code=302,
-	 * 		description=<js>"Redirect"</js>,
-	 * 		headers={
-	 * 			<ja>@ResponseHeader</ja>(
-	 * 				name=<js>"Location"</js>,
-	 * 				type=<js>"string"</js>,
-	 * 				format=<js>"uri"</js>
-	 * 			)
-	 * 		}
-	 * 	)
-	 * </p>
-	 * <p class='bcode w800'>
-	 * 	<jc>// Free-form</jc>
-	 * 	<ja>@Response</ja>(
-	 * 		code=302,
-	 * 		api={
-	 * 			<js>"description: 'Redirect',"</js>,
-	 * 			<js>"headers: {"</js>,
-	 * 				<js>"Location: {"</js>,
-	 * 					<js>"type: 'string',"</js>,
-	 * 					<js>"format: 'uri'"</js>,
-	 * 				<js>"}"</js>,
-	 * 			<js>"}"</js>
-	 * 		}
-	 * 	)
-	 * </p>
-	 * <p class='bcode w800'>
-	 * 	<jc>// Free-form using variables</jc>
-	 * 	<ja>@Response</ja>(
-	 * 		code=302,
-	 * 		api=<js>"$L{redirectSwagger}"</js>
-	 * 	)
-	 * </p>
-	 * <p class='bcode w800'>
-	 * 	<mc>// Contents of MyResource.properties</mc>
-	 * 	<mk>redirectSwagger</mk> = <mv>{ description: "Redirect", headers: { Location: { type: "string", format: "uri" } } }</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'>Used for:</h5>
-	 * <ul class='spaced-list'>
-	 * 	<li>
-	 * 		Server-side generated Swagger documentation.
-	 * </ul>
-	 *
 	 * <h5 class='section'>Notes:</h5>
 	 * <ul class='spaced-list'>
 	 * 	<li>
@@ -377,10 +242,10 @@ public @interface Response {
 	 * 		The leading/trailing <code>{ }</code> characters are optional.
 	 * 		<br>The following two example are considered equivalent:
 	 * 		<p class='bcode w800'>
-	 * 	<ja>@Response</ja>(api=<js>"{description: 'Redirect'}"</js>)
+	 * 	<ja>@ResponseBody</ja>(api=<js>"{schema:{type:'string'}}}"</js>)
 	 * 		</p>
 	 * 		<p class='bcode w800'>
-	 * 	<ja>@Response</ja>(api=<js>"description: 'Redirect''"</js>)
+	 * 	<ja>@ResponseBody</ja>(api=<js>"schema: {type:'string'}"</js>)
 	 * 		</p>
 	 * 	<li>
 	 * 		Multiple lines are concatenated with newlines so that you can format the value to be readable.
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 bc62d32..7d2992c 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
@@ -82,7 +82,7 @@ import org.apache.juneau.httppart.*;
  * </ul>
 */
 @Documented
-@Target({PARAMETER,TYPE})
+@Target({PARAMETER,TYPE,METHOD})
 @Retention(RUNTIME)
 @Inherited
 public @interface ResponseHeader {
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/ResponseStatus.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/ResponseStatus.java
index 1c98f49..bee7460 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/ResponseStatus.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/ResponseStatus.java
@@ -1,159 +1,36 @@
-// ***************************************************************************************************************************
-// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
-// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
-// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
-// * with the License.  You may obtain a copy of the License at                                                              *
-// *                                                                                                                         *
-// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
-// *                                                                                                                         *
-// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
-// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
-// * specific language governing permissions and limitations under the License.                                              *
-// ***************************************************************************************************************************
-package org.apache.juneau.http.annotation;
-
-import static java.lang.annotation.RetentionPolicy.*;
-
-import java.lang.annotation.*;
-
-/**
- * REST response status annotation.
- *
- * <p>
- * Annotation that can be applied to parameters and types to denote them as an HTTP response status on server-side REST method parameters.
- *
- * <p>
- * Can be used in the following locations:
- * <ul>
- * 	<li>Java method arguments and argument-types of server-side <ja>@RestMethod</ja>-annotated REST Java methods.
- * </ul>
- *
- * <h5 class='section'>See Also:</h5>
- * <ul>
- * 	<li class='link'><a class="doclink" href="../../../../../overview-summary.html#juneau-rest-server.HttpPartAnnotations.ResponseStatus">Overview &gt; juneau-rest-server &gt; @ResponseStatus</a>
- * 	<li class='link'><a class="doclink" href="../../../../../overview-summary.html#juneau-rest-server.Swagger">Overview &gt; juneau-rest-server &gt; OPTIONS pages and Swagger</a>
- * 	<li class='link'><a class="doclink" href="https://swagger.io/specification/v2/#responseObject">Swagger Specification &gt; Response Object</a>
- * </ul>
- */
-@Documented
-@Target({})
-@Retention(RUNTIME)
-@Inherited
-public @interface ResponseStatus {
-
-	/**
-	 * The HTTP status of the response.
-	 */
-	int code() default 0;
-
-	/**
-	 * A synonym to {@link #code()}.
-	 *
-	 * <p>
-	 * Useful if you only want to specify a code only.
-	 *
-	 * <p>
-	 * The following are completely equivalent ways of defining the response code:
-	 * <p class='bcode w800'>
-	 * 	<ja>@ResponseStatus</ja>(code=200)
-	 * </p>
-	 * <p class='bcode w800'>
-	 * 	<ja>@ResponseStatus</ja>(200)
-	 * </p>
-	 */
-	int value() default 0;
-
-	/**
-	 * <mk>description</mk> field of the Swagger <a class="doclink" href="https://swagger.io/specification/v2/#responseObject">Response</a> object.
-	 *
-	 * <h5 class='section'>Used for:</h5>
-	 * <ul class='spaced-list'>
-	 * 	<li>
-	 * 		Server-side generated Swagger documentation.
-	 * </ul>
-	 *
-	 * <h5 class='section'>Notes:</h5>
-	 * <ul class='spaced-list'>
-	 * 	<li>
-	 * 		The format is plain text.
-	 * 		<br>Multiple lines are concatenated with newlines.
-	 * 	<li>
-	 * 		Supports <a class="doclink" href="../../../../../overview-summary.html#DefaultRestSvlVariables">initialization-time and request-time variables</a>
-	 * 		(e.g. <js>"$L{my.localized.variable}"</js>).
-	 * </ul>
-	 */
-	String[] description() default {};
-
-	/**
-	 * Free-form value for the Swagger <a class="doclink" href="https://swagger.io/specification/v2/#responseObject">Response</a> object.
-	 *
-	 * <p>
-	 * This is a JSON object that makes up the swagger information for this Response object.
-	 *
-	 * <p>
-	 * The following are completely equivalent ways of defining the swagger description of the Response object:
-	 * <p class='bcode w800'>
-	 * 	<jc>// Normal</jc>
-	 * 	<ja>@ResponseStatus</ja>(
-	 * 		code=401,
-	 * 		description=<js>"Invalid user/pw"</js>
-	 * 	)
-	 * </p>
-	 * <p class='bcode w800'>
-	 * 	<jc>// Free-form</jc>
-	 * 	<ja>@ResponseStatus</ja>(
-	 * 		code=401,
-	 * 		api={
-	 * 			<js>"description: 'Invalid user/pw'"</js>
-	 * 		}
-	 * 	)
-	 * </p>
-	 * <p class='bcode w800'>
-	 * 	<jc>// Free-form using variables</jc>
-	 * 	<ja>@ResponseStatus</ja>(
-	 * 		code=401,
-	 * 		api=<js>"$L{unauthorizedSwagger}"</js>
-	 * 	)
-	 * </p>
-	 * <p class='bcode w800'>
-	 * 	<mc>// Contents of MyResource.properties</mc>
-	 * 	<mk>unauthorizedSwagger</mk> = <mv>{ description: "Invalid user/pw" }</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'>Used for:</h5>
-	 * <ul class='spaced-list'>
-	 * 	<li>
-	 * 		Server-side generated Swagger documentation.
-	 * </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>"code"</js> whose value needs to be known during servlet initialization.
-	 * 	<li>
-	 * 		The format is a <a class='doclink' href='../../../../../overview-summary.html#juneau-marshall.JsonDetails.SimplifiedJson'>Simplified JSON</a> object.
-	 * 	<li>
-	 * 		The leading/trailing <code>{ }</code> characters are optional.
-	 * 		<br>The following two example are considered equivalent:
-	 * 		<p class='bcode w800'>
-	 * 	<ja>@ResponseStatus</ja>(<js>"{description:'Invalid user/pw'}"</js>)
-	 * 		</p>
-	 * 		<p class='bcode w800'>
-	 * 	<ja>@ResponseStatus</ja>(<js>"description:'Invalid user/pw'"</js>)
-	 * 		</p>
-	 * 	<li>
-	 * 		Supports <a class="doclink" href="../../../../../overview-summary.html#DefaultRestSvlVariables">initialization-time and request-time variables</a>
-	 * 		(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[] api() 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.ElementType.*;
+import static java.lang.annotation.RetentionPolicy.*;
+
+import java.lang.annotation.*;
+
+/**
+ * REST response status annotation.
+ * 
+ * <p>
+ * TODO
+ *
+ * <ul>
+ * 	<li class='link'><a class="doclink" href="../../../../../overview-summary.html#juneau-rest-server.HttpPartAnnotations.ResponseStatuses">Overview &gt; juneau-rest-server &gt; @ResponseStatuses</a>
+ * 	<li class='link'><a class="doclink" href="../../../../../overview-summary.html#juneau-rest-server.Swagger">Overview &gt; juneau-rest-server &gt; OPTIONS pages and Swagger</a>
+ * </ul>
+ */
+@Documented
+@Target({PARAMETER,METHOD})
+@Retention(RUNTIME)
+@Inherited
+public @interface ResponseStatus {
+}
\ No newline at end of file
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/httppart/HttpPartSchema.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/httppart/HttpPartSchema.java
index e127e4d..bdb334c 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/httppart/HttpPartSchema.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/httppart/HttpPartSchema.java
@@ -106,7 +106,7 @@ public class HttpPartSchema {
 	 * 		<li>{@link Path}
 	 * 		<li>{@link Response}
 	 * 		<li>{@link ResponseHeader}
-	 * 		<li>{@link ResponseStatus}
+	 * 		<li>{@link ResponseBody}
 	 * 		<li>{@link HasQuery}
 	 * 		<li>{@link HasFormData}
 	 * 	</ul>
@@ -142,7 +142,7 @@ public class HttpPartSchema {
 	 * 		<li>{@link Path}
 	 * 		<li>{@link Response}
 	 * 		<li>{@link ResponseHeader}
-	 * 		<li>{@link ResponseStatus}
+	 * 		<li>{@link ResponseBody}
 	 * 		<li>{@link HasQuery}
 	 * 		<li>{@link HasFormData}
 	 * 	</ul>
@@ -171,7 +171,7 @@ public class HttpPartSchema {
 	 * 		<li>{@link Path}
 	 * 		<li>{@link Response}
 	 * 		<li>{@link ResponseHeader}
-	 * 		<li>{@link ResponseStatus}
+	 * 		<li>{@link ResponseBody}
 	 * 		<li>{@link HasQuery}
 	 * 		<li>{@link HasFormData}
 	 * 	</ul>
@@ -218,7 +218,6 @@ public class HttpPartSchema {
 	 * <ul>
 	 * 		<li>{@link Response}
 	 * 		<li>{@link ResponseHeader}
-	 * 		<li>{@link ResponseStatus}
 	 * </ul>
 	 * For
 	 *
@@ -228,7 +227,6 @@ public class HttpPartSchema {
 	 * 	<ul>
 	 * 		<li>{@link Response}
 	 * 		<li>{@link ResponseHeader}
-	 * 		<li>{@link ResponseStatus}
 	 * 	</ul>
 	 * @param def
 	 * 	The default response code if no codes were specified in the schema.
@@ -253,7 +251,6 @@ public class HttpPartSchema {
 	 * 	<ul>
 	 * 		<li>{@link Response}
 	 * 		<li>{@link ResponseHeader}
-	 * 		<li>{@link ResponseStatus}
 	 * 	</ul>
 	 * @param def
 	 * 	The default response code if no codes were specified in the schema.
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 ba00a97..86ec2d1 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
@@ -80,9 +80,13 @@ public class HttpPartSchemaBuilder {
 	}
 
 	HttpPartSchemaBuilder apply(Class<? extends Annotation> c, java.lang.reflect.Type t) {
-		if (t instanceof Class<?>)
-			for (Annotation a : ReflectionUtils.findAnnotationsParentFirst(c, (Class<?>)t))
+		if (t instanceof Class<?>) {
+			Class<?> tc = (Class<?>)t;
+			for (Annotation a : ReflectionUtils.findAnnotationsParentFirst(c, tc))
 				apply(a);
+		} else if (t instanceof ParameterizedType) {
+			apply(c, Value.getValueType(t));
+		}
 		return this;
 	}
 
@@ -105,14 +109,18 @@ public class HttpPartSchemaBuilder {
 			apply((Path)a);
 		else if (a instanceof Response)
 			apply((Response)a);
+		else if (a instanceof ResponseBody)
+			apply((ResponseBody)a);
 		else if (a instanceof ResponseHeader)
 			apply((ResponseHeader)a);
-		else if (a instanceof ResponseStatus)
-			apply((ResponseStatus)a);
 		else if (a instanceof HasQuery)
 			apply((HasQuery)a);
 		else if (a instanceof HasFormData)
 			apply((HasFormData)a);
+		else if (a instanceof Schema)
+			apply((Schema)a);
+		else
+			throw new RuntimeException("HttpPartSchemaBuilder.apply(@"+a.getClass().getSimpleName()+") not defined");
 		return this;
 	}
 
@@ -122,8 +130,16 @@ public class HttpPartSchemaBuilder {
 		allowEmptyValue(! a.required());
 		serializer(a.partSerializer());
 		parser(a.partParser());
-		usePartSerializer(a.usePartSerializer());
-		usePartParser(a.usePartParser());
+		usePartSerializer(a.usePartSerializer() || a.partSerializer() != HttpPartSerializer.Null.class);
+		usePartParser(a.usePartParser() || a.partParser() != HttpPartParser.Null.class);
+		apply(a.schema());
+		return this;
+	}
+
+	HttpPartSchemaBuilder apply(ResponseBody a) {
+		api = AnnotationUtils.merge(api, a);
+		serializer(a.partSerializer());
+		usePartSerializer(a.usePartSerializer() || a.partSerializer() != HttpPartSerializer.Null.class);
 		apply(a.schema());
 		return this;
 	}
@@ -184,13 +200,6 @@ public class HttpPartSchemaBuilder {
 		return this;
 	}
 
-	HttpPartSchemaBuilder apply(ResponseStatus a) {
-		api = AnnotationUtils.merge(api, a);
-		code(a.value());
-		code(a.code());
-		return this;
-	}
-
 	HttpPartSchemaBuilder apply(FormData a) {
 		api = AnnotationUtils.merge(api, a);
 		name(a.value());
@@ -284,7 +293,7 @@ public class HttpPartSchemaBuilder {
 		required(false);
 		allowEmptyValue(true);
 		serializer(a.partSerializer());
-		usePartSerializer(a.usePartSerializer());
+		usePartSerializer(a.usePartSerializer() || a.partSerializer() != HttpPartSerializer.Null.class);
 		apply(a.schema());
 		return this;
 	}
@@ -334,6 +343,7 @@ public class HttpPartSchemaBuilder {
 	}
 
 	HttpPartSchemaBuilder apply(Schema a) {
+		api = AnnotationUtils.merge(api, a);
 		type(a.type());
 		format(a.format());
 		items(a.items());
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/httppart/RequestBeanMeta.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/httppart/bean/RequestBeanMeta.java
similarity index 98%
rename from juneau-core/juneau-marshall/src/main/java/org/apache/juneau/httppart/RequestBeanMeta.java
rename to juneau-core/juneau-marshall/src/main/java/org/apache/juneau/httppart/bean/RequestBeanMeta.java
index 04b369b..7f23a07 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/httppart/RequestBeanMeta.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/httppart/bean/RequestBeanMeta.java
@@ -10,7 +10,7 @@
 // * "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.httppart;
+package org.apache.juneau.httppart.bean;
 
 import static org.apache.juneau.internal.ReflectionUtils.*;
 
@@ -20,6 +20,7 @@ import java.util.*;
 
 import org.apache.juneau.*;
 import org.apache.juneau.http.annotation.*;
+import org.apache.juneau.httppart.*;
 import org.apache.juneau.internal.*;
 
 /**
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/httppart/RequestBeanPropertyMeta.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/httppart/bean/RequestBeanPropertyMeta.java
similarity index 98%
rename from juneau-core/juneau-marshall/src/main/java/org/apache/juneau/httppart/RequestBeanPropertyMeta.java
rename to juneau-core/juneau-marshall/src/main/java/org/apache/juneau/httppart/bean/RequestBeanPropertyMeta.java
index 1ab0426..6527bd1 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/httppart/RequestBeanPropertyMeta.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/httppart/bean/RequestBeanPropertyMeta.java
@@ -10,10 +10,11 @@
 // * "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.httppart;
+package org.apache.juneau.httppart.bean;
 
 import org.apache.juneau.*;
 import org.apache.juneau.http.annotation.*;
+import org.apache.juneau.httppart.*;
 import org.apache.juneau.internal.*;
 
 /**
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/httppart/ResponseMeta.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/httppart/bean/ResponseBeanMeta.java
similarity index 54%
rename from juneau-core/juneau-marshall/src/main/java/org/apache/juneau/httppart/ResponseMeta.java
rename to juneau-core/juneau-marshall/src/main/java/org/apache/juneau/httppart/bean/ResponseBeanMeta.java
index e447ae7..bb5d5df 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/httppart/ResponseMeta.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/httppart/bean/ResponseBeanMeta.java
@@ -10,7 +10,7 @@
 // * "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.httppart;
+package org.apache.juneau.httppart.bean;
 
 import static org.apache.juneau.internal.ClassFlags.*;
 import static org.apache.juneau.internal.ClassUtils.*;
@@ -20,49 +20,20 @@ import java.lang.reflect.*;
 import java.util.*;
 
 import org.apache.juneau.*;
+import org.apache.juneau.annotation.*;
 import org.apache.juneau.http.annotation.*;
+import org.apache.juneau.httppart.*;
 import org.apache.juneau.internal.*;
 
 /**
  * Represents the metadata gathered from a parameter or class annotated with {@link Response}.
  */
-public class ResponseMeta {
+public class ResponseBeanMeta {
 
 	/**
 	 * Represents a non-existent meta object.
 	 */
-	public static ResponseMeta NULL = new ResponseMeta(new Builder(PropertyStore.DEFAULT));
-
-	/**
-	 * Create metadata from specified parameter.
-	 *
-	 * @param m The method containing the parameter or parameter type annotated with {@link Response}.
-	 * @param i The parameter index.
-	 * @param ps
-	 * 	Configuration information used to instantiate part serializers and part parsers.
-	 * 	<br>Can be <jk>null</jk>.
-	 * @return Metadata about the parameter, or <jk>null</jk> if parameter or parameter type not annotated with {@link Response}.
-	 */
-	public static ResponseMeta create(Method m, int i, PropertyStore ps) {
-		if (! hasAnnotation(Response.class, m, i))
-			return null;
-		return new ResponseMeta.Builder(ps).apply(m, i).build();
-	}
-
-	/**
-	 * Create metadata from specified method return.
-	 *
-	 * @param m The method annotated with {@link Response}.
-	 * @param ps
-	 * 	Configuration information used to instantiate part serializers and part parsers.
-	 * 	<br>Can be <jk>null</jk>.
-	 * @return Metadata about the parameter, or <jk>null</jk> if parameter or parameter type not annotated with {@link Response}.
-	 */
-	public static ResponseMeta create(Method m, PropertyStore ps) {
-		if (! hasAnnotation(Response.class, m))
-			return null;
-		return new ResponseMeta.Builder(ps).apply(m).build();
-	}
+	public static ResponseBeanMeta NULL = new ResponseBeanMeta(new Builder(PropertyStore.DEFAULT));
 
 	/**
 	 * Create metadata from specified class.
@@ -73,10 +44,10 @@ public class ResponseMeta {
 	 * 	<br>Can be <jk>null</jk>.
 	 * @return Metadata about the class, or <jk>null</jk> if class not annotated with {@link Response}.
 	 */
-	public static ResponseMeta create(Class<?> c, PropertyStore ps) {
+	public static ResponseBeanMeta create(Class<?> c, PropertyStore ps) {
 		if (! hasAnnotation(Response.class, c))
 			return null;
-		return new ResponseMeta.Builder(ps).apply(c).build();
+		return new ResponseBeanMeta.Builder(ps).apply(c).build();
 	}
 
 	//-----------------------------------------------------------------------------------------------------------------
@@ -85,24 +56,30 @@ public class ResponseMeta {
 
 	private final ClassMeta<?> cm;
 	private final int code;
-	private final Map<String,ResponsePropertyMeta> headers;
+	private final Map<String,ResponseBeanPropertyMeta> headerMethods;
+	private final Method statusMethod;
+	private final ResponseBeanPropertyMeta bodyMethod;
 	private final HttpPartSerializer partSerializer;
 	private final HttpPartSchema schema;
 	private final boolean usePartSerializer;
 
-	ResponseMeta(Builder b) {
+	ResponseBeanMeta(Builder b) {
 		this.cm = b.cm;
 		this.code = b.code;
 		this.partSerializer = ClassUtils.newInstance(HttpPartSerializer.class, b.partSerializer, true, b.ps);
 		this.schema = b.schema.build();
 		this.usePartSerializer = b.usePartSerializer || partSerializer != null;
-		Map<String,ResponsePropertyMeta> headers = new LinkedHashMap<>();
-		for (Map.Entry<String,ResponsePropertyMeta.Builder> e : b.headers.entrySet()) {
-			ResponsePropertyMeta pm = e.getValue().build(partSerializer);
-			headers.put(e.getKey(), pm);
+
+		Map<String,ResponseBeanPropertyMeta> hm = new LinkedHashMap<>();
+		for (Map.Entry<String,ResponseBeanPropertyMeta.Builder> e : b.headerMethods.entrySet()) {
+			ResponseBeanPropertyMeta pm = e.getValue().build(partSerializer);
+			hm.put(e.getKey(), pm);
 
 		}
-		this.headers = Collections.unmodifiableMap(headers);
+		this.headerMethods = Collections.unmodifiableMap(hm);
+
+		this.bodyMethod = b.bodyMethod == null ? null : b.bodyMethod.build(partSerializer);
+		this.statusMethod = b.statusMethod;
 	}
 
 	static class Builder {
@@ -112,33 +89,55 @@ public class ResponseMeta {
 		boolean usePartSerializer;
 		Class<? extends HttpPartSerializer> partSerializer;
 		HttpPartSchemaBuilder schema = HttpPartSchema.create();
-		Map<String,ResponsePropertyMeta.Builder> headers = new LinkedHashMap<>();
+
+		Map<String,ResponseBeanPropertyMeta.Builder> headerMethods = new LinkedHashMap<>();
+		ResponseBeanPropertyMeta.Builder bodyMethod;
+		Method statusMethod;
 
 		Builder(PropertyStore ps) {
 			this.ps = ps;
 		}
 
-		Builder apply(Method m, int i) {
-			return apply(m.getParameterTypes()[i]).apply(getAnnotation(Response.class, m, i));
-		}
-
-		Builder apply(Method m) {
-			return apply(m.getReturnType()).apply(getAnnotation(Response.class, m));
-		}
-
 		Builder apply(Class<?> c) {
 			apply(getAnnotation(Response.class, c));
 			this.cm = BeanContext.DEFAULT.getClassMeta(c);
 			for (Method m : ClassUtils.getAllMethods(c, false)) {
 				if (isAll(m, PUBLIC, HAS_NO_ARGS)) {
-					Header h = m.getAnnotation(Header.class);
-					if (h != null) {
-						String n = h.name();
+					if (hasAnnotation(ResponseHeader.class, m)) {
+						if (m.getParameterTypes().length != 0)
+							throw new InvalidAnnotationException("@ResponseHeader annotation on method cannot have arguments.  Method=''{0}''", m);
+						Class<?> rt = m.getReturnType();
+						if (rt == void.class)
+							throw new InvalidAnnotationException("Invalid return type for @ResponseHeader annotation on method.  Method=''{0}''", m);
+						ResponseHeader a = getAnnotation(ResponseHeader.class, m);
+						String n = a.name();
 						if (n.isEmpty())
 							n = m.getName();
-						HttpPartSchemaBuilder s = HttpPartSchema.create().apply(h);
-						getProperty(n, HttpPartType.HEADER).apply(s).getter(m);
+						HttpPartSchemaBuilder s = HttpPartSchema.create().apply(a);
+						headerMethods.put(n, ResponseBeanPropertyMeta.create().name(n).partType(HttpPartType.HEADER).apply(s).getter(m));
+					}
+					if (hasAnnotation(ResponseStatus.class, m)) {
+						if (m.getParameterTypes().length != 0)
+							throw new InvalidAnnotationException("@ResponseStatus annotation on method cannot have arguments.  Method=''{0}''", m);
+						Class<?> rt = m.getReturnType();
+						if (rt != int.class || rt != Integer.class)
+							throw new InvalidAnnotationException("Invalid return type for @ResponseStatus annotation on method.  Method=''{0}''", m);
+						statusMethod = m;
 					}
+					if (hasAnnotation(ResponseBody.class, m)) {
+						if (m.getParameterTypes().length != 0)
+							throw new InvalidAnnotationException("@ResponseBody annotation on method cannot have arguments.  Method=''{0}''", m);
+						Class<?> rt = m.getReturnType();
+						if (rt == void.class)
+							throw new InvalidAnnotationException("Invalid return type for @ResponseBody annotation on method.  Method=''{0}''", m);
+						ResponseBody a = getAnnotation(ResponseBody.class, m);
+						HttpPartSchemaBuilder s = HttpPartSchema.create().apply(a);
+						bodyMethod = ResponseBeanPropertyMeta.create().partType(HttpPartType.BODY).apply(s).getter(m);
+					}
+					if (hasAnnotation(Body.class, m))
+						throw new InvalidAnnotationException("@Body annotation cannot be used in a @Response bean.  Use @ResponseBody instead.  Method=''{0}''", m);
+					if (hasAnnotation(Header.class, m))
+						throw new InvalidAnnotationException("@Header annotation cannot be used in a @Response bean.  Use @ResponseHeader instead.  Method=''{0}''", m);
 				}
 			}
 			return this;
@@ -159,17 +158,8 @@ public class ResponseMeta {
 			return this;
 		}
 
-		ResponseMeta build() {
-			return new ResponseMeta(this);
-		}
-
-		private ResponsePropertyMeta.Builder getProperty(String name, HttpPartType partType) {
-			ResponsePropertyMeta.Builder b = headers.get(name);
-			if (b == null) {
-				b = ResponsePropertyMeta.create().name(name).partType(partType);
-				headers.put(name, b);
-			}
-			return b;
+		ResponseBeanMeta build() {
+			return new ResponseBeanMeta(this);
 		}
 	}
 
@@ -192,12 +182,30 @@ public class ResponseMeta {
 	}
 
 	/**
-	 * Returns metadata about headers defined on the response object.
+	 * Returns metadata about the <ja>@ResponseHeader</ja>-annotated methods.
+	 *
+	 * @return Metadata about the <ja>@ResponseHeader</ja>-annotated methods, or an empty collection if none exist.
+	 */
+	public Collection<ResponseBeanPropertyMeta> getHeaderMethods() {
+		return headerMethods.values();
+	}
+
+	/**
+	 * Returns metadata about the <ja>@ResponseBody</ja>-annotated method.
+	 *
+	 * @return Metadata about the <ja>@ResponseBody</ja>-annotated method, or <jk>null</jk> if it doesn't exist.
+	 */
+	public ResponseBeanPropertyMeta getBodyMethod() {
+		return bodyMethod;
+	}
+
+	/**
+	 * Returns metadata about the <ja>@ResponseBody</ja>-annotated method.
 	 *
-	 * @return Metadata about headers defined on the response object.
+	 * @return Metadata about the <ja>@ResponseBody</ja>-annotated method, or <jk>null</jk> if it doesn't exist.
 	 */
-	public Collection<ResponsePropertyMeta> getHeaderMetas() {
-		return headers.values();
+	public Method getStatusMethod() {
+		return statusMethod;
 	}
 
 	/**
@@ -212,11 +220,10 @@ public class ResponseMeta {
 	/**
 	 * Returns the part serializer to use to serialize this response.
 	 *
-	 * @param _default The default serializer to use if it's not defined on this metadata.
 	 * @return The part serializer to use to serialize this response.
 	 */
-	public HttpPartSerializer getPartSerializer(HttpPartSerializer _default) {
-		return partSerializer == null ? _default : partSerializer;
+	public HttpPartSerializer getPartSerializer() {
+		return partSerializer;
 	}
 
 	/**
@@ -227,5 +234,4 @@ public class ResponseMeta {
 	public ClassMeta<?> getClassMeta() {
 		return cm;
 	}
-
 }
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/httppart/ResponsePropertyMeta.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/httppart/bean/ResponseBeanPropertyMeta.java
similarity index 89%
rename from juneau-core/juneau-marshall/src/main/java/org/apache/juneau/httppart/ResponsePropertyMeta.java
rename to juneau-core/juneau-marshall/src/main/java/org/apache/juneau/httppart/bean/ResponseBeanPropertyMeta.java
index 53f149f..fbf667a 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/httppart/ResponsePropertyMeta.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/httppart/bean/ResponseBeanPropertyMeta.java
@@ -10,20 +10,21 @@
 // * "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.httppart;
+package org.apache.juneau.httppart.bean;
 
 import java.lang.reflect.*;
 
 import org.apache.juneau.*;
 import org.apache.juneau.http.annotation.*;
+import org.apache.juneau.httppart.*;
 import org.apache.juneau.internal.*;
 
 /**
  * Represents the metadata gathered from a getter method of a class annotated with {@link Response}.
  */
-public class ResponsePropertyMeta {
+public class ResponseBeanPropertyMeta {
 
-	static ResponsePropertyMeta.Builder create() {
+	static ResponseBeanPropertyMeta.Builder create() {
 		return new Builder();
 	}
 
@@ -37,7 +38,7 @@ public class ResponsePropertyMeta {
 	private final HttpPartSerializer serializer;
 	private final HttpPartSchema schema;
 
-	ResponsePropertyMeta(Builder b, HttpPartSerializer serializer) {
+	ResponseBeanPropertyMeta(Builder b, HttpPartSerializer serializer) {
 		this.partType = b.partType;
 		this.schema = b.schema.build();
 		this.partName = StringUtils.firstNonEmpty(schema.getName(), b.name);
@@ -77,8 +78,8 @@ public class ResponsePropertyMeta {
 			return this;
 		}
 
-		ResponsePropertyMeta build(HttpPartSerializer serializer) {
-			return new ResponsePropertyMeta(this, serializer);
+		ResponseBeanPropertyMeta build(HttpPartSerializer serializer) {
+			return new ResponseBeanPropertyMeta(this, serializer);
 		}
 	}
 
@@ -116,11 +117,10 @@ public class ResponsePropertyMeta {
 	/**
 	 * Returns the serializer to use for serializing the bean property value.
 	 *
-	 * @param _default The default serializer to use if not defined on the annotation.
 	 * @return The serializer to use for serializing the bean property value.
 	 */
-	public HttpPartSerializer getSerializer(HttpPartSerializer _default) {
-		return serializer == null ? _default : serializer;
+	public HttpPartSerializer getSerializer() {
+		return serializer;
 	}
 
 	/**
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/remoteable/RemoteMethodBeanArg.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/remoteable/RemoteMethodBeanArg.java
index 99b5bb0..a2c3c76 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/remoteable/RemoteMethodBeanArg.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/remoteable/RemoteMethodBeanArg.java
@@ -16,6 +16,7 @@ import static org.apache.juneau.internal.ClassUtils.*;
 
 import org.apache.juneau.http.annotation.*;
 import org.apache.juneau.httppart.*;
+import org.apache.juneau.httppart.bean.*;
 
 /**
  * Represents the metadata about an {@link RequestBean}-annotated argument of a method on a remote proxy interface.
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/remoteable/RemoteableMethodMeta.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/remoteable/RemoteableMethodMeta.java
index bc4a08b..23e3a0f 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/remoteable/RemoteableMethodMeta.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/remoteable/RemoteableMethodMeta.java
@@ -22,6 +22,7 @@ import java.util.*;
 import org.apache.juneau.*;
 import org.apache.juneau.http.annotation.*;
 import org.apache.juneau.httppart.*;
+import org.apache.juneau.httppart.bean.*;
 
 /**
  * Contains the meta-data about a Java method on a remoteable interface.
diff --git a/juneau-doc/src/main/javadoc/overview.html b/juneau-doc/src/main/javadoc/overview.html
index 69a66d6..b7d0af4 100644
--- a/juneau-doc/src/main/javadoc/overview.html
+++ b/juneau-doc/src/main/javadoc/overview.html
@@ -14414,9 +14414,9 @@ TODO(7.2.0)
 </p>
 <ul class='doctree'>
 	<li class='ja'>{@link org.apache.juneau.http.annotation.Response Response}
+	<li class='ja'>{@link org.apache.juneau.http.annotation.ResponseBody ResponseBody}
 	<li class='ja'>{@link org.apache.juneau.http.annotation.ResponseHeader ResponseHeader}
 	<li class='ja'>{@link org.apache.juneau.http.annotation.ResponseStatus ResponseStatus}
-	<li class='ja'>{@link org.apache.juneau.http.annotation.ResponseStatuses ResponseStatues}
 </ul>
 <p>
 	The sub-annotations used in the annotation above are:
@@ -15890,12 +15890,12 @@ TODO(7.2.0)
 	types to denote them as an HTTP response status on server-side REST method parameters.
 </p>
 <ul class='doctree'>
-	<li class='ja'>{@link org.apache.juneau.http.annotation.ResponseStatus ResponseStatus}
+	<li class='ja'>{@link org.apache.juneau.http.annotation.Status ResponseStatus}
 	<ul>
-		<li class='jf'>{@link org.apache.juneau.http.annotation.ResponseStatus#api() api()} - Free-form Swagger JSON.
-		<li class='jf'>{@link org.apache.juneau.http.annotation.ResponseStatus#code() code()} - The HTTP status of the response.
-		<li class='jf'>{@link org.apache.juneau.http.annotation.ResponseStatus#description() description()} - Description.
-		<li class='jf'>{@link org.apache.juneau.http.annotation.ResponseStatus#value() value()} - A synonym for <code>code</code>.
+		<li class='jf'>{@link org.apache.juneau.http.annotation.Status#api() api()} - Free-form Swagger JSON.
+		<li class='jf'>{@link org.apache.juneau.http.annotation.Status#code() code()} - The HTTP status of the response.
+		<li class='jf'>{@link org.apache.juneau.http.annotation.Status#description() description()} - Description.
+		<li class='jf'>{@link org.apache.juneau.http.annotation.Status#value() value()} - A synonym for <code>code</code>.
 	</ul>
 </ul>
 <p>
@@ -15969,8 +15969,8 @@ TODO(7.2.0)
 <h4 class='topic new' onclick='toggle(this)'><a href='#juneau-rest-server.HttpPartAnnotations.ResponseStatuses' id='juneau-rest-server.HttpPartAnnotations.ResponseStatuses'>7.9.12 - @ResponseStatuses</a></h4>
 <div class='topic'><!-- START: 7.9.12 - juneau-rest-server.HttpPartAnnotations.ResponseStatuses -->
 <p>
-	The {@link org.apache.juneau.http.annotation.ResponseStatuses @ResponseStatuses} annotation is used to 
-	associate multiple {@link org.apache.juneau.http.annotation.ResponseStatus @ResponseStatus} annotations to the same parameter or class.
+	The {@link org.apache.juneau.http.annotation.ResponseStatus @ResponseStatuses} annotation is used to 
+	associate multiple {@link org.apache.juneau.http.annotation.Status @ResponseStatus} annotations to the same parameter or class.
 </p>
 
 <h5 class='section'>Example:</h5>
diff --git a/juneau-doc/src/main/resources/Topics/07.juneau-rest-server/09.HttpPartAnnotations.html b/juneau-doc/src/main/resources/Topics/07.juneau-rest-server/09.HttpPartAnnotations.html
index 6be17bd..7d9f2bf 100644
--- a/juneau-doc/src/main/resources/Topics/07.juneau-rest-server/09.HttpPartAnnotations.html
+++ b/juneau-doc/src/main/resources/Topics/07.juneau-rest-server/09.HttpPartAnnotations.html
@@ -31,10 +31,10 @@
 	The annotations used for defining the schema for response HTTP parts are:
 </p>
 <ul class='doctree'>
-	<li class='ja'>{@link org.apache.juneau.http.annotation.Response Response}
+	<li class='ja'>{@link org.apache.juneau.http.annotation.ResponseBody ResponseBody}
 	<li class='ja'>{@link org.apache.juneau.http.annotation.ResponseHeader ResponseHeader}
 	<li class='ja'>{@link org.apache.juneau.http.annotation.ResponseStatus ResponseStatus}
-	<li class='ja'>{@link org.apache.juneau.http.annotation.ResponseStatuses ResponseStatues}
+	<li class='ja'>{@link org.apache.juneau.http.annotation.Response Response}
 </ul>
 <p>
 	The sub-annotations used in the annotation above are:
diff --git a/juneau-doc/src/main/resources/Topics/07.juneau-rest-server/09.HttpPartAnnotations/09.ResponseBody.html b/juneau-doc/src/main/resources/Topics/07.juneau-rest-server/09.HttpPartAnnotations/09.ResponseBody.html
new file mode 100644
index 0000000..fac9246
--- /dev/null
+++ b/juneau-doc/src/main/resources/Topics/07.juneau-rest-server/09.HttpPartAnnotations/09.ResponseBody.html
@@ -0,0 +1,17 @@
+<!--
+/***************************************************************************************************************************
+ * 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.
+ ***************************************************************************************************************************/
+ -->
+
+{todo} @ResponseBody
+
diff --git a/juneau-doc/src/main/resources/Topics/07.juneau-rest-server/09.HttpPartAnnotations/11.ResponseStatus.html b/juneau-doc/src/main/resources/Topics/07.juneau-rest-server/09.HttpPartAnnotations/11.ResponseStatus.html
index 4e41225..ce2a7d7 100644
--- a/juneau-doc/src/main/resources/Topics/07.juneau-rest-server/09.HttpPartAnnotations/11.ResponseStatus.html
+++ b/juneau-doc/src/main/resources/Topics/07.juneau-rest-server/09.HttpPartAnnotations/11.ResponseStatus.html
@@ -13,7 +13,7 @@
  ***************************************************************************************************************************/
  -->
 
-{new} @ResponseStatus
+{todo} @ResponseStatus
 
 <p>
 	The {@link org.apache.juneau.http.annotation.ResponseStatus @ResponseStatus} annotation is applied to parameters and parameter 
@@ -21,12 +21,6 @@
 </p>
 <ul class='doctree'>
 	<li class='ja'>{@link org.apache.juneau.http.annotation.ResponseStatus ResponseStatus}
-	<ul>
-		<li class='jf'>{@link org.apache.juneau.http.annotation.ResponseStatus#api() api()} - Free-form Swagger JSON.
-		<li class='jf'>{@link org.apache.juneau.http.annotation.ResponseStatus#code() code()} - The HTTP status of the response.
-		<li class='jf'>{@link org.apache.juneau.http.annotation.ResponseStatus#description() description()} - Description.
-		<li class='jf'>{@link org.apache.juneau.http.annotation.ResponseStatus#value() value()} - A synonym for <code>code</code>.
-	</ul>
 </ul>
 <p>
 	It can be used in the following locations:
@@ -35,7 +29,7 @@
 	<li>Java method arguments and argument-types of server-side <ja>@RestMethod</ja>-annotated REST Java methods.
 </ul>
 <p>
-	This can only be applied to parameters and subclasses of the {@link org.apache.juneau.Value} class with an {@link java.lang.Integer} type.
+	This can only be applied to parameters of the {@link org.apache.juneau.Value} class with an {@link java.lang.Integer} type.
 	<br>The {@link org.apache.juneau.Value} object is mean to be a place-holder for the set value.
 </p>
 
@@ -46,10 +40,7 @@
 	<jk>public void</jk> login(
 		<ja>@FormData</ja>(<js>"username"</js>) String username, 
 		<ja>@FormData</ja>(<js>"password"</js>) String password,
-		<ja>@ResponseStatus</ja>(
-			code=401, 
-			description=<js>"Invalid user/pw"</js>
-		) 
+		<ja>@ResponseStatus</ja> 
 		Value&lt;Integer&gt; status
 	) 
 	{
@@ -57,38 +48,3 @@
 			status.set(401);
 	}
 </p>
-<p class='bpcode w800'>
-	<jc>// Defined on parameter class.</jc>
-	<ja>@RestMethod</ja>(name=<js>"GET"</js>, path=<js>"/user/login"</js>)
-	<jk>public void</jk> login(
-		<ja>@FormData</ja>(<js>"username"</js>) String username, 
-		<ja>@FormData</ja>(<js>"password"</js>) String password,
-		LoginStatus status
-	) 
-	{
-		<jk>if</jk> (! isValid(username, password))
-			status.set(401);
-	}
-
-	<ja>@ResponseStatus</ja>(
-		code=401, 
-		description=<js>"Invalid user/pw"</js>
-	)
-	<jk>public class</jk> LoginStatus <jk>extends</jk> Value&lt;Integer&gt; {}
-</p>
-
-<p>
-	The attributes on this annotation are used to populate the generated Swagger for the method.
-	<br>In this case, the Swagger is populated with the following:
-</p>
-<p class='bpcode w800'>
-	<jok>'/user/login'</jok>: {
-		<jok>get: {
-			<jok>responses: {
-				<jok>401</jok>: {
-					<jok>description</jok>: <jov>'Invalid user/pw'</jov>
-				}
-			}
-		}
-	}
-</p>
diff --git a/juneau-doc/src/main/resources/Topics/07.juneau-rest-server/09.HttpPartAnnotations/09.Response.html b/juneau-doc/src/main/resources/Topics/07.juneau-rest-server/09.HttpPartAnnotations/12.Response.html
similarity index 100%
rename from juneau-doc/src/main/resources/Topics/07.juneau-rest-server/09.HttpPartAnnotations/09.Response.html
rename to juneau-doc/src/main/resources/Topics/07.juneau-rest-server/09.HttpPartAnnotations/12.Response.html
diff --git a/juneau-doc/src/main/resources/Topics/07.juneau-rest-server/09.HttpPartAnnotations/12.ResponseStatuses.html b/juneau-doc/src/main/resources/Topics/07.juneau-rest-server/09.HttpPartAnnotations/12.ResponseStatuses.html
deleted file mode 100644
index 067ef96..0000000
--- a/juneau-doc/src/main/resources/Topics/07.juneau-rest-server/09.HttpPartAnnotations/12.ResponseStatuses.html
+++ /dev/null
@@ -1,85 +0,0 @@
-<!--
-/***************************************************************************************************************************
- * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *  
- *  http://www.apache.org/licenses/LICENSE-2.0
- *  
- * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations under the License.
- ***************************************************************************************************************************/
- -->
-
-{new} @ResponseStatuses
-
-<p>
-	The {@link org.apache.juneau.http.annotation.ResponseStatuses @ResponseStatuses} annotation is used to 
-	associate multiple {@link org.apache.juneau.http.annotation.ResponseStatus @ResponseStatus} annotations to the same parameter or class.
-</p>
-
-<h5 class='section'>Example:</h5>
-<p class='bpcode w800'>
-	<ja>@RestMethod</ja>(name=<js>"GET"</js>, path=<js>"/user/login"</js>)
-	<jk>public void</jk> login(
-		<ja>@FormData</ja>(<js>"username"</js>) String username, 
-		<ja>@FormData</ja>(<js>"password"</js>) String password,
-		<ja>@ResponseStatuses=</ja>{
-			<ja>@ResponseStatus</ja>(200)
-			<ja>@ResponseStatus</ja>(code=401, description=<js>"Invalid user/pw"</js>)
-		}
-		Value&lt;Integer&gt; status
-	) 
-	{
-		<jk>if</jk> (! isValid(username, password))
-			status.set(401);
-		<jk>else</jk>
-			status.set(200);
-	}
-</p>
-
-<p>
-The other option is to apply this annotation to a subclass of {@link org.apache.juneau.Value} which often leads to a cleaner
-REST method:
-</p>
-<p class='bpcode w800'>
-	<ja>@ResponseStatuses=</ja>{
-		<ja>@ResponseStatus</ja>(200)
-		<ja>@ResponseStatus</ja>(code=401, description=<js>"Invalid user/pw"</js>)
-	}
-	<jk>public class</jk> LoginStatus <jk>extends</jk> Value&lt;Integer&gt; {}
-
-	<ja>@RestMethod</ja>(name=<js>"GET"</js>, path=<js>"/user/login"</js>)
-	<jk>public void</jk> login(
-		<ja>@FormData</ja>(<js>"username"</js>) String username, 
-		<ja>@FormData</ja>(<js>"password"</js>) String password,
-		LoginStatus status
-	) 
-	{
-		<jk>if</jk> (! isValid(username, password))
-			status.set(401);
-		<jk>else</jk>
-			status.set(200);
-	}
-</p>
-<p>
-	The attributes on this annotation are used to populate the generated Swagger for the method.
-	<br>In this case, the Swagger is populated with the following:
-</p>
-<p class='bpcode w800'>
-	<jok>'/user/login'</jok>: {
-		<jok>get: {
-			<jok>responses: {
-				<jok>200</jok>: {
-					<jok>description</jok>: <jov>'OK'</jov>
-				},
-				<jok>401</jok>: {
-					<jok>description</jok>: <jov>'Invalid user/pw'</jov>
-				}
-			}
-		}
-	}
-</p>
-
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 bcfeb3c..8fd9e65 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
@@ -26,7 +26,6 @@ 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.Header;
-import org.apache.juneau.internal.*;
 import org.apache.juneau.microservice.*;
 import org.apache.juneau.rest.*;
 import org.apache.juneau.rest.annotation.*;
@@ -591,7 +590,7 @@ public class PetStoreResource extends BasicRestServletJena {
 			@Query(name="username", description="The username for login", required=true, example="myuser") String username,
 			@Query(name="password", description="The password for login in clear text", required=true, example="abc123") String password,
 			@ResponseHeader(name="X-Rate-Limit", type="integer", format="int32", description="Calls per hour allowed by the user.", example="123") Value<Integer> rateLimit,
-			ExpiresAfter expiresAfter,
+			Value<ExpiresAfter> expiresAfter,
 			RestRequest req,
 			RestResponse res
 		) throws InvalidLogin, NotAcceptable {
@@ -602,12 +601,21 @@ public class PetStoreResource extends BasicRestServletJena {
 		Date d = new Date(System.currentTimeMillis() + 30 * 60 * 1000);
 		req.getSession().setAttribute("login-expires", d);
 		rateLimit.set(1000);
-		expiresAfter.set(DateUtils.formatDate(d));
+		expiresAfter.set(new ExpiresAfter(d));
 		return OK;
 	}
 
-	@ResponseHeader(name="X-Expires-After", type="string", format="date-time", description="Date in UTC when token expires", example="20120-10-21")
-	public static class ExpiresAfter extends Value<String> {}
+	@ResponseHeader(name="X-Expires-After", type="string", format="date-time", description="Date in UTC when token expires", example="2012-10-21")
+	public static class ExpiresAfter {
+		private final Calendar c;
+		public ExpiresAfter(Date d) {
+			this.c = new GregorianCalendar();
+			c.setTime(d);
+		}
+		public Calendar toCalendar() {
+			return c;
+		}
+	}
 
 	@RestMethod(
 		name="GET",
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 e524e81..aa95c41 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
@@ -32,6 +32,7 @@ import org.apache.http.entity.*;
 import org.apache.http.impl.client.*;
 import org.apache.juneau.*;
 import org.apache.juneau.httppart.*;
+import org.apache.juneau.httppart.bean.*;
 import org.apache.juneau.internal.*;
 import org.apache.juneau.json.*;
 import org.apache.juneau.parser.*;
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/BasicRestInfoProvider.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/BasicRestInfoProvider.java
index 81153f9..2c88f30 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/BasicRestInfoProvider.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/BasicRestInfoProvider.java
@@ -396,7 +396,7 @@ public class BasicRestInfoProvider implements RestInfoProvider {
 
 				RestParamType in = mp.getParamType();
 
-				if (in == OTHER || in == RESPONSE || in == RESPONSE_HEADER || in == RESPONSE_STATUS)
+				if (in == RestParamType.OTHER || in == RESPONSE_BODY || in == RESPONSE_HEADER || in == RESPONSE_STATUS)
 					continue;
 
 				String key = in.toString() + '.' + (in == BODY ? "body" : mp.getName());
@@ -457,34 +457,114 @@ public class BasicRestInfoProvider implements RestInfoProvider {
 
 			ObjectMap responses = op.getObjectMap("responses", true);
 
-			// Gather responses from @Response-annotated exceptions.
-			for (RestMethodThrown rt : context.getRestMethodThrowns(m)) {
-				ObjectMap md = resolve(vr, rt.getApi(), "RestMethodThrown on class {0} method {1}", c, m);
-				for (String code : md.keySet()) {
-					ObjectMap response = md.getObjectMap(code);
-					ObjectMap om = responses.getObjectMap(code, true);
-					om.appendSkipEmpty("description", resolve(vr, response.getString("description")));
-					om.appendSkipEmpty("x-example", parseAnything(vr, response.getString("example"), "RestMethodThrown/example on class {0} method {1}", c, m));
-					om.appendSkipEmpty("examples", parseMap(vr, response.get("examples"), "RestMethodThrown/examples on class {0} method {1}", c, m));
-					om.appendSkipEmpty("schema", parseMap(vr, response.get("schema"), "RestMethodThrown/schema on class {0} method {1}", c, m));
-					om.appendSkipEmpty("headers", parseMap(vr, response.get("headers"), "RestMethodThrown/headers on class {0} method {1}", c, m));
+			for (Class<?> ec : m.getExceptionTypes()) {
+				if (hasAnnotation(Response.class, ec)) {
+					Response r = getAnnotation(Response.class, ec);
+					Set<Integer> codes = new LinkedHashSet<>();
+					for (int i : r.value())
+						codes.add(i);
+					for (int i : r.code())
+						codes.add(i);
+					if (codes.isEmpty())
+						codes.add(500);
+					for (int code : codes) {
+						ObjectMap om = responses.getObjectMap(String.valueOf(code), true);
+						ObjectMap api = parseMap(vr, r.api(), "RestMethodThrown/api on class {0} method {1}", c, m);
+						ObjectMap headers = new ObjectMap();
+
+						if (api != null) {
+							om.appendSkipEmpty("description", resolve(vr, api.getString("description")));
+							om.appendSkipEmpty("x-example", parseAnything(vr, api.getString("example"), "RestMethodThrown/example on class {0} method {1}", c, m));
+							om.appendSkipEmpty("examples", api.getObjectMap("examples"));
+							om.appendSkipEmpty("schema", api.getObjectMap("schema"));
+							if (api.containsKey("headers"))
+								for (Map.Entry<String,Object> e : api.getObjectMap("headers").entrySet())
+									headers.put(e.getKey(), e.getValue());
+						}
+						om.appendSkipEmpty("description", resolve(vr, r.description()));
+						om.appendSkipEmpty("x-example", parseAnything(vr, r.example(), "RestMethodThrown/example on class {0} method {1}", c, m));
+						om.appendSkipEmpty("examples", parseMap(vr, r.examples(), "RestMethodThrown/examples on class {0} method {1}", c, m));
+						om.appendSkipEmpty("schema", resolve(vr, HttpPartSchema.create(r.schema()).getApi()));
+						for (ResponseHeader h : r.headers()) {
+							headers.put(h.name(), resolve(vr, HttpPartSchema.create(h).getApi()));
+						}
+						om.appendSkipEmpty("headers", headers);
+					}
 				}
 			}
 
-			RestMethodReturn r = context.getRestMethodReturn(m);
-			String rStatus = r.getCode() == 0 ? "200" : String.valueOf(r.getCode());
+			if (hasAnnotation(Response.class, m)) {
+				Response r = getAnnotation(Response.class, m);
+				Set<Integer> codes = new LinkedHashSet<>();
+				for (int i : r.value())
+					codes.add(i);
+				for (int i : r.code())
+					codes.add(i);
+				if (codes.isEmpty())
+					codes.add(200);
+				for (int code : codes) {
+					ObjectMap om = responses.getObjectMap(String.valueOf(code), true);
+					ObjectMap api = parseMap(vr, r.api(), "RestMethodReturn/api on class {0} method {1}", c, m);
+					ObjectMap headers = new ObjectMap();
+
+					if (api != null) {
+						om.appendSkipEmpty("description", api.getString("description"));
+						om.appendSkipEmpty("x-example", parseAnything(vr, api.getString("example"), "RestMethodReturn/example on class {0} method {1}", c, m));
+						om.appendSkipEmpty("examples", api.getObjectMap("examples"));
+						om.appendSkipEmpty("schema", api.getObjectMap("schema"));
+						if (api.containsKey("headers"))
+							for (Map.Entry<String,Object> e : api.getObjectMap("headers").entrySet())
+								headers.put(e.getKey(), e.getValue());
+					}
+					om.appendSkipEmpty("description", resolve(vr, r.description()));
+					om.appendSkipEmpty("x-example", parseAnything(vr, r.example(), "RestMethodReturn/example on class {0} method {1}", c, m));
+					om.appendSkipEmpty("examples", parseMap(vr, r.examples(), "RestMethodReturn/examples on class {0} method {1}", c, m));
+					om.appendSkipEmpty("schema", resolve(vr, HttpPartSchema.create(r.schema()).getApi()));
+					for (ResponseHeader h : r.headers()) {
+						headers.put(h.name(), resolve(vr, HttpPartSchema.create(h).getApi()));
+					}
+					om.appendSkipEmpty("headers", headers);
 
-			ObjectMap rom = responses.getObjectMap(rStatus, true);
+					Type type = m.getGenericReturnType();
+					if (type instanceof ParameterizedType) {
+						ParameterizedType pt = (ParameterizedType)type;
+						if (pt.getRawType().equals(Value.class))
+							type = pt.getActualTypeArguments()[0];
+					}
 
-			if (r.getType() != void.class) {
-				ObjectMap rmd = resolve(vr, r.getApi(), "RestMethodReturn on class {0} method {1}", c, m);
-				rom.appendSkipEmpty("description", resolve(vr, rmd.getString("description")));
-				rom.appendSkipEmpty("x-example", parseAnything(vr, rmd.getString("example"), "RestMethodReturn/example on class {0} method {1}", c, m));
-				rom.appendSkipEmpty("examples", parseMap(vr, rmd.get("examples"), "RestMethodReturn/examples on class {0} method {1}", c, m));
-				rom.appendSkipEmpty("schema", parseMap(vr, rmd.get("schema"), "RestMethodReturn/schema on class {0} method {1}", c, m));
-				rom.appendSkipEmpty("headers", parseMap(vr, rmd.get("headers"), "RestMethodReturn/headers on class {0} method {1}", c, m));
-				rom.appendSkipEmpty("schema", getSchema(req, rom.getObjectMap("schema", true), js, m.getGenericReturnType()));
-				addXExamples(req, sm, rom, "ok", js, m.getGenericReturnType());
+					om.appendSkipEmpty("schema", getSchema(req, om.getObjectMap("schema", true), js, type));
+				}
+			}
+
+			if (hasAnnotation(ResponseBody.class, m)) {
+				ResponseBody r = getAnnotation(ResponseBody.class, m);
+				ObjectMap om = responses.getObjectMap("200", true);
+				ObjectMap api = parseMap(vr, r.api(), "RestMethodReturn/api on class {0} method {1}", c, m);
+				ObjectMap headers = new ObjectMap();
+
+				if (api != null) {
+					om.appendSkipEmpty("description", api.getString("description"));
+					om.appendSkipEmpty("x-example", parseAnything(vr, api.getString("example"), "RestMethodReturn/example on class {0} method {1}", c, m));
+					om.appendSkipEmpty("examples", api.getObjectMap("examples"));
+					om.appendSkipEmpty("schema", api.getObjectMap("schema"));
+					if (api.containsKey("headers"))
+						for (Map.Entry<String,Object> e : api.getObjectMap("headers").entrySet())
+							headers.put(e.getKey(), e.getValue());
+				}
+				om.appendSkipEmpty("x-example", parseAnything(vr, r.example(), "RestMethodReturn/example on class {0} method {1}", c, m));
+				om.appendSkipEmpty("examples", parseMap(vr, r.examples(), "RestMethodReturn/examples on class {0} method {1}", c, m));
+				om.appendSkipEmpty("schema", resolve(vr, HttpPartSchema.create(r.schema()).getApi()));
+
+				Type type = m.getGenericReturnType();
+				if (type instanceof ParameterizedType) {
+					ParameterizedType pt = (ParameterizedType)type;
+					if (pt.getRawType().equals(Value.class))
+						type = pt.getActualTypeArguments()[0];
+				}
+
+				om.appendSkipEmpty("schema", getSchema(req, om.getObjectMap("schema", true), js, type));
+
+				addXExamples(req, sm, om, "ok", js, m.getGenericReturnType());
 			}
 
 			// Finally, look for @ResponseHeader parameters defined on method.
@@ -521,7 +601,7 @@ public class BasicRestInfoProvider implements RestInfoProvider {
 						header.appendSkipEmpty("items", parseMap(vr, pi2.get("items"), "@ResponseHeader/items on class {0} method {1}", c, m));
 					}
 
-				} else if (in == RESPONSE) {
+				} else if (in == RESPONSE_BODY) {
 					ObjectMap pi = resolve(vr, mp.getApi(), "@Response on class {0} method {1}", c, m);
 					for (String code : pi.keySet()) {
 						ObjectMap pi2 = pi.getObjectMap(code, true);
@@ -654,7 +734,13 @@ public class BasicRestInfoProvider implements RestInfoProvider {
 	}
 
 	private ObjectMap resolve(VarResolverSession vs, ObjectMap om) throws ParseException {
-		ObjectMap om2 = om.containsKey("_value") ? parseMap(vs, om.remove("_value")) : new ObjectMap();
+		ObjectMap om2 = null;
+		if (om.containsKey("_value")) {
+			om = om.modifiable();
+			om2 = parseMap(vs, om.remove("_value"));
+		} else {
+			om2 = new ObjectMap();
+		}
 		for (Map.Entry<String,Object> e : om.entrySet()) {
 			Object val = e.getValue();
 			if (val instanceof ObjectMap) {
@@ -746,6 +832,7 @@ public class BasicRestInfoProvider implements RestInfoProvider {
 			String s = o.toString();
 			if (s.isEmpty())
 				return null;
+			s = vs.resolve(s);
 			return RestUtils.parseAnything(s);
 		} catch (ParseException e) {
 			throw new SwaggerException(e, "Malformed swagger JSON encountered in "+location+".", locationArgs);
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/Value.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/ResponsePartMeta.java
similarity index 59%
copy from juneau-core/juneau-marshall/src/main/java/org/apache/juneau/Value.java
copy to juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/ResponsePartMeta.java
index 4a92954..2f675af 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/Value.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/ResponsePartMeta.java
@@ -10,75 +10,61 @@
 // * "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;
+package org.apache.juneau.rest;
+
+import org.apache.juneau.httppart.*;
 
 /**
- * Represents a simple settable value.
- *
- * <p>
- * This object is not thread safe.
- *
- * @param <T> The value type.
+ * Represents the information needed to serialize a response part such as a response header or body.
  */
-public class Value<T> {
-
-	private T t;
-	private ValueListener<T> listener;
+public class ResponsePartMeta {
 
 	/**
-	 * Constructor.
+	 * Represents a non-existent meta.
 	 */
-	public Value() {
-	}
+	public static final ResponsePartMeta NULL = new ResponsePartMeta(null, null, null);
 
-	/**
-	 * Constructor.
-	 *
-	 * @param t Initial value.
-	 */
-	public Value(T t) {
-		set(t);
-	}
+	private final HttpPartType partType;
+	private final HttpPartSchema schema;
+	private final HttpPartSerializer serializer;
 
 	/**
-	 * Adds a listener for this value.
+	 * Constructor.
 	 *
-	 * @param listener The new listener for this value.
-	 * @return This object (for method chaining).
+	 * @param partType The part type.
+	 * @param schema The part schema.
+	 * @param serializer The serializer to use to serialize the part.
 	 */
-	public Value<T> listener(ValueListener<T> listener) {
-		this.listener = listener;
-		return this;
+	public ResponsePartMeta(HttpPartType partType, HttpPartSchema schema, HttpPartSerializer serializer) {
+		this.partType = partType;
+		this.schema = schema;
+		this.serializer = serializer;
 	}
 
 	/**
-	 * Sets the value.
+	 * Returns the part type.
 	 *
-	 * @param t The new value.
-	 * @return This object (for method chaining).
+	 * @return The part type.
 	 */
-	public Value<T> set(T t) {
-		this.t = t;
-		if (listener != null)
-			listener.onSet(t);
-		return this;
+	public HttpPartType getPartType() {
+		return partType;
 	}
 
 	/**
-	 * Returns the value.
+	 * Returns the part schema.
 	 *
-	 * @return The value, or <jk>null</jk> if it is not set.
+	 * @return The part schema.
 	 */
-	public T get() {
-		return t;
+	public HttpPartSchema getSchema() {
+		return schema;
 	}
 
 	/**
-	 * Returns <jk>true</jk> if the value is set.
+	 * Returns the part serializer.
 	 *
-	 * @return <jk>true</jk> if the value is set.
+	 * @return The part serializer.
 	 */
-	public boolean isSet() {
-		return get() != null;
+	public HttpPartSerializer getSerializer() {
+		return serializer;
 	}
 }
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestContext.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestContext.java
index 818a98a..ddf7748 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestContext.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestContext.java
@@ -40,6 +40,7 @@ import org.apache.juneau.htmlschema.*;
 import org.apache.juneau.http.*;
 import org.apache.juneau.http.annotation.*;
 import org.apache.juneau.httppart.*;
+import org.apache.juneau.httppart.bean.*;
 import org.apache.juneau.internal.*;
 import org.apache.juneau.json.*;
 import org.apache.juneau.jsonschema.*;
@@ -2853,8 +2854,6 @@ public final class RestContext extends BeanContext {
 	private final ClasspathResourceManager staticResourceManager;
 	private final ConcurrentHashMap<Integer,AtomicInteger> stackTraceHashes = new ConcurrentHashMap<>();
 
-	private final Map<Class<?>,ResponseMeta> responseMetas = new ConcurrentHashMap<>();
-
 	/**
 	 * Constructor.
 	 *
@@ -4244,26 +4243,6 @@ public final class RestContext extends BeanContext {
 	}
 
 	/**
-	 * Returns the parameters defined on the specified Java method.
-	 *
-	 * @param method The Java method to check.
-	 * @return The parameters defined on the Java method.
-	 */
-	public RestMethodReturn getRestMethodReturn(Method method) {
-		return callMethods.get(method.getName()).methodReturn;
-	}
-
-	/**
-	 * Returns the parameters defined on the specified Java method.
-	 *
-	 * @param method The Java method to check.
-	 * @return The parameters defined on the Java method.
-	 */
-	public RestMethodThrown[] getRestMethodThrowns(Method method) {
-		return callMethods.get(method.getName()).methodThrowns;
-	}
-
-	/**
 	 * Returns the media type for the specified file name.
 	 *
 	 * <h5 class='section'>See Also:</h5>
@@ -4346,7 +4325,7 @@ public final class RestContext extends BeanContext {
 				rp[i] = new RestParamDefaults.FormDataObject(method, s, t, ps);
 			} else if (hasAnnotation(Path.class, method, i)) {
 				s = HttpPartSchema.create(Path.class, method, i);
-				rp[i] = new RestParamDefaults.PathObject(method, s, t, ps);
+				rp[i] = new RestParamDefaults.PathObject(method, i, s, t, ps);
 			} else if (hasAnnotation(Body.class, method, i)) {
 				s = HttpPartSchema.create(Body.class, method, i);
 				rp[i] = new RestParamDefaults.BodyObject(method, s, t, ps);
@@ -4355,22 +4334,18 @@ public final class RestContext extends BeanContext {
 				RequestBeanMeta rbm = RequestBeanMeta.create(method, i, ps);
 				rp[i] = new RestParamDefaults.RequestBeanObject(method, rbm, t);
 
-			} else if (hasAnnotation(Response.class, method, i)) {
+			} else if (hasAnnotation(Response.class, method, i) || hasAnnotation(Response.class, Value.getValueType(method, i))) {
 				s = HttpPartSchema.create(Response.class, method, i);
-				rp[i] = new RestParamDefaults.ResponseParamObject(method, i, s, t, ps);
-			} else if (hasAnnotation(ResponseHeader.class, method, i)) {
+				rp[i] = new RestParamDefaults.ResponseBeanObject(method, i, s, t, ps);
+			} else if (hasAnnotation(ResponseHeader.class, method, i) || hasAnnotation(ResponseHeader.class, Value.getValueType(method, i))) {
 				s = HttpPartSchema.create(ResponseHeader.class, method, i);
-				rp[i] = new RestParamDefaults.ResponseHeaderObject(method, s, t, ps);
-			} else if (hasAnnotation(ResponseStatus.class, method, i)) {
-				s = HttpPartSchema.create(ResponseStatus.class, method, i);
-				rp[i] = new RestParamDefaults.ResponseStatusObject(method, s, t);
+				rp[i] = new RestParamDefaults.ResponseHeaderObject(method, i, s, t, ps);
+			} else if (hasAnnotation(ResponseBody.class, method, i) || hasAnnotation(ResponseBody.class, Value.getValueType(method, i))) {
+				s = HttpPartSchema.create(ResponseBody.class, method, i);
+				rp[i] = new RestParamDefaults.ResponseBodyObject(method, i, s, t, ps);
 
-			} else if (hasAnnotation(ResponseStatuses.class, method, i)) {
-				ResponseStatuses a = getAnnotation(ResponseStatuses.class, method, i);
-				HttpPartSchema[] ss = new HttpPartSchema[a.value().length];
-				for (int j = 0; j < ss.length; j++)
-					ss[j] = HttpPartSchema.create(a.value()[j]);
-				rp[i] = new RestParamDefaults.ResponseStatusObject(method, ss, t);
+			} else if (hasAnnotation(ResponseStatus.class, method, i)) {
+				rp[i] = new RestParamDefaults.ResponseStatusObject(method, t);
 
 			} else if (hasAnnotation(HasFormData.class, method, i)) {
 				s = HttpPartSchema.create(HasFormData.class, method, i);
@@ -4549,21 +4524,4 @@ public final class RestContext extends BeanContext {
 	public BeanSessionArgs createDefaultSessionArgs() {
 		throw new NoSuchMethodError();
 	}
-
-	ResponseMeta getResponseMetaForObject(Object o) {
-		if (o == null)
-			return null;
-		return getResponseMeta(o.getClass());
-	}
-
-	ResponseMeta getResponseMeta(Class<?> c) {
-		ResponseMeta rm = responseMetas.get(c);
-		if (rm == ResponseMeta.NULL)
-			return null;
-		if (rm != null)
-			return rm;
-		rm = ResponseMeta.create(c, getPropertyStore());
-		responseMetas.put(c, rm == null ? ResponseMeta.NULL : rm);
-		return rm;
-	}
 }
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestJavaMethod.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestJavaMethod.java
index 9e678af..4367c02 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestJavaMethod.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestJavaMethod.java
@@ -25,6 +25,7 @@ import java.beans.*;
 import java.lang.annotation.*;
 import java.lang.reflect.*;
 import java.util.*;
+import java.util.concurrent.*;
 
 import javax.servlet.http.*;
 
@@ -33,6 +34,7 @@ import org.apache.juneau.encoders.*;
 import org.apache.juneau.http.*;
 import org.apache.juneau.http.annotation.*;
 import org.apache.juneau.httppart.*;
+import org.apache.juneau.httppart.bean.*;
 import org.apache.juneau.internal.*;
 import org.apache.juneau.parser.*;
 import org.apache.juneau.rest.annotation.*;
@@ -49,8 +51,6 @@ public class RestJavaMethod implements Comparable<RestJavaMethod>  {
 	private final String httpMethod;
 	private final UrlPathPattern pathPattern;
 	final RestMethodParam[] methodParams;
-	final RestMethodReturn methodReturn;
-	final RestMethodThrown[] methodThrowns;
 	private final RestGuard[] guards;
 	private final RestMatcher[] optionalMatchers;
 	private final RestMatcher[] requiredMatchers;
@@ -76,6 +76,11 @@ public class RestJavaMethod implements Comparable<RestJavaMethod>  {
 		supportedAcceptTypes,
 		supportedContentTypes;
 
+	final Map<Class<?>,ResponseBeanMeta> responseBeanMetas = new ConcurrentHashMap<>();
+	final Map<Class<?>,ResponsePartMeta> headerPartMetas = new ConcurrentHashMap<>();
+	final Map<Class<?>,ResponsePartMeta> bodyPartMetas = new ConcurrentHashMap<>();
+	final ResponsePartMeta returnBodyMeta;
+
 	RestJavaMethod(Object servlet, java.lang.reflect.Method method, RestContext context) throws RestServletException {
 		Builder b = new Builder(servlet, method, context);
 		this.context = context;
@@ -83,8 +88,6 @@ public class RestJavaMethod implements Comparable<RestJavaMethod>  {
 		this.httpMethod = b.httpMethod;
 		this.pathPattern = b.pathPattern;
 		this.methodParams = b.methodParams;
-		this.methodReturn = b.methodReturn;
-		this.methodThrowns = b.methodThrowns;
 		this.guards = b.guards;
 		this.optionalMatchers = b.optionalMatchers;
 		this.requiredMatchers = b.requiredMatchers;
@@ -104,6 +107,7 @@ public class RestJavaMethod implements Comparable<RestJavaMethod>  {
 		this.priority = b.priority;
 		this.supportedAcceptTypes = b.supportedAcceptTypes;
 		this.supportedContentTypes = b.supportedContentTypes;
+		this.returnBodyMeta = b.returnBodyMeta;
 		this.widgets = unmodifiableMap(b.widgets);
 	}
 
@@ -111,8 +115,6 @@ public class RestJavaMethod implements Comparable<RestJavaMethod>  {
 		String httpMethod, defaultCharset;
 		UrlPathPattern pathPattern;
 		RestMethodParam[] methodParams;
-		RestMethodReturn methodReturn;
-		RestMethodThrown[] methodThrowns;
 		RestGuard[] guards;
 		RestMatcher[] optionalMatchers, requiredMatchers;
 		RestConverter[] converters;
@@ -128,6 +130,7 @@ public class RestJavaMethod implements Comparable<RestJavaMethod>  {
 		Integer priority;
 		Map<String,Widget> widgets;
 		List<MediaType> supportedAcceptTypes, supportedContentTypes;
+		ResponsePartMeta returnBodyMeta;
 
 		Builder(Object servlet, java.lang.reflect.Method method, RestContext context) throws RestServletException {
 			String sig = method.getDeclaringClass().getName() + '.' + method.getName();
@@ -200,8 +203,8 @@ public class RestJavaMethod implements Comparable<RestJavaMethod>  {
 								break;
 							}
 						}
-						if (p.equals(""))
-							p = "/";
+						if (! p.startsWith("/"))
+							p = "/" + p;
 					}
 				}
 
@@ -407,11 +410,10 @@ public class RestJavaMethod implements Comparable<RestJavaMethod>  {
 
 				methodParams = context.findParams(method, pathPattern, false);
 
-				methodReturn = new RestMethodReturn(method, partSerializer, ps);
-
-				methodThrowns = new RestMethodThrown[method.getExceptionTypes().length];
-				for (int i = 0; i < methodThrowns.length; i++)
-					methodThrowns[i] = new RestMethodThrown(method.getExceptionTypes()[i], partSerializer, ps);
+				if (ReflectionUtils.hasAnnotation(ResponseBody.class, method)) {
+					HttpPartSchema s = HttpPartSchema.create(ResponseBody.class, method);
+					returnBodyMeta = new ResponsePartMeta(HttpPartType.BODY, s, createPartSerializer(s.getSerializer(), serializers.getPropertyStore(), partSerializer));
+				}
 
 				// Need this to access methods in anonymous inner classes.
 				setAccessible(method, true);
@@ -423,6 +425,64 @@ public class RestJavaMethod implements Comparable<RestJavaMethod>  {
 		}
 	}
 
+	ResponseBeanMeta getResponseBeanMeta(Object o) {
+		if (o == null)
+			return null;
+		Class<?> c = o.getClass();
+		ResponseBeanMeta rbm = responseBeanMetas.get(c);
+		if (rbm == null) {
+			rbm = ResponseBeanMeta.create(c, serializers.getPropertyStore());
+			if (rbm == null)
+				rbm = ResponseBeanMeta.NULL;
+			responseBeanMetas.put(c, rbm);
+		}
+		if (rbm == ResponseBeanMeta.NULL)
+			return null;
+		return rbm;
+	}
+
+	ResponsePartMeta getResponseHeaderMeta(Object o) {
+		if (o == null)
+			return null;
+		Class<?> c = o.getClass();
+		ResponsePartMeta pm = headerPartMetas.get(c);
+		if (pm == null) {
+			ResponseHeader a = c.getAnnotation(ResponseHeader.class);
+			if (a != null) {
+				HttpPartSchema schema = HttpPartSchema.create(a);
+				HttpPartSerializer serializer = createPartSerializer(schema.getSerializer(), serializers.getPropertyStore(), partSerializer);
+				pm = new ResponsePartMeta(HttpPartType.HEADER, schema, serializer);
+			}
+			if (pm == null)
+				pm = ResponsePartMeta.NULL;
+			headerPartMetas.put(c, pm);
+		}
+		if (pm == ResponsePartMeta.NULL)
+			return null;
+		return pm;
+	}
+
+	ResponsePartMeta getResponseBodyMeta(Object o) {
+		if (o == null)
+			return null;
+		Class<?> c = o.getClass();
+		ResponsePartMeta pm = bodyPartMetas.get(c);
+		if (pm == null) {
+			ResponseBody a = c.getAnnotation(ResponseBody.class);
+			if (a != null) {
+				HttpPartSchema schema = HttpPartSchema.create(a);
+				HttpPartSerializer serializer = schema.isUsePartSerializer() ? createPartSerializer(schema.getSerializer(), serializers.getPropertyStore(), partSerializer) : null;
+				pm = new ResponsePartMeta(HttpPartType.BODY, schema, serializer);
+			}
+			if (pm == null)
+				pm = ResponsePartMeta.NULL;
+			bodyPartMetas.put(c, pm);
+		}
+		if (pm == ResponsePartMeta.NULL)
+			return null;
+		return pm;
+	}
+
 	/**
 	 * Returns <jk>true</jk> if this Java method has any guards or matchers.
 	 */
@@ -524,27 +584,14 @@ public class RestJavaMethod implements Comparable<RestJavaMethod>  {
 				output = method.invoke(context.getResource(), args);
 				if (res.getStatus() == 0)
 					res.setStatus(200);
-				RestMethodReturn rmr = req.getRestMethodReturn();
 				if (! method.getReturnType().equals(Void.TYPE)) {
-					if (output != null || ! res.getOutputStreamCalled()) {
+					if (output != null || ! res.getOutputStreamCalled())
 						res.setOutput(output);
-						ResponseMeta rm = rmr.getResponseMeta();
-						if (rm == null)
-							rm = context.getResponseMetaForObject(output);
-						if (rm != null)
-							res.setMeta(rm);
-					}
 				}
 			} catch (InvocationTargetException e) {
 				Throwable e2 = e.getTargetException();		// Get the throwable thrown from the doX() method.
-				if (res.getStatus() == 0)
-					res.setStatus(500);
-				RestMethodThrown rmt = req.getRestMethodThrown(e2);
-				ResponseMeta rm = rmt == null ? null : rmt.getResponseMeta();
-				if (rm == null)
-					rm = context.getResponseMetaForObject(e2);
-				if (rm != null) {
-					res.setMeta(rm);
+				res.setStatus(500);
+				if (getResponseBodyMeta(e2) != null || getResponseBeanMeta(e2) != null) {
 					res.setOutput(e2);
 				} else {
 					throw e;
@@ -659,6 +706,9 @@ public class RestJavaMethod implements Comparable<RestJavaMethod>  {
 		return method.hashCode();
 	}
 
+	//-----------------------------------------------------------------------------------------------------------------
+	// Utility methods.
+	//-----------------------------------------------------------------------------------------------------------------
 	static String[] resolveVars(VarResolver vr, String[] in) {
 		String[] out = new String[in.length];
 		for (int i = 0; i < in.length; i++)
@@ -666,11 +716,8 @@ public class RestJavaMethod implements Comparable<RestJavaMethod>  {
 		return out;
 	}
 
-	RestMethodReturn getRestMethodReturn() {
-		return this.methodReturn;
-	}
-
-	List<RestMethodThrown> getRestMethodThrown() {
-		return Collections.unmodifiableList(Arrays.asList(this.methodThrowns));
+	static HttpPartSerializer createPartSerializer(Class<? extends HttpPartSerializer> c, PropertyStore ps, HttpPartSerializer _default) {
+		HttpPartSerializer hps = ClassUtils.newInstance(HttpPartSerializer.class, c, true, ps);
+		return hps == null ? _default : hps;
 	}
 }
\ No newline at end of file
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestMethodReturn.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestMethodReturn.java
deleted file mode 100644
index 29d1876..0000000
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestMethodReturn.java
+++ /dev/null
@@ -1,82 +0,0 @@
-// ***************************************************************************************************************************
-// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
-// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
-// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
-// * with the License.  You may obtain a copy of the License at                                                              *
-// *                                                                                                                         *
-// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
-// *                                                                                                                         *
-// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
-// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
-// * specific language governing permissions and limitations under the License.                                              *
-// ***************************************************************************************************************************
-package org.apache.juneau.rest;
-
-import static org.apache.juneau.internal.ReflectionUtils.*;
-
-import java.lang.reflect.*;
-
-import org.apache.juneau.*;
-import org.apache.juneau.http.annotation.*;
-import org.apache.juneau.httppart.*;
-
-/**
- * Contains metadata about the return type on a REST Java method.
- */
-public class RestMethodReturn {
-
-	private final Type type;
-	private final int code;
-	private final ObjectMap api;
-	private final ResponseMeta responseMeta;
-
-	RestMethodReturn(Method m, HttpPartSerializer partSerializer, PropertyStore ps) {
-		this.responseMeta = ResponseMeta.create(m, ps);
-
-		HttpPartSchema s = HttpPartSchema.DEFAULT;
-		if (hasAnnotation(Response.class, m))
-			s = HttpPartSchema.create(Response.class, m);
-
-		this.type = m.getGenericReturnType();
-		this.api = HttpPartSchema.getApiCodeMap(s, 200).unmodifiable();
-		this.code = s.getCode(200);
-	}
-
-	/**
-	 * Returns the return type of the Java method.
-	 *
-	 * @return The return type of the Java method.
-	 */
-	public Type getType() {
-		return type;
-	}
-
-	/**
-	 * Returns the HTTP code code of the response.
-	 *
-	 * @return The HTTP code code of the response.
-	 */
-	public int getCode() {
-		return code;
-	}
-
-	/**
-	 * Returns the Swagger metadata associated with this return.
-	 *
-	 * @return A map of return metadata, never <jk>null</jk>.
-	 */
-	public ObjectMap getApi() {
-		return api;
-	}
-
-	/**
-	 * Returns metadata about the response object.
-	 *
-	 * @return
-	 * 	Metadata about the response object.
-	 * 	<br>Can be <jk>null</jk> if no {@link Response} annotation is associated with the return.
-	 */
-	public ResponseMeta getResponseMeta() {
-		return responseMeta;
-	}
-}
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestMethodThrown.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestMethodThrown.java
deleted file mode 100644
index ada4e7f..0000000
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestMethodThrown.java
+++ /dev/null
@@ -1,80 +0,0 @@
-// ***************************************************************************************************************************
-// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
-// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
-// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
-// * with the License.  You may obtain a copy of the License at                                                              *
-// *                                                                                                                         *
-// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
-// *                                                                                                                         *
-// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
-// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
-// * specific language governing permissions and limitations under the License.                                              *
-// ***************************************************************************************************************************
-package org.apache.juneau.rest;
-
-import static org.apache.juneau.internal.ReflectionUtils.*;
-
-import org.apache.juneau.*;
-import org.apache.juneau.http.annotation.*;
-import org.apache.juneau.httppart.*;
-
-/**
- * Contains metadata about a throwable on a REST Java method.
- */
-public class RestMethodThrown {
-
-	final Class<?> type;
-	final int code;
-	final ObjectMap api;
-	private final ResponseMeta responseMeta;
-
-	RestMethodThrown(Class<?> type, HttpPartSerializer partSerializer, PropertyStore ps) {
-		this.responseMeta = ResponseMeta.create(type, ps);
-
-		HttpPartSchema s = HttpPartSchema.DEFAULT;
-		if (hasAnnotation(Response.class, type))
-			s = HttpPartSchema.create(Response.class, type);
-
-		this.type = type;
-		this.api = HttpPartSchema.getApiCodeMap(s, 500).unmodifiable();
-		this.code = s.getCode(500);
-	}
-
-	/**
-	 * Returns the return type of the Java method.
-	 *
-	 * @return The return type of the Java method.
-	 */
-	public Class<?> getType() {
-		return type;
-	}
-
-	/**
-	 * Returns the HTTP status code of the response.
-	 *
-	 * @return The HTTP status code of the response.
-	 */
-	public int getCode() {
-		return code;
-	}
-
-	/**
-	 * Returns the Swagger metadata associated with this return.
-	 *
-	 * @return A map of return metadata, never <jk>null</jk>.
-	 */
-	public ObjectMap getApi() {
-		return api;
-	}
-
-	/**
-	 * Returns metadata about the thrown object.
-	 *
-	 * @return
-	 * 	Metadata about the thrown object.
-	 * 	<br>Can be <jk>null</jk> if no {@link Response} annotation is associated with the thrown object.
-	 */
-	public ResponseMeta getResponseMeta() {
-		return responseMeta;
-	}
-}
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestParamDefaults.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestParamDefaults.java
index 445097a..7466e6e 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestParamDefaults.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestParamDefaults.java
@@ -29,9 +29,10 @@ import org.apache.juneau.config.*;
 import org.apache.juneau.dto.swagger.*;
 import org.apache.juneau.http.*;
 import org.apache.juneau.http.Date;
+import org.apache.juneau.http.annotation.*;
 import org.apache.juneau.httppart.*;
+import org.apache.juneau.httppart.bean.*;
 import org.apache.juneau.internal.*;
-import org.apache.juneau.json.*;
 import org.apache.juneau.parser.*;
 import org.apache.juneau.rest.annotation.*;
 import org.apache.juneau.rest.exception.*;
@@ -551,18 +552,18 @@ class RestParamDefaults {
 		private final HttpPartParser partParser;
 		private final HttpPartSchema schema;
 
-		protected PathObject(Method m, HttpPartSchema s, Type t, PropertyStore ps) {
+		protected PathObject(Method m, int i, HttpPartSchema s, Type t, PropertyStore ps) {
 			super(PATH, m, s.getName(), t, s.getApi());
-			this.partParser = ClassUtils.newInstance(HttpPartParser.class, s.getParser(), true, ps);
-			this.schema = s;
+			this.schema = HttpPartSchema.create(Path.class, m, i);
+			this.partParser = createPartParser(schema.getParser(), ps);
 
-			if (isEmpty(name))
+			if (isEmpty(schema.getName()))
 				throw new InternalServerError("@Path used without name or value on method ''{0}''.", method);
 		}
 
 		@Override /* RestMethodParam */
 		public Object resolve(RestRequest req, RestResponse res) throws Exception {
-			return req.getPathMatch().get(partParser, schema, name, type);
+			return req.getPathMatch().get(partParser, schema, schema.getName(), type);
 		}
 	}
 
@@ -572,7 +573,7 @@ class RestParamDefaults {
 
 		protected BodyObject(Method m, HttpPartSchema s, Type t, PropertyStore ps) {
 			super(BODY, m, null, t, s.getApi());
-			this.partParser = s.isUsePartParser() ? ClassUtils.newInstance(HttpPartParser.class, s.getParser(), true, ps) : null;
+			this.partParser = s.isUsePartParser() ? createPartParser(s.getParser(), ps) : null;
 			this.schema = s;
 		}
 
@@ -588,7 +589,7 @@ class RestParamDefaults {
 
 		protected HeaderObject(Method m, HttpPartSchema s, Type t, PropertyStore ps) {
 			super(HEADER, m, s.getName(), t, s.getApi());
-			this.partParser = ClassUtils.newInstance(HttpPartParser.class, s.getParser(), true, ps);
+			this.partParser = createPartParser(s.getParser(), ps);
 			this.schema = s;
 
 			if (isEmpty(name))
@@ -605,7 +606,7 @@ class RestParamDefaults {
 		private final RequestBeanMeta requestBeanMeta;
 
 		protected RequestBeanObject(Method m, RequestBeanMeta rbm, Type t) {
-			super(OTHER, m, null, t, null);
+			super(RESPONSE_BODY, m, null, t, null);
 			this.requestBeanMeta = rbm;
 		}
 
@@ -616,22 +617,16 @@ class RestParamDefaults {
 	}
 
 	static final class ResponseHeaderObject extends RestMethodParam {
-		final HttpPartSerializer partSerializer;
-		final HttpPartSchema schema;
-		final String _default;
+		final ResponsePartMeta rpm;
 
-		protected ResponseHeaderObject(Method m, HttpPartSchema s, Type t, PropertyStore ps) {
+		protected ResponseHeaderObject(Method m, int i, HttpPartSchema s, Type t, PropertyStore ps) {
 			super(RESPONSE_HEADER, m, s.getName(), t, HttpPartSchema.getApiCodeMap(s, 200));
-			this.partSerializer = ClassUtils.newInstance(HttpPartSerializer.class, s.getSerializer(), true, ps);
-			this.schema = s;
-			this._default = s.getDefault();
+			this.rpm = new ResponsePartMeta(HttpPartType.HEADER, s, createPartSerializer(s.getSerializer(), ps));
 
-			if (isEmpty(name))
+			if (isEmpty(rpm.getSchema().getName()))
 				throw new InternalServerError("@ResponseHeader used without name or value on method ''{0}''.", method);
-			if (getTypeClass() == null)
-				throw new InternalServerError("Invalid type {0} specified with @ResponseHeader annotation.  It must be a subclass of Value.", type);
-			if (ClassUtils.findNoArgConstructor(getTypeClass(), Visibility.PUBLIC) == null)
-				throw new InternalServerError("Invalid type {0} specified with @ResponseHeader annotation.  It must have a public no-arg constructor.", type);
+			if (getTypeClass() != Value.class)
+				throw new InternalServerError("Invalid type {0} specified with @ResponseHeader annotation.  It must be Value.", type);
 		}
 
 		@SuppressWarnings({ "unchecked", "rawtypes" })
@@ -642,78 +637,82 @@ class RestParamDefaults {
 				@Override
 				public void onSet(Object o) {
 					try {
-						res.setHeader(new HttpPart(name, HttpPartType.HEADER, schema, partSerializer, req.getSerializerSessionArgs(), o));
+						ResponsePartMeta rpm = req.getResponseHeaderMeta(o);
+						if (rpm == null)
+							rpm = ResponseHeaderObject.this.rpm;
+						res.setHeader(new HttpPart(name, HttpPartType.HEADER, rpm.getSchema(), firstNonNull(rpm.getSerializer(), req.getPartSerializer()), req.getSerializerSessionArgs(), o));
 					} catch (SerializeException | SchemaValidationException e) {
 						throw new RuntimeException(e);
 					}
 				}
 			});
-			if (_default != null) {
-				Class<?> pc = ClassUtils.resolveParameterType(Value.class, 0, c);
-				v.set(JsonParser.DEFAULT.parse(_default, req.getBeanSession().getClassMeta(pc)));
-			}
 			return v;
 		}
-
-		public HttpPartSerializer getPartSerializer() {
-			return partSerializer;
-		}
 	}
 
-	static final class ResponseParamObject extends RestMethodParam {
-		private String _default;
-		final ResponseMeta meta;
+	static final class ResponseBodyObject extends RestMethodParam {
+		final ResponsePartMeta rpm;
 
-		protected ResponseParamObject(Method m, int i, HttpPartSchema s, Type t, PropertyStore ps) {
-			super(RESPONSE, m, s.getName(), t, HttpPartSchema.getApiCodeMap(s, 200));
-			this.meta = ResponseMeta.create(m, i, ps);
-			this._default = s.getDefault();
+		protected ResponseBodyObject(Method m, int i, HttpPartSchema s, Type t, PropertyStore ps) {
+			super(RESPONSE_BODY, m, s.getName(), t, HttpPartSchema.getApiCodeMap(s, 200));
+			this.rpm = new ResponsePartMeta(HttpPartType.BODY, s, createPartSerializer(s.getSerializer(), ps));
 
-			if (getTypeClass() == null)
-				throw new InternalServerError("Invalid type {0} specified with @Response annotation.  It must be a subclass of Value.", type);
-			if (ClassUtils.findNoArgConstructor(getTypeClass(), Visibility.PUBLIC) == null)
-				throw new InternalServerError("Invalid type {0} specified with @Response annotation.  It must have a public no-arg constructor.", type);
+			if (getTypeClass() != Value.class)
+				throw new InternalServerError("Invalid type {0} specified with @ResponseHeader annotation.  It must be Value.", type);
 		}
 
 		@SuppressWarnings({ "unchecked", "rawtypes" })
 		@Override /* RestMethodParam */
 		public Object resolve(final RestRequest req, final RestResponse res) throws Exception {
-			Value<Object> v = (Value<Object>)c.newInstance();
+			Value<Object> v = (Value<Object>)getTypeClass().newInstance();
 			v.listener(new ValueListener() {
 				@Override
-				public void onSet(Object output) {
-					res.setMeta(meta);
-					res.setOutput(output);
+				public void onSet(Object o) {
+					ResponsePartMeta rpm = req.getResponseBodyMeta(o);
+					if (rpm == null)
+						rpm = ResponseBodyObject.this.rpm;
+					res.setResponseBodyMeta(rpm);
+					res.setOutput(o);
 				}
 			});
-			if (_default != null) {
-				Class<?> pc = ClassUtils.resolveParameterType(Value.class, 0, c);
-				v.set(JsonParser.DEFAULT.parse(_default, req.getBeanSession().getClassMeta(pc)));
-			}
 			return v;
 		}
 	}
 
-	static class ResponseStatusObject extends RestMethodParam {
-
-		private String _default;
+	static final class ResponseBeanObject extends RestMethodParam {
+		final ResponseBeanMeta rbm;
 
-		protected ResponseStatusObject(Method m, HttpPartSchema s, Type t) {
-			this(m, t, HttpPartSchema.getApiCodeMap(s, 200));
-			this._default = s.getDefault();
+		protected ResponseBeanObject(Method m, int i, HttpPartSchema s, Type t, PropertyStore ps) {
+			super(RESPONSE_BODY, m, s.getName(), t, HttpPartSchema.getApiCodeMap(s, 200));
+			this.rbm = ResponseBeanMeta.create(m.getParameterTypes()[i], ps);
+			if (getTypeClass() != Value.class)
+				throw new InternalServerError("Invalid type {0} specified with @Response annotation.  It must be Value.", type);
 		}
 
-		protected ResponseStatusObject(Method m, HttpPartSchema[] ss, Type t) {
-			this(m, t, HttpPartSchema.getApiCodeMap(ss, 200));
+		@SuppressWarnings({ "unchecked", "rawtypes" })
+		@Override /* RestMethodParam */
+		public Object resolve(final RestRequest req, final RestResponse res) throws Exception {
+			Value<Object> v = (Value<Object>)c.newInstance();
+			v.listener(new ValueListener() {
+				@Override
+				public void onSet(Object o) {
+					ResponseBeanMeta rbm = req.getResponseBeanMeta(o);
+					if (rbm == null)
+						rbm = ResponseBeanObject.this.rbm;
+					res.setResponseBeanMeta(rbm);
+					res.setOutput(o);
+				}
+			});
+			return v;
 		}
+	}
 
-		protected ResponseStatusObject(Method m, Type t, ObjectMap api) {
-			super(RESPONSE_STATUS, m, null, t, api);
+	static class ResponseStatusObject extends RestMethodParam {
 
-			if (getTypeClass() == null)
-				throw new InternalServerError("Invalid type {0} specified with @ResponseStatus annotation.  It must be a subclass of Value.", type);
-			if (ClassUtils.findNoArgConstructor(getTypeClass(), Visibility.PUBLIC) == null)
-				throw new InternalServerError("Invalid type {0} specified with @ResponseStatus annotation.  It must have a public no-arg constructor.", type);
+		protected ResponseStatusObject(Method m, Type t) {
+			super(RESPONSE_STATUS, t);
+			if (getTypeClass() != Value.class || Value.getValueType(t) != Integer.class)
+				throw new InternalServerError("Invalid type {0} specified with @ResponseStatus annotation.  It must Value<Integer>.", type);
 		}
 
 		@SuppressWarnings({ "unchecked", "rawtypes" })
@@ -722,14 +721,10 @@ class RestParamDefaults {
 			Value<Object> v = (Value<Object>)c.newInstance();
 			v.listener(new ValueListener() {
 				@Override
-				public void onSet(Object newValue) {
-					res.setStatus(Integer.parseInt(newValue.toString()));
+				public void onSet(Object o) {
+					res.setStatus(Integer.parseInt(o.toString()));
 				}
 			});
-			if (_default != null) {
-				Class<?> pc = ClassUtils.resolveParameterType(Value.class, 0, c);
-				v.set(JsonParser.DEFAULT.parse(_default, req.getBeanSession().getClassMeta(pc)));
-			}
 			return v;
 		}
 	}
@@ -755,7 +750,7 @@ class RestParamDefaults {
 
 		protected FormDataObject(Method m, HttpPartSchema s, Type t, PropertyStore ps) {
 			super(FORM_DATA, m, s.getName(), t, s.getApi());
-			this.partParser = ClassUtils.newInstance(HttpPartParser.class, s.getParser(), true, ps);
+			this.partParser = createPartParser(s.getParser(), ps);
 			this.schema = s;
 			this.multiPart = s.getCollectionFormat() == HttpPartSchema.CollectionFormat.MULTI;
 
@@ -780,7 +775,7 @@ class RestParamDefaults {
 
 		protected QueryObject(Method m, HttpPartSchema s, Type t, PropertyStore ps) {
 			super(QUERY, m, s.getName(), t, s.getApi());
-			this.partParser = ClassUtils.newInstance(HttpPartParser.class, s.getParser(), true, ps);
+			this.partParser = createPartParser(s.getParser(), ps);
 			this.schema = s;
 			this.multiPart = s.getCollectionFormat() == HttpPartSchema.CollectionFormat.MULTI;
 
@@ -1139,4 +1134,12 @@ class RestParamDefaults {
 	static final boolean isCollection(Type t) {
 		return BeanContext.DEFAULT.getClassMeta(t).isCollectionOrArray();
 	}
+
+	static final HttpPartParser createPartParser(Class<? extends HttpPartParser> p, PropertyStore ps) {
+		return ClassUtils.newInstance(HttpPartParser.class, p, true, ps);
+	}
+
+	static final HttpPartSerializer createPartSerializer(Class<? extends HttpPartSerializer> s, PropertyStore ps) {
+		return ClassUtils.newInstance(HttpPartSerializer.class, s, true, ps);
+	}
 }
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestParamType.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestParamType.java
index 0ceafb7..403e598 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestParamType.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestParamType.java
@@ -37,8 +37,12 @@ public enum RestParamType {
 	/** Request body */
 	BODY("body"),
 
+	//-----------------------------------------------------------------------------------------------------------------
+	// The following are additional parameter types not defined in Swagger
+	//-----------------------------------------------------------------------------------------------------------------
+
 	/** Response value */
-	RESPONSE("response"),
+	RESPONSE_BODY("responseBody"),
 
 	/** Response header value */
 	RESPONSE_HEADER("responseHeader"),
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestRequest.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestRequest.java
index 9992ee7..8e97171 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestRequest.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestRequest.java
@@ -39,6 +39,7 @@ import org.apache.juneau.dto.swagger.*;
 import org.apache.juneau.http.*;
 import org.apache.juneau.http.annotation.*;
 import org.apache.juneau.httppart.*;
+import org.apache.juneau.httppart.bean.*;
 import org.apache.juneau.internal.*;
 import org.apache.juneau.parser.*;
 import org.apache.juneau.remoteable.*;
@@ -1598,6 +1599,36 @@ public final class RestRequest extends HttpServletRequestWrapper {
 		}
 	}
 
+	/**
+	 * Returns metadata about the specified response object if it's annotated with {@link Response @Response}.
+	 *
+ 	 * @param o The response POJO.
+	 * @return Metadata about the specified response object, or <jk>null</jk> if it's not annotated with {@link Response @Response}. 
+	 */
+	public ResponseBeanMeta getResponseBeanMeta(Object o) {
+		return restJavaMethod.getResponseBeanMeta(o);
+	}
+
+	/**
+	 * Returns metadata about the specified response object if it's annotated with {@link ResponseHeader @ResponseHeader}.
+	 *
+ 	 * @param o The response POJO.
+	 * @return Metadata about the specified response object, or <jk>null</jk> if it's not annotated with {@link ResponseHeader @ResponseHeader}. 
+	 */
+	public ResponsePartMeta getResponseHeaderMeta(Object o) {
+		return restJavaMethod.getResponseHeaderMeta(o);
+	}
+
+	/**
+	 * Returns metadata about the specified response object if it's annotated with {@link ResponseBody @ResponseBody}.
+	 *
+ 	 * @param o The response POJO.
+	 * @return Metadata about the specified response object, or <jk>null</jk> if it's not annotated with {@link ResponseBody @ResponseBody}. 
+	 */
+	public ResponsePartMeta getResponseBodyMeta(Object o) {
+		return restJavaMethod.getResponseBodyMeta(o);
+	}
+
 	//--------------------------------------------------------------------------------
 	// Utility methods
 	//--------------------------------------------------------------------------------
@@ -1619,27 +1650,4 @@ public final class RestRequest extends HttpServletRequestWrapper {
 	void setJavaMethod(Method method) {
 		this.javaMethod = method;
 	}
-
-	/**
-	 * Returns metadata about the method return type.
-	 *
-	 * @return Metadata about the method return type.
-	 */
-	public RestMethodReturn getRestMethodReturn() {
-		return restJavaMethod.getRestMethodReturn();
-	}
-
-	/**
-	 * Returns metadata about the specified exception.
-	 *
-	 * @param e
-	 * @return Metadata about the specified exception.
-	 */
-	public RestMethodThrown getRestMethodThrown(Throwable e) {
-		if (restJavaMethod != null)
-			for (RestMethodThrown rmt : restJavaMethod.getRestMethodThrown())
-				if (rmt.getType().isAssignableFrom(e.getClass()))
-					return rmt;
-		return null;
-	}
 }
\ No newline at end of file
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestResponse.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestResponse.java
index 2842eb7..b38221d 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestResponse.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestResponse.java
@@ -25,6 +25,7 @@ import org.apache.juneau.*;
 import org.apache.juneau.encoders.*;
 import org.apache.juneau.http.*;
 import org.apache.juneau.httppart.*;
+import org.apache.juneau.httppart.bean.*;
 import org.apache.juneau.rest.annotation.*;
 import org.apache.juneau.rest.exception.*;
 import org.apache.juneau.rest.util.*;
@@ -58,7 +59,6 @@ public final class RestResponse extends HttpServletResponseWrapper {
 
 	private final RestRequest request;
 	private RestJavaMethod restJavaMethod;
-	private ResponseMeta meta;
 	private Object output;                       // The POJO being sent to the output.
 	private boolean isNullOutput;                // The output is null (as opposed to not being set at all)
 	private RequestProperties properties;                // Response properties
@@ -67,6 +67,9 @@ public final class RestResponse extends HttpServletResponseWrapper {
 	private FinishablePrintWriter w;
 	private HtmlDocBuilder htmlDocBuilder;
 
+	private ResponseBeanMeta resBeanMeta;
+	private ResponsePartMeta resBodyMeta;
+
 	/**
 	 * Constructor.
 	 */
@@ -117,6 +120,8 @@ public final class RestResponse extends HttpServletResponseWrapper {
 		if (charset == null)
 			throw new NotAcceptable("No supported charsets in header ''Accept-Charset'': ''{0}''", request.getHeader("Accept-Charset"));
 		super.setCharacterEncoding(charset);
+
+		this.resBodyMeta = rjm.returnBodyMeta;
 	}
 
 	/**
@@ -518,18 +523,40 @@ public final class RestResponse extends HttpServletResponseWrapper {
 	 * 	The metadata about this response.
 	 * 	<jk>Never <jk>null</jk>.
 	 */
-	public ResponseMeta getMeta() {
-		return meta;
+	public ResponseBeanMeta getResponseBeanMeta() {
+		return resBeanMeta;
 	}
 
 	/**
 	 * Sets metadata about this response.
 	 *
-	 * @param meta The metadata about this response.
+	 * @param rbm The metadata about this response.
+	 * @return This object (for method chaining).
+	 */
+	public RestResponse setResponseBeanMeta(ResponseBeanMeta rbm) {
+		this.resBeanMeta = rbm;
+		return this;
+	}
+
+	/**
+	 * Returns the metadata about this response body.
+	 *
+	 * @return
+	 * 	The metadata about this response.
+	 * 	<jk>Never <jk>null</jk>.
+	 */
+	public ResponsePartMeta getResponseBodyMeta() {
+		return resBodyMeta;
+	}
+
+	/**
+	 * Sets metadata about this response body.
+	 *
+	 * @param rpm The metadata about this response body.
 	 * @return This object (for method chaining).
 	 */
-	public RestResponse setMeta(ResponseMeta meta) {
-		this.meta = meta;
+	public RestResponse setResponseBodyMeta(ResponsePartMeta rpm) {
+		this.resBodyMeta = rpm;
 		return this;
 	}
 
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/reshandlers/DefaultHandler.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/reshandlers/DefaultHandler.java
index fc337ee..c9004a6 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/reshandlers/DefaultHandler.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/reshandlers/DefaultHandler.java
@@ -12,13 +12,17 @@
 // ***************************************************************************************************************************
 package org.apache.juneau.rest.reshandlers;
 
+import static org.apache.juneau.internal.ObjectUtils.*;
+
 import java.io.*;
+import java.lang.reflect.*;
 import java.net.*;
 import java.util.*;
 
 import org.apache.juneau.*;
 import org.apache.juneau.http.*;
 import org.apache.juneau.httppart.*;
+import org.apache.juneau.httppart.bean.*;
 import org.apache.juneau.internal.*;
 import org.apache.juneau.rest.*;
 import org.apache.juneau.rest.exception.*;
@@ -53,29 +57,56 @@ public class DefaultHandler implements ResponseHandler {
 		SerializerMatch sm = g.getSerializerMatch(accept);
 
 		Object o = res.getOutput();
-		ResponseMeta rm = res.getMeta();
 
-		if (rm != null) {
-			if (rm.getCode() != 0)
-				res.setStatus(rm.getCode());
+		ResponseBeanMeta rbm = res.getResponseBeanMeta();
+		if (rbm == null)
+			rbm = req.getResponseBeanMeta(o);
+
+		if (rbm != null) {
+
+			Method stm = rbm.getStatusMethod();
+			if (stm != null) {
+				try {
+					res.setStatus((int)stm.invoke(o));
+				} catch (Exception e) {
+					throw new InternalServerError(e, "Could not get status.");
+				}
+			} else if (rbm.getCode() != 0) {
+				res.setStatus(rbm.getCode());
+			}
 
-			for (ResponsePropertyMeta hm : rm.getHeaderMetas()) {
+			for (ResponseBeanPropertyMeta hm : rbm.getHeaderMethods()) {
 				try {
 					Object ho = hm.getGetter().invoke(o);
 					if (ho instanceof URI)
 						ho = req.getUriResolver().resolve(ho);
-					res.setHeader(new HttpPart(hm.getPartName(), HttpPartType.HEADER, hm.getSchema(), hm.getSerializer(req.getPartSerializer()), req.getSerializerSessionArgs(), ho));
+					res.setHeader(new HttpPart(hm.getPartName(), HttpPartType.HEADER, hm.getSchema(), firstNonNull(hm.getSerializer(), req.getPartSerializer()), req.getSerializerSessionArgs(), ho));
 				} catch (Exception e) {
 					throw new InternalServerError(e, "Could not set header ''{0}''", hm.getPartName());
 				}
 			}
 
-			if (rm.isUsePartSerializer()) {
-				res.setContentType("text/plain");
-				HttpPartSerializer ps = rm.getPartSerializer(req.getPartSerializer());
+			ResponseBeanPropertyMeta m = rbm.getBodyMethod();
+			boolean usePartSerializer = rbm.isUsePartSerializer();
+			HttpPartSchema schema = rbm.getSchema();
+
+			if (m != null) {
+				try {
+					o = m.getGetter().invoke(o);
+					schema = m.getSchema();
+					usePartSerializer |= schema.isUsePartSerializer();
+				} catch (Exception e) {
+					throw new InternalServerError(e, "Could not get body.");
+				}
+			}
+
+			if (usePartSerializer) {
+				if (res.getContentType() == null)
+					res.setContentType("text/plain");
+				HttpPartSerializer ps = firstNonNull(rbm.getPartSerializer(), req.getPartSerializer());
 				if (ps != null) {
 					try (FinishablePrintWriter w = res.getNegotiatedWriter()) {
-						w.append(ps.serialize(HttpPartType.BODY, rm.getSchema(), o));
+						w.append(ps.serialize(HttpPartType.BODY, schema, o));
 						w.flush();
 						w.finish();
 					} catch (SchemaValidationException | SerializeException e) {
@@ -86,6 +117,29 @@ public class DefaultHandler implements ResponseHandler {
 			}
 		}
 
+		ResponsePartMeta rpm = res.getResponseBodyMeta();
+		if (rpm == null)
+			rpm = req.getResponseBodyMeta(o);
+
+		if (rpm != null && rpm.getSchema().isUsePartSerializer()) {
+			if (res.getContentType() == null)
+				res.setContentType("text/plain");
+			HttpPartSerializer ps = rpm.getSerializer();
+			if (ps == null)
+				ps = req.getPartSerializer();
+			if (ps != null) {
+				try (FinishablePrintWriter w = res.getNegotiatedWriter()) {
+					w.append(ps.serialize(HttpPartType.BODY, rpm.getSchema(), o));
+					w.flush();
+					w.finish();
+				} catch (SchemaValidationException | SerializeException e) {
+					throw new InternalServerError(e);
+				}
+				return true;
+			}
+		}
+
+
 		if (sm != null) {
 			Serializer s = sm.getSerializer();
 			MediaType mediaType = res.getMediaType();
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/response/Found.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/response/Found.java
index e39ca1e..e9aa7f6 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/response/Found.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/response/Found.java
@@ -58,7 +58,7 @@ public class Found {
 	/**
 	 * @return <code>Location</code> header value.
 	 */
-	@Header(name="Location", description="")
+	@ResponseHeader(name="Location")
 	public URI getLocation() {
 		return location;
 	}
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/response/MovedPermanently.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/response/MovedPermanently.java
index 06d4e50..441e5f1 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/response/MovedPermanently.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/response/MovedPermanently.java
@@ -63,7 +63,7 @@ public class MovedPermanently {
 	/**
 	 * @return <code>Location</code> header value.
 	 */
-	@Header(name="Location")
+	@ResponseHeader(name="Location")
 	public URI getLocation() {
 		return location;
 	}
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/response/PermanentRedirect.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/response/PermanentRedirect.java
index a4fb513..7f4d883 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/response/PermanentRedirect.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/response/PermanentRedirect.java
@@ -64,7 +64,7 @@ public class PermanentRedirect {
 	/**
 	 * @return <code>Location</code> header value.
 	 */
-	@Header(name="Location")
+	@ResponseHeader(name="Location")
 	public URI getLocation() {
 		return location;
 	}
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/response/SeeOther.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/response/SeeOther.java
index 8b7848b..4d9d903 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/response/SeeOther.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/response/SeeOther.java
@@ -64,7 +64,7 @@ public class SeeOther {
 	/**
 	 * @return <code>Location</code> header value.
 	 */
-	@Header(name="Location")
+	@ResponseHeader(name="Location")
 	public URI getLocation() {
 		return location;
 	}
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/response/TemporaryRedirect.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/response/TemporaryRedirect.java
index a46121c..00037ba 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/response/TemporaryRedirect.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/response/TemporaryRedirect.java
@@ -66,7 +66,7 @@ public class TemporaryRedirect {
 	/**
 	 * @return <code>Location</code> header value.
 	 */
-	@Header(name="Location")
+	@ResponseHeader(name="Location")
 	public URI getLocation() {
 		return location;
 	}
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 246fc0d..e5121a4 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
@@ -1783,25 +1783,33 @@ public class BasicRestInfoProviderTest {
 	//=================================================================================================================
 
 	@RestResource
-	public static class OA01 {
+	public static class OA01a {
 		@RestMethod(name=GET,path="/path/{foo}/responses/100")
-		public Foo doFoo(@Response(100) Value<Foo> foo) {
-			return null;
-		}
+		public void doFoo(Value<OA01x> foo) {}
+	}
+	@RestResource
+	public static class OA01b {
+		@RestMethod(name=GET,path="/path/{foo}/responses/100")
+		public OA01x doFoo() { return null;}
 	}
+	@Response(code=100)
+	public static class OA01x {}
 
 	@Test
-	public void oa01_responses_100_description_default() throws Exception {
-		assertEquals("Continue", getSwagger(new OA01()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getDescription());
-		assertEquals("s-100-description", getSwaggerWithFile(new OA01()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getDescription());
+	public void oa01a_responses_100_description_default() throws Exception {
+		assertEquals("Continue", getSwagger(new OA01a()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getDescription());
+		assertEquals("s-100-description", getSwaggerWithFile(new OA01a()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getDescription());
+	}
+	@Test
+	public void oa01b_responses_100_description_default() throws Exception {
+		assertEquals("Continue", getSwagger(new OA01b()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getDescription());
+		assertEquals("s-100-description", getSwaggerWithFile(new OA01b()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getDescription());
 	}
 
 	@RestResource(swagger=@ResourceSwagger("paths:{'/path/{foo}/responses/100':{get:{responses:{100:{description:'a-100-description'}}}}}"))
 	public static class OA02 {
 		@RestMethod(name=GET,path="/path/{foo}/responses/100")
-		public Foo doFoo(@ResponseStatuses Value<Integer> foo) {
-			return null;
-		}
+		public void doFoo(@ResponseStatus Value<Integer> foo) {}
 	}
 
 	@Test
@@ -1813,9 +1821,7 @@ public class BasicRestInfoProviderTest {
 	@RestResource(swagger=@ResourceSwagger("paths:{'/path/{foo}/responses/100':{get:{responses:{100:{description:'a-100-description'}}}}}"))
 	public static class OA03 {
 		@RestMethod(name=GET,path="/path/{foo}/responses/100",swagger=@MethodSwagger("responses:{100:{description:'b-100-description'}}"))
-		public Foo doFoo(@ResponseStatuses Value<Integer> foo) {
-			return null;
-		}
+		public void doFoo(@ResponseStatus Value<Integer> foo) {}
 	}
 
 	@Test
@@ -1825,31 +1831,51 @@ public class BasicRestInfoProviderTest {
 	}
 
 	@RestResource(swagger=@ResourceSwagger("paths:{'/path/{foo}/responses/100':{get:{responses:{100:{description:'a-100-description'}}}}}"))
-	public static class OA04 {
+	public static class OA04a {
 		@RestMethod(name=GET,path="/path/{foo}/responses/100")
-		public Foo doFoo(@Response(code=100,description="c-100-description") Value<Foo> foo) {
-			return null;
-		}
+		public void doFoo(Value<OA04x> foo) {}
+	}
+	@RestResource(swagger=@ResourceSwagger("paths:{'/path/{foo}/responses/100':{get:{responses:{100:{description:'a-100-description'}}}}}"))
+	public static class OA04b {
+		@RestMethod(name=GET,path="/path/{foo}/responses/100")
+		public OA04x doFoo() {return null;}
 	}
+	@Response(code=100,description="c-100-description")
+	public static class OA04x {}
 
 	@Test
-	public void oa04_response_100_description_swaggerOnAnnotation() throws Exception {
-		assertEquals("c-100-description", getSwagger(new OA04()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getDescription());
-		assertEquals("c-100-description", getSwaggerWithFile(new OA04()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getDescription());
+	public void oa04a_response_100_description_swaggerOnAnnotation() throws Exception {
+		assertEquals("c-100-description", getSwagger(new OA04a()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getDescription());
+		assertEquals("c-100-description", getSwaggerWithFile(new OA04a()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getDescription());
+	}
+	@Test
+	public void oa04b_response_100_description_swaggerOnAnnotation() throws Exception {
+		assertEquals("c-100-description", getSwagger(new OA04b()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getDescription());
+		assertEquals("c-100-description", getSwaggerWithFile(new OA04b()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getDescription());
 	}
 
 	@RestResource(messages="BasicRestInfoProviderTest", swagger=@ResourceSwagger("paths:{'/path/{foo}/responses/100':{get:{responses:{100:{description:'a-100-description'}}}}}"))
-	public static class OA05 {
+	public static class OA05a {
 		@RestMethod(name=GET,path="/path/{foo}/responses/100")
-		public Foo doFoo(@Response(code=100,description="$L{foo}") Value<Foo> foo) {
-			return null;
-		}
+		public void doFoo(Value<OA05x> foo) {}
 	}
+	@RestResource(messages="BasicRestInfoProviderTest", swagger=@ResourceSwagger("paths:{'/path/{foo}/responses/100':{get:{responses:{100:{description:'a-100-description'}}}}}"))
+	public static class OA05b {
+		@RestMethod(name=GET,path="/path/{foo}/responses/100")
+		public OA05x doFoo() {return null;}
+	}
+	@Response(code=100,description="$L{foo}")
+	public static class OA05x {}
 
 	@Test
-	public void oa05_response_100_description_swaggerOnAnnotation_localized() throws Exception {
-		assertEquals("l-foo", getSwagger(new OA05()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getDescription());
-		assertEquals("l-foo", getSwaggerWithFile(new OA05()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getDescription());
+	public void oa05a_response_100_description_swaggerOnAnnotation_localized() throws Exception {
+		assertEquals("l-foo", getSwagger(new OA05a()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getDescription());
+		assertEquals("l-foo", getSwaggerWithFile(new OA05a()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getDescription());
+	}
+	@Test
+	public void oa05b_response_100_description_swaggerOnAnnotation_localized() throws Exception {
+		assertEquals("l-foo", getSwagger(new OA05b()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getDescription());
+		assertEquals("l-foo", getSwaggerWithFile(new OA05b()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getDescription());
 	}
 
 	//=================================================================================================================
@@ -1857,23 +1883,33 @@ public class BasicRestInfoProviderTest {
 	//=================================================================================================================
 
 	@RestResource
-	public static class OB01 {
+	public static class OB01a {
 		@RestMethod(name=GET,path="/path/{foo}/responses/100")
-		public Foo doFoo(@Response(code=100) Value<Foo> foo) {
-			return null;
-		}
+		public void doFoo(Value<OB01x> foo) {}
 	}
+	@RestResource
+	public static class OB01b {
+		@RestMethod(name=GET,path="/path/{foo}/responses/100")
+		public OB01x doFoo() {return null;}
+	}
+	@Response(code=100)
+	public static class OB01x {}
 
 	@Test
-	public void ob01_responses_100_headers_default() throws Exception {
-		assertEquals(null, getSwagger(new OB01()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getHeaders());
-		assertObjectEquals("{'X-Foo':{description:'s-description',type:'integer',format:'int32'}}", getSwaggerWithFile(new OB01()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getHeaders());
+	public void ob01a_responses_100_headers_default() throws Exception {
+		assertEquals(null, getSwagger(new OB01a()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getHeaders());
+		assertObjectEquals("{'X-Foo':{description:'s-description',type:'integer',format:'int32'}}", getSwaggerWithFile(new OB01a()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getHeaders());
+	}
+	@Test
+	public void ob01b_responses_100_headers_default() throws Exception {
+		assertEquals(null, getSwagger(new OB01b()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getHeaders());
+		assertObjectEquals("{'X-Foo':{description:'s-description',type:'integer',format:'int32'}}", getSwaggerWithFile(new OB01b()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getHeaders());
 	}
 
 	@RestResource(swagger=@ResourceSwagger("paths:{'/path/{foo}/responses/100':{get:{responses:{100:{headers:{'X-Foo':{description:'b-description',type:'integer',format:'int32'}}}}}}}"))
 	public static class OB02 {
 		@RestMethod(name=GET,path="/path/{foo}/responses/100")
-		public Foo doFoo(@ResponseStatuses Value<Integer> foo) {
+		public Foo doFoo(@ResponseStatus Value<Integer> foo) {
 			return null;
 		}
 	}
@@ -1887,7 +1923,7 @@ public class BasicRestInfoProviderTest {
 	@RestResource(swagger=@ResourceSwagger("paths:{'/path/{foo}/responses/100':{get:{responses:{100:{headers:{'X-Foo':{description:'b-description',type:'integer',format:'int32'}}}}}}}"))
 	public static class OB03 {
 		@RestMethod(name=GET,path="/path/{foo}/responses/100",swagger=@MethodSwagger("responses:{100:{headers:{'X-Foo':{description:'c-description',type:'integer',format:'int32'}}}}"))
-		public Foo doFoo(@ResponseStatuses Value<Integer> foo) {
+		public Foo doFoo(@ResponseStatus Value<Integer> foo) {
 			return null;
 		}
 	}
@@ -1899,31 +1935,51 @@ public class BasicRestInfoProviderTest {
 	}
 
 	@RestResource(swagger=@ResourceSwagger("paths:{'/path/{foo}/responses/100':{get:{responses:{100:{headers:{'X-Foo':{description:'b-description',type:'integer',format:'int32'}}}}}}}"))
-	public static class OB04 {
+	public static class OB04a {
 		@RestMethod(name=GET,path="/path/{foo}/responses/100")
-		public Foo doFoo(@Response(code=100,headers=@ResponseHeader(name="X-Foo",description="d-description",type="integer",format="int32")) Value<Foo> foo) {
-			return null;
-		}
+		public void doFoo(Value<OB04x> foo) {}
+	}
+	@RestResource(swagger=@ResourceSwagger("paths:{'/path/{foo}/responses/100':{get:{responses:{100:{headers:{'X-Foo':{description:'b-description',type:'integer',format:'int32'}}}}}}}"))
+	public static class OB04b {
+		@RestMethod(name=GET,path="/path/{foo}/responses/100")
+		public OB04x doFoo() {return null;}
 	}
+	@Response(code=100,headers=@ResponseHeader(name="X-Foo",description="d-description",type="integer",format="int32"))
+	public static class OB04x {}
 
 	@Test
-	public void ob04_response_100_headers_swaggerOnAnnotation() throws Exception {
-		assertObjectEquals("{'X-Foo':{description:'d-description',type:'integer',format:'int32'}}", getSwagger(new OB04()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getHeaders());
-		assertObjectEquals("{'X-Foo':{description:'d-description',type:'integer',format:'int32'}}", getSwaggerWithFile(new OB04()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getHeaders());
+	public void ob04a_response_100_headers_swaggerOnAnnotation() throws Exception {
+		assertObjectEquals("{'X-Foo':{description:'d-description',type:'integer',format:'int32'}}", getSwagger(new OB04a()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getHeaders());
+		assertObjectEquals("{'X-Foo':{description:'d-description',type:'integer',format:'int32'}}", getSwaggerWithFile(new OB04a()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getHeaders());
+	}
+	@Test
+	public void ob04b_response_100_headers_swaggerOnAnnotation() throws Exception {
+		assertObjectEquals("{'X-Foo':{description:'d-description',type:'integer',format:'int32'}}", getSwagger(new OB04b()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getHeaders());
+		assertObjectEquals("{'X-Foo':{description:'d-description',type:'integer',format:'int32'}}", getSwaggerWithFile(new OB04b()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getHeaders());
 	}
 
 	@RestResource(messages="BasicRestInfoProviderTest", swagger=@ResourceSwagger("paths:{'/path/{foo}/responses/100':{get:{responses:{100:{headers:{'X-Foo':{description:'b-description',type:'integer',format:'int32'}}}}}}}"))
-	public static class OB05 {
+	public static class OB05a {
 		@RestMethod(name=GET,path="/path/{foo}/responses/100")
-		public Foo doFoo(@Response(code=100,headers=@ResponseHeader(name="X-Foo",description="$L{foo}",type="integer",format="int32")) Value<Foo> foo) {
-			return null;
-		}
+		public void doFoo(Value<OB05x> foo) {}
 	}
+	@RestResource(messages="BasicRestInfoProviderTest", swagger=@ResourceSwagger("paths:{'/path/{foo}/responses/100':{get:{responses:{100:{headers:{'X-Foo':{description:'b-description',type:'integer',format:'int32'}}}}}}}"))
+	public static class OB05b {
+		@RestMethod(name=GET,path="/path/{foo}/responses/100")
+		public OB05x doFoo() {return null;}
+	}
+	@Response(code=100,headers=@ResponseHeader(name="X-Foo",description="$L{foo}",type="integer",format="int32"))
+	public static class OB05x {}
 
 	@Test
-	public void ob05_response_100_headers_swaggerOnAnnotation_localized() throws Exception {
-		assertObjectEquals("{'X-Foo':{description:'l-foo',type:'integer',format:'int32'}}", getSwagger(new OB05()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getHeaders());
-		assertObjectEquals("{'X-Foo':{description:'l-foo',type:'integer',format:'int32'}}", getSwaggerWithFile(new OB05()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getHeaders());
+	public void ob05a_response_100_headers_swaggerOnAnnotation_localized() throws Exception {
+		assertObjectEquals("{'X-Foo':{description:'l-foo',type:'integer',format:'int32'}}", getSwagger(new OB05a()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getHeaders());
+		assertObjectEquals("{'X-Foo':{description:'l-foo',type:'integer',format:'int32'}}", getSwaggerWithFile(new OB05a()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getHeaders());
+	}
+	@Test
+	public void ob05b_response_100_headers_swaggerOnAnnotation_localized() throws Exception {
+		assertObjectEquals("{'X-Foo':{description:'l-foo',type:'integer',format:'int32'}}", getSwagger(new OB05b()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getHeaders());
+		assertObjectEquals("{'X-Foo':{description:'l-foo',type:'integer',format:'int32'}}", getSwaggerWithFile(new OB05b()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getHeaders());
 	}
 
 	//=================================================================================================================
@@ -1931,25 +1987,33 @@ public class BasicRestInfoProviderTest {
 	//=================================================================================================================
 
 	@RestResource
-	public static class OC01 {
+	public static class OC01a {
 		@RestMethod(name=GET,path="/path/{foo}/responses/100")
-		public Foo doFoo(@Response(code=100) Value<Foo> foo) {
-			return null;
-		}
+		public void doFoo(Value<OC01x> foo) {}
+	}
+	@RestResource
+	public static class OC01b {
+		@RestMethod(name=GET,path="/path/{foo}/responses/100")
+		public OC01x doFoo() {return null;}
 	}
+	@Response(code=100)
+	public static class OC01x {}
 
 	@Test
-	public void oc01_responses_100_example_default() throws Exception {
-		assertEquals(null, getSwagger(new OC01()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getExample());
-		assertObjectEquals("{foo:'a'}", getSwaggerWithFile(new OC01()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getExample());
+	public void oc01a_responses_100_example_default() throws Exception {
+		assertEquals(null, getSwagger(new OC01a()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getExample());
+		assertObjectEquals("{foo:'a'}", getSwaggerWithFile(new OC01a()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getExample());
+	}
+	@Test
+	public void oc01b_responses_100_example_default() throws Exception {
+		assertEquals(null, getSwagger(new OC01b()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getExample());
+		assertObjectEquals("{foo:'a'}", getSwaggerWithFile(new OC01b()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getExample());
 	}
 
 	@RestResource(swagger=@ResourceSwagger("paths:{'/path/{foo}/responses/100':{get:{responses:{100:{example:{foo:'b'}}}}}}"))
 	public static class OC02 {
 		@RestMethod(name=GET,path="/path/{foo}/responses/100")
-		public Foo doFoo(@ResponseStatuses Value<Integer> foo) {
-			return null;
-		}
+		public void doFoo(@ResponseStatus Value<Integer> foo) {}
 	}
 
 	@Test
@@ -1961,9 +2025,7 @@ public class BasicRestInfoProviderTest {
 	@RestResource(swagger=@ResourceSwagger("paths:{'/path/{foo}/responses/100':{get:{responses:{100:{example:{foo:'b'}}}}}}"))
 	public static class OC03 {
 		@RestMethod(name=GET,path="/path/{foo}/responses/100",swagger=@MethodSwagger("responses:{100:{example:{foo:'c'}}}"))
-		public Foo doFoo(@ResponseStatuses Value<Integer> foo) {
-			return null;
-		}
+		public void doFoo(@ResponseStatus Value<Integer> foo) {}
 	}
 
 	@Test
@@ -1973,31 +2035,51 @@ public class BasicRestInfoProviderTest {
 	}
 
 	@RestResource(swagger=@ResourceSwagger("paths:{'/path/{foo}/responses/100':{get:{responses:{100:{example:{foo:'b'}}}}}}"))
-	public static class OC04 {
+	public static class OC04a {
 		@RestMethod(name=GET,path="/path/{foo}/responses/100")
-		public Foo doFoo(@Response(code=100,example="{foo:'d'}") Value<Foo> foo) {
-			return null;
-		}
+		public void doFoo(Value<OC04x> foo) {}
+	}
+	@RestResource(swagger=@ResourceSwagger("paths:{'/path/{foo}/responses/100':{get:{responses:{100:{example:{foo:'b'}}}}}}"))
+	public static class OC04b {
+		@RestMethod(name=GET,path="/path/{foo}/responses/100")
+		public OC04x doFoo() {return null;}
 	}
+	@Response(code=100,example="{foo:'d'}")
+	public static class OC04x {}
 
 	@Test
-	public void oc04_response_100_example_swaggerOnAnnotation() throws Exception {
-		assertObjectEquals("{foo:'d'}", getSwagger(new OC04()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getExample());
-		assertObjectEquals("{foo:'d'}", getSwaggerWithFile(new OC04()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getExample());
+	public void oc04a_response_100_example_swaggerOnAnnotation() throws Exception {
+		assertObjectEquals("{foo:'d'}", getSwagger(new OC04a()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getExample());
+		assertObjectEquals("{foo:'d'}", getSwaggerWithFile(new OC04a()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getExample());
+	}
+	@Test
+	public void oc04b_response_100_example_swaggerOnAnnotation() throws Exception {
+		assertObjectEquals("{foo:'d'}", getSwagger(new OC04b()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getExample());
+		assertObjectEquals("{foo:'d'}", getSwaggerWithFile(new OC04b()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getExample());
 	}
 
 	@RestResource(messages="BasicRestInfoProviderTest", swagger=@ResourceSwagger("paths:{'/path/{foo}/responses/100':{get:{responses:{100:{example:{foo:'b'}}}}}}"))
-	public static class OC05 {
+	public static class OC05a {
 		@RestMethod(name=GET,path="/path/{foo}/responses/100")
-		public Foo doFoo(@Response(code=100,example="{foo:'$L{foo}'}") Value<Foo> foo) {
-			return null;
-		}
+		public void doFoo(Value<OC05x> foo) {}
+	}
+	@RestResource(messages="BasicRestInfoProviderTest", swagger=@ResourceSwagger("paths:{'/path/{foo}/responses/100':{get:{responses:{100:{example:{foo:'b'}}}}}}"))
+	public static class OC05b {
+		@RestMethod(name=GET,path="/path/{foo}/responses/100")
+		public OC05x doFoo() {return null;}
 	}
+	@Response(code=100,example="{foo:'$L{foo}'}")
+	public static class OC05x {}
 
 	@Test
-	public void oc05_response_100_example_swaggerOnAnnotation_localized() throws Exception {
-		assertObjectEquals("{foo:'l-foo'}", getSwagger(new OC05()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getExample());
-		assertObjectEquals("{foo:'l-foo'}", getSwaggerWithFile(new OC05()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getExample());
+	public void oc05a_response_100_example_swaggerOnAnnotation_localized() throws Exception {
+		assertObjectEquals("{foo:'l-foo'}", getSwagger(new OC05a()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getExample());
+		assertObjectEquals("{foo:'l-foo'}", getSwaggerWithFile(new OC05a()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getExample());
+	}
+	@Test
+	public void oc05b_response_100_example_swaggerOnAnnotation_localized() throws Exception {
+		assertObjectEquals("{foo:'l-foo'}", getSwagger(new OC05b()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getExample());
+		assertObjectEquals("{foo:'l-foo'}", getSwaggerWithFile(new OC05b()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getExample());
 	}
 
 	//=================================================================================================================
@@ -2005,25 +2087,33 @@ public class BasicRestInfoProviderTest {
 	//=================================================================================================================
 
 	@RestResource
-	public static class OD01 {
+	public static class OD01a {
 		@RestMethod(name=GET,path="/path/{foo}/responses/100")
-		public Foo doFoo(@Response(code=100) Value<Foo> foo) {
-			return null;
-		}
+		public void doFoo(Value<OD01x> foo) {}
 	}
+	@RestResource
+	public static class OD01b {
+		@RestMethod(name=GET,path="/path/{foo}/responses/100")
+		public OD01x doFoo() {return null;}
+	}
+	@Response(code=100)
+	public static class OD01x {}
 
 	@Test
-	public void od01_responses_100_examples_default() throws Exception {
-		assertEquals(null, getSwagger(new OD01()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getExamples());
-		assertObjectEquals("{foo:'a'}", getSwaggerWithFile(new OD01()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getExamples());
+	public void od01a_responses_100_examples_default() throws Exception {
+		assertEquals(null, getSwagger(new OD01a()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getExamples());
+		assertObjectEquals("{foo:'a'}", getSwaggerWithFile(new OD01a()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getExamples());
+	}
+	@Test
+	public void od01b_responses_100_examples_default() throws Exception {
+		assertEquals(null, getSwagger(new OD01b()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getExamples());
+		assertObjectEquals("{foo:'a'}", getSwaggerWithFile(new OD01b()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getExamples());
 	}
 
 	@RestResource(swagger=@ResourceSwagger("paths:{'/path/{foo}/responses/100':{get:{responses:{100:{examples:{foo:{bar:'b'}}}}}}}"))
 	public static class OD02 {
 		@RestMethod(name=GET,path="/path/{foo}/responses/100")
-		public Foo doFoo(@ResponseStatuses Value<Integer> foo) {
-			return null;
-		}
+		public void doFoo(@ResponseStatus Value<Integer> foo) {}
 	}
 
 	@Test
@@ -2035,9 +2125,7 @@ public class BasicRestInfoProviderTest {
 	@RestResource(swagger=@ResourceSwagger("paths:{'/path/{foo}/responses/100':{get:{responses:{100:{examples:{foo:{bar:'b'}}}}}}}"))
 	public static class OD03 {
 		@RestMethod(name=GET,path="/path/{foo}/responses/100",swagger=@MethodSwagger("responses:{100:{examples:{foo:{bar:'c'}}}}"))
-		public Foo doFoo(@ResponseStatuses Value<Integer> foo) {
-			return null;
-		}
+		public void doFoo(@ResponseStatus Value<Integer> foo) {}
 	}
 
 	@Test
@@ -2047,31 +2135,51 @@ public class BasicRestInfoProviderTest {
 	}
 
 	@RestResource(swagger=@ResourceSwagger("paths:{'/path/{foo}/responses/100':{get:{responses:{100:{examples:{foo:{bar:'b'}}}}}}}"))
-	public static class OD04 {
+	public static class OD04a {
 		@RestMethod(name=GET,path="/path/{foo}/responses/100")
-		public Foo doFoo(@Response(code=100,examples="{foo:{bar:'d'}}") Value<Foo> foo) {
-			return null;
-		}
+		public void doFoo(Value<OD04x> foo) {}
 	}
+	@RestResource(swagger=@ResourceSwagger("paths:{'/path/{foo}/responses/100':{get:{responses:{100:{examples:{foo:{bar:'b'}}}}}}}"))
+	public static class OD04b {
+		@RestMethod(name=GET,path="/path/{foo}/responses/100")
+		public OD04x doFoo() {return null;}
+	}
+	@Response(code=100,examples="{foo:{bar:'d'}}")
+	public static class OD04x {}
 
 	@Test
-	public void od04_response_100_examples_swaggerOnAnnotation() throws Exception {
-		assertObjectEquals("{foo:{bar:'d'}}", getSwagger(new OD04()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getExamples());
-		assertObjectEquals("{foo:{bar:'d'}}", getSwaggerWithFile(new OD04()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getExamples());
+	public void od04a_response_100_examples_swaggerOnAnnotation() throws Exception {
+		assertObjectEquals("{foo:{bar:'d'}}", getSwagger(new OD04a()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getExamples());
+		assertObjectEquals("{foo:{bar:'d'}}", getSwaggerWithFile(new OD04a()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getExamples());
+	}
+	@Test
+	public void od04b_response_100_examples_swaggerOnAnnotation() throws Exception {
+		assertObjectEquals("{foo:{bar:'d'}}", getSwagger(new OD04b()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getExamples());
+		assertObjectEquals("{foo:{bar:'d'}}", getSwaggerWithFile(new OD04b()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getExamples());
 	}
 
 	@RestResource(messages="BasicRestInfoProviderTest", swagger=@ResourceSwagger("paths:{'/path/{foo}/responses/100':{get:{responses:{100:{examples:{foo:{bar:'b'}}}}}}}"))
-	public static class OD05 {
+	public static class OD05a {
 		@RestMethod(name=GET,path="/path/{foo}/responses/100")
-		public Foo doFoo(@Response(code=100,examples="{foo:{bar:'$L{foo}'}}") Value<Foo> foo) {
-			return null;
-		}
+		public void doFoo(Value<OD05x> foo) {}
 	}
+	@RestResource(messages="BasicRestInfoProviderTest", swagger=@ResourceSwagger("paths:{'/path/{foo}/responses/100':{get:{responses:{100:{examples:{foo:{bar:'b'}}}}}}}"))
+	public static class OD05b {
+		@RestMethod(name=GET,path="/path/{foo}/responses/100")
+		public OD05x doFoo() {return null;}
+	}
+	@Response(code=100,examples="{foo:{bar:'$L{foo}'}}")
+	public static class OD05x {}
 
 	@Test
-	public void od05_response_100_examples_swaggerOnAnnotation_lodalized() throws Exception {
-		assertObjectEquals("{foo:{bar:'l-foo'}}", getSwagger(new OD05()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getExamples());
-		assertObjectEquals("{foo:{bar:'l-foo'}}", getSwaggerWithFile(new OD05()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getExamples());
+	public void od05a_response_100_examples_swaggerOnAnnotation_lodalized() throws Exception {
+		assertObjectEquals("{foo:{bar:'l-foo'}}", getSwagger(new OD05a()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getExamples());
+		assertObjectEquals("{foo:{bar:'l-foo'}}", getSwaggerWithFile(new OD05a()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getExamples());
+	}
+	@Test
+	public void od05b_response_100_examples_swaggerOnAnnotation_lodalized() throws Exception {
+		assertObjectEquals("{foo:{bar:'l-foo'}}", getSwagger(new OD05b()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getExamples());
+		assertObjectEquals("{foo:{bar:'l-foo'}}", getSwaggerWithFile(new OD05b()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getExamples());
 	}
 
 	//=================================================================================================================
@@ -2079,25 +2187,33 @@ public class BasicRestInfoProviderTest {
 	//=================================================================================================================
 
 	@RestResource
-	public static class OE01 {
+	public static class OE01a {
 		@RestMethod(name=GET,path="/path/{foo}/responses/100")
-		public Foo doFoo(@Response(code=100) Value<Foo> foo) {
-			return null;
-		}
+		public void doFoo(Value<OE01x> foo) {}
 	}
+	@RestResource
+	public static class OE01b {
+		@RestMethod(name=GET,path="/path/{foo}/responses/100")
+		public OE01x doFoo() {return null;}
+	}
+	@Response(code=100)
+	public static class OE01x extends Foo {}
 
 	@Test
-	public void oe01_responses_100_schema_default() throws Exception {
-		assertObjectEquals("{type:'object',properties:{id:{format:'int32',type:'integer'}}}", getSwagger(new OE01()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getSchema());
-		assertObjectEquals("{type:'array',items:{'$ref':'#/definitions/Foo'}}", getSwaggerWithFile(new OE01()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getSchema());
+	public void oe01a_responses_100_schema_default() throws Exception {
+		assertObjectEquals("{type:'object',properties:{id:{format:'int32',type:'integer'}}}", getSwagger(new OE01a()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getSchema());
+		assertObjectEquals("{type:'array',items:{'$ref':'#/definitions/Foo'}}", getSwaggerWithFile(new OE01a()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getSchema());
+	}
+	@Test
+	public void oe01b_responses_100_schema_default() throws Exception {
+		assertObjectEquals("{type:'object',properties:{id:{format:'int32',type:'integer'}}}", getSwagger(new OE01b()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getSchema());
+		assertObjectEquals("{type:'array',items:{'$ref':'#/definitions/Foo'}}", getSwaggerWithFile(new OE01b()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getSchema());
 	}
 
 	@RestResource(swagger=@ResourceSwagger("paths:{'/path/{foo}/responses/100':{get:{responses:{100:{schema:{$ref:'b'}}}}}}"))
 	public static class OE02 {
 		@RestMethod(name=GET,path="/path/{foo}/responses/100")
-		public Foo doFoo(@ResponseStatuses Value<Integer> foo) {
-			return null;
-		}
+		public void doFoo(@ResponseStatus Value<Integer> foo) {}
 	}
 
 	@Test
@@ -2109,9 +2225,7 @@ public class BasicRestInfoProviderTest {
 	@RestResource(swagger=@ResourceSwagger("paths:{'/path/{foo}/responses/100':{get:{responses:{100:{schema:{$ref:'b'}}}}}}"))
 	public static class OE03 {
 		@RestMethod(name=GET,path="/path/{foo}/responses/100",swagger=@MethodSwagger("responses:{100:{schema:{$ref:'c'}}}}"))
-		public Foo doFoo(@ResponseStatuses Value<Integer> foo) {
-			return null;
-		}
+		public void doFoo(@ResponseStatus Value<Integer> foo) {}
 	}
 
 	@Test
@@ -2121,33 +2235,52 @@ public class BasicRestInfoProviderTest {
 	}
 
 	@RestResource(swagger=@ResourceSwagger("paths:{'/path/{foo}/responses/100':{get:{responses:{100:{schema:{$ref:'b'}}}}}}"))
-	public static class OE04 {
+	public static class OE04a {
 		@RestMethod(name=GET,path="/path/{foo}/responses/100")
-		public Foo doFoo(@Response(code=100,schema=@Schema($ref="d")) Value<Foo> foo) {
-			return null;
-		}
+		public void doFoo(Value<OE04x> foo) {}
+	}
+	@RestResource(swagger=@ResourceSwagger("paths:{'/path/{foo}/responses/100':{get:{responses:{100:{schema:{$ref:'b'}}}}}}"))
+	public static class OE04b {
+		@RestMethod(name=GET,path="/path/{foo}/responses/100")
+		public OE04x doFoo() {return null;}
 	}
+	@Response(code=100,schema=@Schema($ref="d"))
+	public static class OE04x extends Foo {}
 
 	@Test
-	public void oe04_response_100_schema_swaggerOnAnnotation() throws Exception {
-		assertObjectEquals("{'$ref':'d'}", getSwagger(new OE04()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getSchema());
-		assertObjectEquals("{'$ref':'d'}", getSwaggerWithFile(new OE04()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getSchema());
+	public void oe04a_response_100_schema_swaggerOnAnnotation() throws Exception {
+		assertObjectEquals("{'$ref':'d'}", getSwagger(new OE04a()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getSchema());
+		assertObjectEquals("{'$ref':'d'}", getSwaggerWithFile(new OE04a()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getSchema());
+	}
+	@Test
+	public void oe04b_response_100_schema_swaggerOnAnnotation() throws Exception {
+		assertObjectEquals("{'$ref':'d'}", getSwagger(new OE04b()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getSchema());
+		assertObjectEquals("{'$ref':'d'}", getSwaggerWithFile(new OE04b()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getSchema());
 	}
 
 	@RestResource(messages="BasicRestInfoProviderTest", swagger=@ResourceSwagger("paths:{'/path/{foo}/responses/100':{get:{responses:{100:{schema:{$ref:'b'}}}}}}"))
-	public static class OE05 {
+	public static class OE05a {
 		@RestMethod(name=GET,path="/path/{foo}/responses/100")
-		public Foo doFoo(@Response(code=100,schema=@Schema("{$ref:'$L{foo}'}")) Value<Foo> foo) {
-			return null;
-		}
+		public void doFoo(Value<OE05x> foo) {}
+	}
+	@RestResource(messages="BasicRestInfoProviderTest", swagger=@ResourceSwagger("paths:{'/path/{foo}/responses/100':{get:{responses:{100:{schema:{$ref:'b'}}}}}}"))
+	public static class OE05b {
+		@RestMethod(name=GET,path="/path/{foo}/responses/100")
+		public OE05x doFoo() {return null;}
 	}
+	@Response(code=100,schema=@Schema("{$ref:'$L{foo}'}"))
+	public static class OE05x extends Foo {}
 
 	@Test
-	public void oe05_response_100_schema_swaggerOnAnnotation_loealized() throws Exception {
-		assertObjectEquals("{'$ref':'l-foo'}", getSwagger(new OE05()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getSchema());
-		assertObjectEquals("{'$ref':'l-foo'}", getSwaggerWithFile(new OE05()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getSchema());
+	public void oe05a_response_100_schema_swaggerOnAnnotation_loealized() throws Exception {
+		assertObjectEquals("{'$ref':'l-foo'}", getSwagger(new OE05a()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getSchema());
+		assertObjectEquals("{'$ref':'l-foo'}", getSwaggerWithFile(new OE05a()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getSchema());
+	}
+	@Test
+	public void oe05b_response_100_schema_swaggerOnAnnotation_loealized() throws Exception {
+		assertObjectEquals("{'$ref':'l-foo'}", getSwagger(new OE05b()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getSchema());
+		assertObjectEquals("{'$ref':'l-foo'}", getSwaggerWithFile(new OE05b()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getSchema());
 	}
-
 
 	@Bean(typeName="Foo")
 	public static class Foo {
diff --git a/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/annotation/ResponseAnnotationTest.java b/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/annotation/ResponseAnnotationTest.java
index 02e623f..06fe540 100644
--- a/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/annotation/ResponseAnnotationTest.java
+++ b/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/annotation/ResponseAnnotationTest.java
@@ -58,12 +58,6 @@ public class ResponseAnnotationTest {
 	@RestResource
 	public static class A {
 
-		@Response(code=201)
-		@RestMethod(name=GET,path="/codeOnMethod")
-		public String a01() {
-			return "foo";
-		}
-
 		@RestMethod(name=GET,path="/codeOnClass")
 		public A02 a02() {
 			return new A02();
@@ -73,12 +67,6 @@ public class ResponseAnnotationTest {
 		public String a03() throws A03 {
 			throw new A03();
 		}
-
-		@Response(code=201)
-		@RestMethod(name=GET,path="/codeOnParameter")
-		public void a04(@Response(code=201) Value<String> value) {
-			value.set("foo");
-		}
 	}
 
 	@Response(code=201)
@@ -96,11 +84,6 @@ public class ResponseAnnotationTest {
 	static MockRest a = MockRest.create(A.class);
 
 	@Test
-	public void a01_codeOnMethod() throws Exception {
-		a.get("/codeOnMethod").execute().assertStatus(201).assertBody("foo");
-	}
-
-	@Test
 	public void a02_codeOnClass() throws Exception {
 		a.get("/codeOnClass").execute().assertStatus(201).assertBody("foo");
 	}
@@ -110,11 +93,6 @@ public class ResponseAnnotationTest {
 		a.get("/codeOnThrown").execute().assertStatus(501);
 	}
 
-	@Test
-	public void a04_codeOnParameter() throws Exception {
-		a.get("/codeOnParameter").execute().assertStatus(201).assertBody("foo");
-	}
-
 	//=================================================================================================================
 	// PartSerializers
 	//=================================================================================================================
@@ -148,13 +126,13 @@ public class ResponseAnnotationTest {
 	@RestResource(partSerializer=XPartSerializer.class)
 	public static class B {
 
-		@Response(usePartSerializer=true)
+		@ResponseBody(usePartSerializer=true)
 		@RestMethod(name=GET,path="/useOnMethod")
 		public String b01() {
 			return "foo";
 		}
 
-		@Response(usePartSerializer=false)
+		@ResponseBody(usePartSerializer=false)
 		@RestMethod(name=GET,path="/dontUseOnMethod")
 		public String b02() {
 			return "foo";
@@ -181,12 +159,12 @@ public class ResponseAnnotationTest {
 		}
 
 		@RestMethod(name=GET,path="/useOnParameter")
-		public void b07(@Response(usePartSerializer=true) Value<String> value) {
+		public void b07(@ResponseBody(usePartSerializer=true) Value<String> value) {
 			value.set("foo");
 		}
 
 		@RestMethod(name=GET,path="/dontUseOnParameter")
-		public void b08(@Response(usePartSerializer=false) Value<String> value) {
+		public void b08(@ResponseBody(usePartSerializer=false) Value<String> value) {
 			value.set("foo");
 		}
 
@@ -266,13 +244,13 @@ public class ResponseAnnotationTest {
 	@RestResource
 	public static class C {
 
-		@Response(partSerializer=XPartSerializer.class)
+		@ResponseBody(partSerializer=XPartSerializer.class)
 		@RestMethod(name=GET,path="/useOnMethod")
 		public String c01() {
 			return "foo";
 		}
 
-		@Response
+		@ResponseBody
 		@RestMethod(name=GET,path="/dontUseOnMethod")
 		public String c02() {
 			return "foo";
@@ -299,12 +277,12 @@ public class ResponseAnnotationTest {
 		}
 
 		@RestMethod(name=GET,path="/useOnParameter")
-		public void c07(@Response(partSerializer=XPartSerializer.class) Value<String> value) {
+		public void c07(@ResponseBody(partSerializer=XPartSerializer.class) Value<String> value) {
 			value.set("foo");
 		}
 
 		@RestMethod(name=GET,path="/dontUseOnParameter")
-		public void c08(@Response Value<String> value) {
+		public void c08(@ResponseBody Value<String> value) {
 			value.set("foo");
 		}
 
@@ -384,7 +362,7 @@ public class ResponseAnnotationTest {
 	@RestResource
 	public static class D {
 
-		@Response(schema=@Schema(collectionFormat="pipes"),usePartSerializer=true)
+		@ResponseBody(schema=@Schema(collectionFormat="pipes"),usePartSerializer=true)
 		@RestMethod(name=GET,path="/useOnMethod")
 		public String[] d01() {
 			return new String[]{"foo","bar"};
@@ -401,11 +379,11 @@ public class ResponseAnnotationTest {
 		}
 
 		@RestMethod(name=GET,path="/useOnParameter")
-		public void d04(@Response(schema=@Schema(collectionFormat="pipes"),usePartSerializer=true) Value<String[]> value) {
+		public void d04(@ResponseBody(schema=@Schema(collectionFormat="pipes"),usePartSerializer=true) Value<String[]> value) {
 			value.set(new String[]{"foo","bar"});
 		}
 
-		@Response(schema=@Schema(type="string",format="byte"),usePartSerializer=true)
+		@ResponseBody(schema=@Schema(type="string",format="byte"),usePartSerializer=true)
 		@RestMethod(name=GET,path="/useOnMethodBytes")
 		public byte[] d05() {
 			return "foo".getBytes();
@@ -423,7 +401,7 @@ public class ResponseAnnotationTest {
 
 
 		@RestMethod(name=GET,path="/useOnParameterBytes")
-		public void d08(@Response(schema=@Schema(type="string",format="byte"),usePartSerializer=true) Value<byte[]> value) {
+		public void d08(@ResponseBody(schema=@Schema(type="string",format="byte"),usePartSerializer=true) Value<byte[]> value) {
 			value.set("foo".getBytes());
 		}
 
@@ -520,8 +498,10 @@ public class ResponseAnnotationTest {
 			examples=" {foo:'a'} "
 		)
 		public static class SA01 {}
-		@RestMethod(name=GET,path="/basic")
-		public void sa01(SA01 r) {}
+		@RestMethod
+		public void sa01a(Value<SA01> r) {}
+		@RestMethod
+		public SA01 sa01b() {return null;}
 
 		@Response(
 			api={
@@ -532,10 +512,11 @@ public class ResponseAnnotationTest {
 				"examples:{foo:'a'}"
 			}
 		)
-
 		public static class SA02 {}
-		@RestMethod(name=GET,path="/api")
-		public void sa02(SA02 r) {}
+		@RestMethod
+		public void sa02a(Value<SA02> r) {}
+		@RestMethod
+		public SA02 sa02b() {return null;}
 
 		@Response(
 			api={
@@ -552,28 +533,37 @@ public class ResponseAnnotationTest {
 			examples=" {foo:'a'} "
 		)
 		public static class SA03 {}
-		@RestMethod(name=GET,path="/mixed")
-		public void sa03(SA03 r) {}
+		@RestMethod
+		public void sa03a(Value<SA03> r) {}
+		@RestMethod
+		public SA03 sa03b() {return null;}
 
 		@Response(code=100)
 		public static class SA04 {}
-		@RestMethod(name=GET,path="/code")
-		public void sa04(SA04 r) {}
+		@RestMethod
+		public void sa04a(Value<SA04> r) {}
+		@RestMethod
+		public SA04 sa04b() {return null;}
 
 		@Response(100)
 		public static class SA05 {}
-		@RestMethod(name=GET,path="/value")
-		public void sa05(SA05 r) {}
+		@RestMethod
+		public void sa05a(Value<SA05> r) {}
+		@RestMethod
+		public SA05 sa05b() {return null;}
 
 		@Response(headers=@ResponseHeader(name="foo",api=" type:'b' "))
 		public static class SA06 {}
-		@RestMethod(name=GET,path="/headers")
-		public void sa06(SA06 r) {}
+		@RestMethod
+		public void sa06a(Value<SA06> r) {}
+		@RestMethod
+		public SA06 sa06b() {return null;}
 	}
 
 	@Test
-	public void sa01_Response_onPojo_basic() throws Exception {
-		ResponseInfo x = getSwagger(new SA()).getPaths().get("/basic").get("get").getResponse(200);
+	public void sa01a_Response_onPojo_basic() throws Exception {
+		System.err.println(getSwagger(new SA()).getPaths().get("/sa01a"));
+		ResponseInfo x = getSwagger(new SA()).getPaths().get("/sa01a").get("get").getResponse(200);
 		assertEquals("a\nb", x.getDescription());
 		assertObjectEquals("{type:'string'}", x.getSchema());
 		assertObjectEquals("{foo:{type:'string'}}", x.getHeaders());
@@ -581,8 +571,8 @@ public class ResponseAnnotationTest {
 		assertObjectEquals("{foo:'a'}", x.getExamples());
 	}
 	@Test
-	public void sa02_Response_onPojo_api() throws Exception {
-		ResponseInfo x = getSwagger(new SA()).getPaths().get("/api").get("get").getResponse(200);
+	public void sa01b_Response_onPojo_basic() throws Exception {
+		ResponseInfo x = getSwagger(new SA()).getPaths().get("/sa01b").get("get").getResponse(200);
 		assertEquals("a\nb", x.getDescription());
 		assertObjectEquals("{type:'string'}", x.getSchema());
 		assertObjectEquals("{foo:{type:'string'}}", x.getHeaders());
@@ -590,8 +580,8 @@ public class ResponseAnnotationTest {
 		assertObjectEquals("{foo:'a'}", x.getExamples());
 	}
 	@Test
-	public void sa03_Response_onPojo_mixed() throws Exception {
-		ResponseInfo x = getSwagger(new SA()).getPaths().get("/mixed").get("get").getResponse(200);
+	public void sa02a_Response_onPojo_api() throws Exception {
+		ResponseInfo x = getSwagger(new SA()).getPaths().get("/sa02a").get("get").getResponse(200);
 		assertEquals("a\nb", x.getDescription());
 		assertObjectEquals("{type:'string'}", x.getSchema());
 		assertObjectEquals("{foo:{type:'string'}}", x.getHeaders());
@@ -599,175 +589,8 @@ public class ResponseAnnotationTest {
 		assertObjectEquals("{foo:'a'}", x.getExamples());
 	}
 	@Test
-	public void sa04_Response_onPojo_code() throws Exception {
-		ResponseInfo x = getSwagger(new SA()).getPaths().get("/code").get("get").getResponse(100);
-		assertEquals("Continue", x.getDescription());
-	}
-	@Test
-	public void sa05_Response_onPojo_value() throws Exception {
-		ResponseInfo x = getSwagger(new SA()).getPaths().get("/value").get("get").getResponse(100);
-		assertEquals("Continue", x.getDescription());
-	}
-	@Test
-	public void sa06_Response_onPojo_headers() throws Exception {
-		ResponseInfo x = getSwagger(new SA()).getPaths().get("/headers").get("get").getResponse(200);
-		assertObjectEquals("{foo:{type:'b'}}", x.getHeaders());
-	}
-
-	//-----------------------------------------------------------------------------------------------------------------
-	// Schema
-	//-----------------------------------------------------------------------------------------------------------------
-
-	@RestResource
-	public static class SB {
-
-		@Response(schema=@Schema(" type:'number' "))
-		public static class SB01 {}
-		@RestMethod(name=GET,path="/schemaValue")
-		public void sb01(SB01 r) {}
-
-		@Response
-		public static class SB02 {
-			public String f1;
-		}
-		@RestMethod(name=GET,path="/autoDetectBean")
-		public void sb02(SB02 b) {}
-
-		@Response
-		public static class SB03 extends LinkedList<String> {
-			private static final long serialVersionUID = 1L;
-		}
-		@RestMethod(name=GET,path="/autoDetectList")
-		public void sb03(SB03 b) {}
-
-		@Response
-		public static class SB04 {}
-		@RestMethod(name=GET,path="/autoDetectStringObject")
-		public void sb04(SB04 b) {}
-	}
-
-	@Test
-	public void sb01_Response_onPojo_schemaValue() throws Exception {
-		ResponseInfo x = getSwagger(new SB()).getPaths().get("/schemaValue").get("get").getResponse(200);
-		assertObjectEquals("{type:'number'}", x.getSchema());
-	}
-	@Test
-	public void sb02_Response_onPojo_autoDetectBean() throws Exception {
-		ResponseInfo x = getSwagger(new SB()).getPaths().get("/autoDetectBean").get("get").getResponse(200);
-		assertObjectEquals("{type:'object',properties:{f1:{type:'string'}}}", x.getSchema());
-	}
-	@Test
-	public void sb03_Response_onPojo_autoDetectList() throws Exception {
-		ResponseInfo x = getSwagger(new SB()).getPaths().get("/autoDetectList").get("get").getResponse(200);
-		assertObjectEquals("{type:'array',items:{type:'string'}}", x.getSchema());
-	}
-	@Test
-	public void sb04_Response_onPojo_autoDetectStringObject() throws Exception {
-		ResponseInfo x = getSwagger(new SB()).getPaths().get("/autoDetectStringObject").get("get").getResponse(200);
-		assertObjectEquals("{type:'string'}", x.getSchema());
-	}
-
-	//-----------------------------------------------------------------------------------------------------------------
-	// Examples
-	//-----------------------------------------------------------------------------------------------------------------
-
-	@RestResource
-	public static class SC {
-
-		@Response(example="{f1:'a'}")
-		public static class SC01 {}
-		@RestMethod(name=GET,path="/example")
-		public void sc01(SC01 r) {}
-
-		@Response(examples={" foo:'b' "})
-		public static class SC02 {}
-		@RestMethod(name=GET,path="/examples")
-		public void sc02(SC02 r) {}
-	}
-
-	@Test
-	public void sc01_Response_onPojo_example() throws Exception {
-		ResponseInfo x = getSwagger(new SC()).getPaths().get("/example").get("get").getResponse(200);
-		assertObjectEquals("{f1:'a'}", x.getExample());
-	}
-	@Test
-	public void sc02_Response_onPojo_examples() throws Exception {
-		ResponseInfo x = getSwagger(new SC()).getPaths().get("/examples").get("get").getResponse(200);
-		assertObjectEquals("{foo:'b'}", x.getExamples());
-	}
-
-	//=================================================================================================================
-	// @Response on parameter
-	//=================================================================================================================
-
-	//-----------------------------------------------------------------------------------------------------------------
-	// Basic tests
-	//-----------------------------------------------------------------------------------------------------------------
-
-	@RestResource
-	public static class TA {
-
-		public static class TA01 {}
-		@RestMethod(name=GET,path="/basic")
-		public void ta01(
-			@Response(
-				description={"a","b"},
-				schema=@Schema(type="string"),
-				headers=@ResponseHeader(name="foo",type="string"),
-				example=" 'a' ",
-				examples=" {foo:'a'} "
-			) TA01 r
-		) {}
-
-		public static class TA02 {}
-		@RestMethod(name=GET,path="/api")
-		public void ta02(
-			@Response(
-				api={
-					"description:'a\nb',",
-					"schema:{type:'string'},",
-					"headers:{foo:{type:'string'}},",
-					"example:'a',",
-					"examples:{foo:'a'}"
-				}
-			) TA02 r
-		) {}
-
-		public static class TA03 {}
-		@RestMethod(name=GET,path="/mixed")
-		public void ta03(
-			@Response(
-				api={
-					"description:'b',",
-					"schema:{type:'number'},",
-					"headers:{bar:{type:'number'}},",
-					"example:'b',",
-					"examples:{bar:'b'}"
-				},
-				description={"a","b"},
-				schema=@Schema(type="string"),
-				headers=@ResponseHeader(name="foo",type="string"),
-				example=" 'a' ",
-				examples=" {foo:'a'} "
-			) TA03 r
-		) {}
-
-		public static class TA04 {}
-		@RestMethod(name=GET,path="/code")
-		public void ta04(@Response(code=100) TA04 r) {}
-
-		public static class TA05 {}
-		@RestMethod(name=GET,path="/value")
-		public void ta05(@Response(code=100) TA05 r) {}
-
-		public static class TA06 {}
-		@RestMethod(name=GET,path="/headers")
-		public void ta06(@Response(headers=@ResponseHeader(name="foo",api=" type:'number' ")) TA06 r) {}
-	}
-
-	@Test
-	public void ta01_Response_onParameter_basic() throws Exception {
-		ResponseInfo x = getSwagger(new TA()).getPaths().get("/basic").get("get").getResponse(200);
+	public void sa02b_Response_onPojo_api() throws Exception {
+		ResponseInfo x = getSwagger(new SA()).getPaths().get("/sa02b").get("get").getResponse(200);
 		assertEquals("a\nb", x.getDescription());
 		assertObjectEquals("{type:'string'}", x.getSchema());
 		assertObjectEquals("{foo:{type:'string'}}", x.getHeaders());
@@ -775,8 +598,8 @@ public class ResponseAnnotationTest {
 		assertObjectEquals("{foo:'a'}", x.getExamples());
 	}
 	@Test
-	public void ta02_Response_onParameter_api() throws Exception {
-		ResponseInfo x = getSwagger(new TA()).getPaths().get("/api").get("get").getResponse(200);
+	public void sa03a_Response_onPojo_mixed() throws Exception {
+		ResponseInfo x = getSwagger(new SA()).getPaths().get("/sa03a").get("get").getResponse(200);
 		assertEquals("a\nb", x.getDescription());
 		assertObjectEquals("{type:'string'}", x.getSchema());
 		assertObjectEquals("{foo:{type:'string'}}", x.getHeaders());
@@ -784,28 +607,43 @@ public class ResponseAnnotationTest {
 		assertObjectEquals("{foo:'a'}", x.getExamples());
 	}
 	@Test
-	public void ta03_Response_onParameter_mixed() throws Exception {
-		ResponseInfo x = getSwagger(new TA()).getPaths().get("/mixed").get("get").getResponse(200);
+	public void sa03b_Response_onPojo_mixed() throws Exception {
+		ResponseInfo x = getSwagger(new SA()).getPaths().get("/sa03b").get("get").getResponse(200);
 		assertEquals("a\nb", x.getDescription());
 		assertObjectEquals("{type:'string'}", x.getSchema());
-		assertObjectEquals("{foo:{type:'string'}}", x.getHeaders());
+		assertObjectEquals("{bar:{type:'number'},foo:{type:'string'}}", x.getHeaders());
 		assertObjectEquals("'a'", x.getExample());
 		assertObjectEquals("{foo:'a'}", x.getExamples());
 	}
 	@Test
-	public void ta04_Response_onParameter_code() throws Exception {
-		ResponseInfo x = getSwagger(new TA()).getPaths().get("/code").get("get").getResponse(100);
+	public void sa04a_Response_onPojo_code() throws Exception {
+		ResponseInfo x = getSwagger(new SA()).getPaths().get("/sa04a").get("get").getResponse(100);
 		assertEquals("Continue", x.getDescription());
 	}
 	@Test
-	public void ta05_Response_onParameter_value() throws Exception {
-		ResponseInfo x = getSwagger(new TA()).getPaths().get("/value").get("get").getResponse(100);
+	public void sa04b_Response_onPojo_code() throws Exception {
+		ResponseInfo x = getSwagger(new SA()).getPaths().get("/sa04b").get("get").getResponse(100);
 		assertEquals("Continue", x.getDescription());
 	}
 	@Test
-	public void ta06_Response_onParameter_headers() throws Exception {
-		ResponseInfo x = getSwagger(new TA()).getPaths().get("/headers").get("get").getResponse(200);
-		assertObjectEquals("{foo:{type:'number'}}", x.getHeaders());
+	public void sa05a_Response_onPojo_value() throws Exception {
+		ResponseInfo x = getSwagger(new SA()).getPaths().get("/sa05a").get("get").getResponse(100);
+		assertEquals("Continue", x.getDescription());
+	}
+	@Test
+	public void sa05b_Response_onPojo_value() throws Exception {
+		ResponseInfo x = getSwagger(new SA()).getPaths().get("/sa05b").get("get").getResponse(100);
+		assertEquals("Continue", x.getDescription());
+	}
+	@Test
+	public void sa06a_Response_onPojo_headers() throws Exception {
+		ResponseInfo x = getSwagger(new SA()).getPaths().get("/sa06a").get("get").getResponse(200);
+		assertObjectEquals("{foo:{type:'b'}}", x.getHeaders());
+	}
+	@Test
+	public void sa06b_Response_onPojo_headers() throws Exception {
+		ResponseInfo x = getSwagger(new SA()).getPaths().get("/sa06b").get("get").getResponse(200);
+		assertObjectEquals("{foo:{type:'b'}}", x.getHeaders());
 	}
 
 	//-----------------------------------------------------------------------------------------------------------------
@@ -813,47 +651,79 @@ public class ResponseAnnotationTest {
 	//-----------------------------------------------------------------------------------------------------------------
 
 	@RestResource
-	public static class TB {
+	public static class SB {
 
-		public static class TB01 {}
-		@RestMethod(name=GET,path="/schemaValue")
-		public void tb01(@Response(schema=@Schema(" type:'number' ")) TB01 r) {}
+		@Response(schema=@Schema(" type:'number' "))
+		public static class SB01 {}
+		@RestMethod
+		public void sb01a(Value<SB01> r) {}
+		@RestMethod
+		public SB01 sb01b() {return null;}
 
-		public static class TB02 {
+		@Response
+		public static class SB02 {
 			public String f1;
 		}
-		@RestMethod(name=GET,path="/autoDetectBean")
-		public void tb02(@Response TB02 b) {}
+		@RestMethod
+		public void sb02a(Value<SB02> b) {}
+		@RestMethod
+		public SB02 sb02b() {return null;}
 
-		public static class TB03 extends LinkedList<String> {
+		@Response
+		public static class SB03 extends LinkedList<String> {
 			private static final long serialVersionUID = 1L;
 		}
-		@RestMethod(name=GET,path="/autoDetectList")
-		public void tb03(@Response TB03 b) {}
+		@RestMethod
+		public void sb03a(Value<SB03> b) {}
+		@RestMethod
+		public SB03 sb03b() {return null;}
 
-		public static class TB04 {}
-		@RestMethod(name=GET,path="/autoDetectStringObject")
-		public void tb04(@Response TB04 b) {}
+		@Response
+		public static class SB04 {}
+		@RestMethod
+		public void sb04a(Value<SB04> b) {}
+		@RestMethod
+		public SB04 sb04b() {return null;}
 	}
 
 	@Test
-	public void tb01_Response_onParameter_schemaValue() throws Exception {
-		ResponseInfo x = getSwagger(new TB()).getPaths().get("/schemaValue").get("get").getResponse(200);
+	public void sb01a_Response_onPojo_schemaValue() throws Exception {
+		ResponseInfo x = getSwagger(new SB()).getPaths().get("/sb01a").get("get").getResponse(200);
+		assertObjectEquals("{type:'number'}", x.getSchema());
+	}
+	@Test
+	public void sb01b_Response_onPojo_schemaValue() throws Exception {
+		ResponseInfo x = getSwagger(new SB()).getPaths().get("/sb01b").get("get").getResponse(200);
 		assertObjectEquals("{type:'number'}", x.getSchema());
 	}
 	@Test
-	public void tb02_Response_onParameter_autoDetectBean() throws Exception {
-		ResponseInfo x = getSwagger(new TB()).getPaths().get("/autoDetectBean").get("get").getResponse(200);
+	public void sb02a_Response_onPojo_autoDetectBean() throws Exception {
+		ResponseInfo x = getSwagger(new SB()).getPaths().get("/sb02a").get("get").getResponse(200);
 		assertObjectEquals("{type:'object',properties:{f1:{type:'string'}}}", x.getSchema());
 	}
 	@Test
-	public void tb03_Response_onParameter_autoDetectList() throws Exception {
-		ResponseInfo x = getSwagger(new TB()).getPaths().get("/autoDetectList").get("get").getResponse(200);
+	public void sb02b_Response_onPojo_autoDetectBean() throws Exception {
+		ResponseInfo x = getSwagger(new SB()).getPaths().get("/sb02b").get("get").getResponse(200);
+		assertObjectEquals("{type:'object',properties:{f1:{type:'string'}}}", x.getSchema());
+	}
+	@Test
+	public void sb03a_Response_onPojo_autoDetectList() throws Exception {
+		ResponseInfo x = getSwagger(new SB()).getPaths().get("/sb03a").get("get").getResponse(200);
+		assertObjectEquals("{type:'array',items:{type:'string'}}", x.getSchema());
+	}
+	@Test
+	public void sb03b_Response_onPojo_autoDetectList() throws Exception {
+		ResponseInfo x = getSwagger(new SB()).getPaths().get("/sb03b").get("get").getResponse(200);
 		assertObjectEquals("{type:'array',items:{type:'string'}}", x.getSchema());
 	}
 	@Test
-	public void tb04_Response_onParameter_autoDetectStringObject() throws Exception {
-		ResponseInfo x = getSwagger(new TB()).getPaths().get("/autoDetectStringObject").get("get").getResponse(200);
+	public void sb04a_Response_onPojo_autoDetectStringObject() throws Exception {
+		ResponseInfo x = getSwagger(new SB()).getPaths().get("/sb04a").get("get").getResponse(200);
+		assertObjectEquals("{type:'string'}", x.getSchema());
+	}
+	@Test
+	public void sb04b_Response_onPojo_autoDetectStringObject() throws Exception {
+		ResponseInfo x = getSwagger(new SB()).getPaths().get("/sb04b").get("get").getResponse(200);
 		assertObjectEquals("{type:'string'}", x.getSchema());
 	}
 
@@ -862,25 +732,41 @@ public class ResponseAnnotationTest {
 	//-----------------------------------------------------------------------------------------------------------------
 
 	@RestResource
-	public static class TC {
+	public static class SC {
 
-		public static class TC01 {}
-		@RestMethod(name=GET,path="/example")
-		public void tc01(@Response(example=" {f1:'b'} ") TC01 r) {}
+		@Response(example="{f1:'a'}")
+		public static class SC01 {}
+		@RestMethod
+		public void sc01a(Value<SC01> r) {}
+		@RestMethod
+		public SC01 sc01b() {return null;}
 
-		public static class TC02 {}
-		@RestMethod(name=GET,path="/examples")
-		public void tc02(@Response(examples={" foo:'b' "}) TC02 r) {}
+		@Response(examples={" foo:'b' "})
+		public static class SC02 {}
+		@RestMethod
+		public void sc02a(Value<SC02> r) {}
+		@RestMethod
+		public SC02 sc02b() {return null;}
 	}
 
 	@Test
-	public void tc01_Response_onParameter_example() throws Exception {
-		ResponseInfo x = getSwagger(new TC()).getPaths().get("/example").get("get").getResponse(200);
-		assertObjectEquals("{f1:'b'}", x.getExample());
+	public void sc01a_Response_onPojo_example() throws Exception {
+		ResponseInfo x = getSwagger(new SC()).getPaths().get("/sc01a").get("get").getResponse(200);
+		assertObjectEquals("{f1:'a'}", x.getExample());
+	}
+	@Test
+	public void sc01b_Response_onPojo_example() throws Exception {
+		ResponseInfo x = getSwagger(new SC()).getPaths().get("/sc01b").get("get").getResponse(200);
+		assertObjectEquals("{f1:'a'}", x.getExample());
 	}
 	@Test
-	public void tc02_Response_onParameter_examples() throws Exception {
-		ResponseInfo x = getSwagger(new TC()).getPaths().get("/examples").get("get").getResponse(200);
+	public void sc02a_Response_onPojo_examples() throws Exception {
+		ResponseInfo x = getSwagger(new SC()).getPaths().get("/sc02a").get("get").getResponse(200);
+		assertObjectEquals("{foo:'b'}", x.getExamples());
+	}
+	@Test
+	public void sc02b_Response_onPojo_examples() throws Exception {
+		ResponseInfo x = getSwagger(new SC()).getPaths().get("/sc02b").get("get").getResponse(200);
 		assertObjectEquals("{foo:'b'}", x.getExamples());
 	}
 
@@ -977,7 +863,7 @@ public class ResponseAnnotationTest {
 		ResponseInfo x = getSwagger(new UA()).getPaths().get("/mixed").get("get").getResponse(500);
 		assertEquals("a\nb", x.getDescription());
 		assertObjectEquals("{type:'string'}", x.getSchema());
-		assertObjectEquals("{foo:{type:'string'}}", x.getHeaders());
+		assertObjectEquals("{bar:{type:'number'},foo:{type:'string'}}", x.getHeaders());
 		assertObjectEquals("'a'", x.getExample());
 		assertObjectEquals("{foo:'a'}", x.getExamples());
 	}
diff --git a/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/annotation/ResponseHeaderAnnotationTest.java b/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/annotation/ResponseHeaderAnnotationTest.java
index 56ff096..fde13b3 100644
--- a/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/annotation/ResponseHeaderAnnotationTest.java
+++ b/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/annotation/ResponseHeaderAnnotationTest.java
@@ -14,8 +14,8 @@ package org.apache.juneau.rest.annotation;
 
 import static org.apache.juneau.http.HttpMethodName.*;
 import static org.junit.Assert.*;
-import static org.junit.Assert.assertEquals;
 
+import org.apache.juneau.*;
 import org.apache.juneau.dto.swagger.*;
 import org.apache.juneau.http.annotation.*;
 import org.apache.juneau.rest.*;
@@ -26,8 +26,8 @@ import org.junit.runners.*;
 /**
  * Tests related to @ResponseHeader annotation.
  */
-@SuppressWarnings("javadoc")
 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
+@SuppressWarnings("javadoc")
 public class ResponseHeaderAnnotationTest {
 
 	//=================================================================================================================
@@ -42,6 +42,47 @@ public class ResponseHeaderAnnotationTest {
 	}
 
 	//=================================================================================================================
+	// Basic tests
+	//=================================================================================================================
+
+	@RestResource
+	public static class A {
+		@RestMethod
+		public void a01(Value<A01> h) {
+			h.set(new A01());
+		}
+		@RestMethod
+		public void a02(@ResponseHeader(name="Foo") Value<String> h) {
+			h.set("foo");
+		}
+		@RestMethod
+		public void a03(@ResponseHeader(name="Bar") Value<A01> h) {
+			h.set(new A01());
+		}
+	}
+
+	@ResponseHeader(name="Foo")
+	public static class A01 {
+		@Override
+		public String toString() {return "foo";}
+	}
+
+	static MockRest a = MockRest.create(A.class,true);
+
+	@Test
+	public void a01_valueOnParameterPojo() throws Exception {
+		a.get("/a01").execute().assertStatus(200).assertHeader("Foo", "foo");
+	}
+	@Test
+	public void a02_valueOnParameterString() throws Exception {
+		a.get("/a02").execute().assertStatus(200).assertHeader("Foo", "foo");
+	}
+	@Test
+	public void a03_valueOnParameterOverrideName() throws Exception {
+		a.get("/a03").execute().assertStatus(200).assertHeader("Bar", "foo");
+	}
+
+	//=================================================================================================================
 	// @ResponseHeader on POJO
 	//=================================================================================================================
 
@@ -55,7 +96,7 @@ public class ResponseHeaderAnnotationTest {
 		)
 		public static class SA01 {}
 		@RestMethod(name=GET,path="/basic")
-		public void sa01(SA01 h) {}
+		public void sa01(Value<SA01> h) {}
 
 		@ResponseHeader(
 			name="H",
@@ -66,7 +107,7 @@ public class ResponseHeaderAnnotationTest {
 		)
 		public static class SA02 {}
 		@RestMethod(name=GET,path="/api")
-		public void sa02(SA02 h) {}
+		public void sa02(Value<SA02> h) {}
 
 		@ResponseHeader(
 			name="H",
@@ -79,27 +120,27 @@ public class ResponseHeaderAnnotationTest {
 		)
 		public static class SA03 {}
 		@RestMethod(name=GET,path="/mixed")
-		public void sa03(SA03 h) {}
+		public void sa03(Value<SA03> h) {}
 
 		@ResponseHeader(name="H", code=100)
 		public static class SA04 {}
 		@RestMethod(name=GET,path="/code")
-		public void sa04(SA04 h) {}
+		public void sa04(Value<SA04> h) {}
 
 		@ResponseHeader(name="H", code={100,101})
 		public static class SA05 {}
 		@RestMethod(name=GET,path="/codes")
-		public void sa05(SA05 h) {}
+		public void sa05(Value<SA05> h) {}
 
 		@ResponseHeader(name="H", description="a")
 		public static class SA07 {}
 		@RestMethod(name=GET,path="/nocode")
-		public void sa07(SA07 h) {}
+		public void sa07(Value<SA07> h) {}
 
 		@ResponseHeader("H")
 		public static class SA08 {}
 		@RestMethod(name=GET,path="/value")
-		public void sa08(SA08 h) {}
+		public void sa08(Value<SA08> h) {}
 	}
 
 	@Test
@@ -156,7 +197,7 @@ public class ResponseHeaderAnnotationTest {
 				name="H",
 				description="a",
 				type="string"
-			) SB01 h) {}
+			) Value<SB01> h) {}
 
 		public static class SB02 {}
 		@RestMethod(name=GET,path="/api")
@@ -167,7 +208,7 @@ public class ResponseHeaderAnnotationTest {
 					"description:'a',",
 					"type:'string'"
 				}
-			) SB02 h) {}
+			) Value<SB02> h) {}
 
 		public static class SB03 {}
 		@RestMethod(name=GET,path="/mixed")
@@ -180,23 +221,23 @@ public class ResponseHeaderAnnotationTest {
 				},
 				description="a",
 				type="string"
-			) SB03 h) {}
+			) Value<SB03> h) {}
 
 		public static class SB04 {}
 		@RestMethod(name=GET,path="/code")
-		public void sb04(@ResponseHeader(name="H", code=100) SB04 h) {}
+		public void sb04(@ResponseHeader(name="H", code=100) Value<SB04> h) {}
 
 		public static class SB05 {}
 		@RestMethod(name=GET,path="/codes")
-		public void sb05(@ResponseHeader(name="H", code={100,101}) SB05 h) {}
+		public void sb05(@ResponseHeader(name="H", code={100,101}) Value<SB05> h) {}
 
 		public static class SB07 {}
 		@RestMethod(name=GET,path="/nocode")
-		public void sb07(@ResponseHeader(name="H", description="a") SB07 h) {}
+		public void sb07(@ResponseHeader(name="H", description="a") Value<SB07> h) {}
 
 		public static class SB08 {}
 		@RestMethod(name=GET,path="/value")
-		public void sb08(@ResponseHeader("H") SB08 h) {}
+		public void sb08(@ResponseHeader("H") Value<SB08> h) {}
 	}
 
 	@Test
diff --git a/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/annotation/ResponseStatusAnnotationTest.java b/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/annotation/ResponseStatusAnnotationTest.java
index 19aab14..81d8344 100644
--- a/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/annotation/ResponseStatusAnnotationTest.java
+++ b/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/annotation/ResponseStatusAnnotationTest.java
@@ -12,143 +12,35 @@
 // ***************************************************************************************************************************
 package org.apache.juneau.rest.annotation;
 
-import static org.apache.juneau.http.HttpMethodName.*;
-import static org.junit.Assert.assertEquals;
-
-import org.apache.juneau.dto.swagger.*;
+import org.apache.juneau.*;
 import org.apache.juneau.http.annotation.*;
-import org.apache.juneau.rest.*;
 import org.apache.juneau.rest.mock.*;
 import org.junit.*;
 import org.junit.runners.*;
 
 /**
- * Tests related to @ResponseStatuses annotation.
+ * Tests related to @ResponseStatus annotation.
  */
-@SuppressWarnings("javadoc")
 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
+@SuppressWarnings("javadoc")
 public class ResponseStatusAnnotationTest {
 
 	//=================================================================================================================
-	// Setup
-	//=================================================================================================================
-
-	private static Swagger getSwagger(Object resource) throws Exception {
-		RestContext rc = RestContext.create(resource).build();
-		RestRequest req = rc.getCallHandler().createRequest(new MockServletRequest());
-		RestInfoProvider ip = rc.getInfoProvider();
-		return ip.getSwagger(req);
-	}
-
-	//=================================================================================================================
-	// @ResponseStatuses on POJO
+	// Basic tests
 	//=================================================================================================================
 
 	@RestResource
-	public static class SA {
-		@ResponseStatuses({
-			@ResponseStatus(code=100),
-			@ResponseStatus(code=101)
-		})
-		public static class SA01 {}
-
-		@RestMethod(name=GET,path="/code")
-		public void sa01(SA01 r) {}
-
-		@ResponseStatuses({
-			@ResponseStatus(100),
-			@ResponseStatus(101)
-		})
-		public static class SA02 {}
-
-		@RestMethod(name=GET,path="/salue")
-		public void sa02(SA02 r) {}
-
-		@ResponseStatuses({
-			@ResponseStatus(code=100, description="a"),
-			@ResponseStatus(code=101, description="a\nb")
-		})
-		public static class SA03 {}
-
-		@RestMethod(name=GET,path="/description")
-		public void sa03(SA03 r) {}
-	}
-
-	@Test
-	public void sa01_ResponseStatus_onPojo_code() throws Exception {
-		Operation x = getSwagger(new SA()).getPaths().get("/code").get("get");
-		assertEquals("Continue", x.getResponse(100).getDescription());
-		assertEquals("Switching Protocols", x.getResponse(101).getDescription());
-	}
-	@Test
-	public void sa02_ResponseStatus_onPojo_salue() throws Exception {
-		Operation x = getSwagger(new SA()).getPaths().get("/salue").get("get");
-		assertEquals("Continue", x.getResponse(100).getDescription());
-		assertEquals("Switching Protocols", x.getResponse(101).getDescription());
-	}
-	@Test
-	public void sa03_ResponseStatus_onPojo_description() throws Exception {
-		Operation x = getSwagger(new SA()).getPaths().get("/description").get("get");
-		assertEquals("a", x.getResponse(100).getDescription());
-		assertEquals("a\nb", x.getResponse(101).getDescription());
+	public static class A {
+		@RestMethod
+		public void a01(@ResponseStatus Value<Integer> status) {
+			status.set(100);
+		}
 	}
 
-	//=================================================================================================================
-	// @ResponseStatuses on parameter
-	//=================================================================================================================
-
-	@RestResource
-	public static class SB {
-		public static class SB01 {}
-
-		@RestMethod(name=GET,path="/code")
-		public void sb01(
-				@ResponseStatuses({
-					@ResponseStatus(code=100),
-					@ResponseStatus(code=101)
-				})
-				SB01 r
-			) {}
-
-		public static class SB02 {}
+	static MockRest a = MockRest.create(A.class);
 
-		@RestMethod(name=GET,path="/salue")
-		public void sb02(
-				@ResponseStatuses({
-					@ResponseStatus(100),
-					@ResponseStatus(101)
-				})
-				SB02 r
-			) {}
-
-		public static class SB03 {}
-
-		@RestMethod(name=GET,path="/description")
-		public void sb03(
-				@ResponseStatuses({
-					@ResponseStatus(code=100, description="a"),
-					@ResponseStatus(code=101, description="a\nb")
-				})
-				SB03 r
-			) {}
-	}
-
-	@Test
-	public void sb01_ResponseStatus_onParameter_code() throws Exception {
-		Operation x = getSwagger(new SB()).getPaths().get("/code").get("get");
-		assertEquals("Continue", x.getResponse(100).getDescription());
-		assertEquals("Switching Protocols", x.getResponse(101).getDescription());
-	}
-	@Test
-	public void sb02_ResponseStatus_onParameter_sblue() throws Exception {
-		Operation x = getSwagger(new SB()).getPaths().get("/salue").get("get");
-		assertEquals("Continue", x.getResponse(100).getDescription());
-		assertEquals("Switching Protocols", x.getResponse(101).getDescription());
-	}
 	@Test
-	public void sb03_ResponseStatus_onParameter_description() throws Exception {
-		Operation x = getSwagger(new SB()).getPaths().get("/description").get("get");
-		assertEquals("a", x.getResponse(100).getDescription());
-		assertEquals("a\nb", x.getResponse(101).getDescription());
+	public void a01() throws Exception {
+		a.get("/a01").execute().assertStatus(100);
 	}
 }