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/04/22 23:07:51 UTC

[juneau] branch master updated: Swagger improvements.

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 8e8716d  Swagger improvements.
8e8716d is described below

commit 8e8716d46751e3337e7e71088894d708193af1d3
Author: JamesBognar <ja...@apache.org>
AuthorDate: Sun Apr 22 19:07:34 2018 -0400

    Swagger improvements.
---
 .../org/apache/juneau/dto/swagger/HeaderInfo.java  |  83 ++-
 .../org/apache/juneau/dto/swagger/ui/SwaggerUI.css |   2 +-
 .../org/apache/juneau/internal/ObjectUtils.java    |  27 +
 .../main/java/org/apache/juneau/utils/Value.java   |  83 ++-
 .../org/apache/juneau/utils/ValueListener.java     |  20 +-
 juneau-doc/src/main/javadoc/overview.html          |   2 +-
 .../files/htdocs/styles/SwaggerUI.css              |   2 +-
 .../examples/rest/SystemPropertiesResource.java    |   2 +-
 .../juneau/examples/rest/petstore/IdConflict.java  |   2 +-
 .../juneau/examples/rest/petstore/IdNotFound.java  |   2 +-
 .../juneau/examples/rest/petstore/InvalidId.java   |   2 +-
 .../examples/rest/petstore/InvalidLogin.java       |   2 +-
 .../examples/rest/petstore/InvalidSpecies.java     |   2 +-
 .../juneau/examples/rest/petstore/InvalidTag.java  |   2 +-
 .../examples/rest/petstore/InvalidUsername.java    |   2 +-
 .../examples/rest/petstore/PetStoreResource.java   |  20 +-
 .../microservice/resources/ConfigResource.java     |   4 +-
 .../microservice/resources/DirectoryResource.java  |   8 +-
 .../microservice/resources/LogsResource.java       |   8 +-
 .../apache/juneau/rest/BasicRestCallHandler.java   |   6 +-
 .../apache/juneau/rest/BasicRestInfoProvider.java  |  56 +-
 .../java/org/apache/juneau/rest/RestContext.java   |  49 +-
 .../org/apache/juneau/rest/RestMethodReturn.java   |   5 +-
 .../org/apache/juneau/rest/RestMethodThrown.java   |   5 +-
 .../org/apache/juneau/rest/RestParamDefaults.java  | 236 +++++-
 .../java/org/apache/juneau/rest/RestParamType.java |   9 +
 .../org/apache/juneau/rest/annotation/Body.java    |  20 +-
 .../apache/juneau/rest/annotation/FormData.java    |   2 +-
 .../apache/juneau/rest/annotation/HasFormData.java |   2 +-
 .../apache/juneau/rest/annotation/HasQuery.java    |   2 +-
 .../org/apache/juneau/rest/annotation/Header.java  |   4 +-
 .../org/apache/juneau/rest/annotation/Path.java    |   2 +-
 .../org/apache/juneau/rest/annotation/Query.java   |   2 +-
 .../{ResponseInfo.java => Response.java}           |  31 +-
 .../{Header.java => ResponseHeader.java}           | 823 +++++++++++----------
 .../ResponseStatus.java}                           |  31 +-
 .../juneau/rest/annotation/ResponseStatuses.java   |  58 +-
 .../apache/juneau/rest/annotation/Responses.java   |  58 +-
 .../apache/juneau/rest/exception/BadRequest.java   |   2 +-
 .../org/apache/juneau/rest/exception/Conflict.java |   2 +-
 .../juneau/rest/exception/ExpectationFailed.java   |   2 +-
 .../juneau/rest/exception/FailedDependency.java    |   2 +-
 .../apache/juneau/rest/exception/Forbidden.java    |   2 +-
 .../org/apache/juneau/rest/exception/Gone.java     |   2 +-
 .../rest/exception/HttpVersionNotSupported.java    |   2 +-
 .../juneau/rest/exception/InsufficientStorage.java |   2 +-
 .../juneau/rest/exception/InternalServerError.java |   2 +-
 .../juneau/rest/exception/LengthRequired.java      |   2 +-
 .../org/apache/juneau/rest/exception/Locked.java   |   2 +-
 .../apache/juneau/rest/exception/LoopDetected.java |   2 +-
 .../juneau/rest/exception/MethodNotAllowed.java    |   2 +-
 .../juneau/rest/exception/MisdirectedRequest.java  |   2 +-
 .../exception/NetworkAuthenticationRequired.java   |   2 +-
 .../juneau/rest/exception/NotAcceptable.java       |   2 +-
 .../apache/juneau/rest/exception/NotExtended.java  |   2 +-
 .../org/apache/juneau/rest/exception/NotFound.java |   2 +-
 .../juneau/rest/exception/NotImplemented.java      |   2 +-
 .../juneau/rest/exception/PayloadTooLarge.java     |   2 +-
 .../juneau/rest/exception/PreconditionFailed.java  |   2 +-
 .../rest/exception/PreconditionRequired.java       |   2 +-
 .../juneau/rest/exception/RangeNotSatisfiable.java |   2 +-
 .../exception/RequestHeaderFieldsTooLarge.java     |   2 +-
 .../juneau/rest/exception/ServiceUnavailable.java  |   2 +-
 .../juneau/rest/exception/TooManyRequests.java     |   2 +-
 .../apache/juneau/rest/exception/Unauthorized.java |   2 +-
 .../rest/exception/UnavailableForLegalReasons.java |   2 +-
 .../juneau/rest/exception/UnprocessableEntity.java |   2 +-
 .../rest/exception/UnsupportedMediaType.java       |   2 +-
 .../juneau/rest/exception/UpgradeRequired.java     |   2 +-
 .../apache/juneau/rest/exception/UriTooLong.java   |   2 +-
 .../rest/exception/VariantAlsoNegotiates.java      |   2 +-
 .../java/org/apache/juneau/rest/helper/Ok.java     |   2 +-
 .../org/apache/juneau/rest/helper/Redirect.java    |   2 +-
 .../juneau/rest/helper/RedirectToServletRoot.java  |   2 +-
 .../juneau/rest/helper/ResourceDescription.java    |   2 +-
 75 files changed, 1067 insertions(+), 683 deletions(-)

diff --git a/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/swagger/HeaderInfo.java b/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/swagger/HeaderInfo.java
index e4316fa..0c09d04 100644
--- a/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/swagger/HeaderInfo.java
+++ b/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/swagger/HeaderInfo.java
@@ -49,7 +49,7 @@ import org.apache.juneau.utils.*;
  * 	<li class='link'><a class='doclink' href='../../../../../overview-summary.html#juneau-dto.Swagger'>Overview &gt; juneau-dto &gt; Swagger</a>
  * </ul>
  */
-@Bean(properties="description,type,format,items,collectionFormat,default,maximum,exclusiveMaximum,minimum,exclusiveMinimum,maxLength,minLength,pattern,maxItems,minItems,uniqueItems,enum,multipleOf,$ref,*")
+@Bean(properties="description,type,format,items,collectionFormat,default,maximum,exclusiveMaximum,minimum,exclusiveMinimum,maxLength,minLength,pattern,maxItems,minItems,uniqueItems,enum,multipleOf,$ref,x-examples,*")
 @SuppressWarnings({"unchecked"})
 public class HeaderInfo extends SwaggerElement {
 
@@ -79,6 +79,7 @@ public class HeaderInfo extends SwaggerElement {
 	private Items items;
 	private Object _default;
 	private List<Object> _enum;
+	private Map<String,String> examples;
 	
 	/**
 	 * Default constructor.
@@ -111,6 +112,10 @@ public class HeaderInfo extends SwaggerElement {
 		this._default = copyFrom._default;
 		this.items = copyFrom.items == null ? null : copyFrom.items.copy();
 		this._enum = newList(copyFrom._enum);
+		
+		this.examples = copyFrom.examples == null ? null : new LinkedHashMap<String,String>();
+		if (copyFrom.examples != null)
+			this.examples.putAll(copyFrom.examples);
 	}
 	
 	/**
@@ -1053,6 +1058,77 @@ public class HeaderInfo extends SwaggerElement {
 		return setRef(value);
 	}
 
+	/**
+	 * Bean property getter:  <property>x-examples</property>.
+	 * 
+	 * @return The property value, or <jk>null</jk> if it is not set.
+	 */
+	@BeanProperty("x-examples")
+	public Map<String,String> getExamples() {
+		return examples;
+	}
+
+	/**
+	 * Bean property setter:  <property>examples</property>.
+	 * 
+	 * @param value 
+	 * 	The new value for this property.
+	 * 	<br>Can be <jk>null</jk> to unset the property.
+	 * @return This object (for method chaining).
+	 */
+	@BeanProperty("x-examples")
+	public HeaderInfo setExamples(Map<String,String> value) {
+		examples = newMap(value);
+		return this;
+	}
+
+	/**
+	 * Adds one or more values to the <property>examples</property> property.
+	 * 
+	 * @param values
+	 * 	The values to add to this property.
+	 * 	<br>Ignored if <jk>null</jk>.
+	 * @return This object (for method chaining).
+	 */
+	public HeaderInfo addExamples(Map<String,String> values) {
+		examples = addToMap(examples, values);
+		return this;
+	}
+
+	/**
+	 * Adds a single value to the <property>examples</property> property.
+	 * 
+	 * @param name The extra property name.
+	 * @param value The extra property value.
+	 * @return This object (for method chaining).
+	 */
+	public HeaderInfo example(String name, String value) {
+		examples = addToMap(examples, name, value);
+		return this;
+	}
+
+	/**
+	 * Adds one or more values to the <property>examples</property> property.
+	 * 
+	 * @param values
+	 * 	The values to add to this property.
+	 * 	<br>Valid types:
+	 * 	<ul>
+	 * 		<li><code>Map&lt;String,String&gt;</code>
+	 * 		<li><code>String</code> - JSON object representation of <code>Map&lt;String,Object&gt;</code>
+	 * 			<h5 class='figure'>Example:</h5>
+	 * 			<p class='bcode'>
+	 * 	examples(<js>"{'text/json':'{foo:\\'bar\\'}'}"</js>);
+	 * 			</p>
+	 * 	</ul>
+	 * 	<br>Ignored if <jk>null</jk>.
+	 * @return This object (for method chaining).
+	 */
+	public HeaderInfo examples(Object...values) {
+		examples = addToMap(examples, values, String.class, String.class);
+		return this;
+	}
+
 	@Override /* SwaggerElement */
 	public <T> T get(String property, Class<T> type) {
 		if (property == null)
@@ -1077,6 +1153,7 @@ public class HeaderInfo extends SwaggerElement {
 			case "uniqueItems": return toType(getUniqueItems(), type);
 			case "enum": return toType(getEnum(), type);
 			case "multipleOf": return toType(getMultipleOf(), type);
+			case "x-examples": return toType(getExamples(), type);
 			default: return super.get(property, type);
 		}
 	}
@@ -1105,6 +1182,7 @@ public class HeaderInfo extends SwaggerElement {
 			case "uniqueItems": return uniqueItems(value);
 			case "enum": return setEnum(null)._enum(value);
 			case "multipleOf": return multipleOf(value);
+			case "x-examples": return examples(value);
 			default: 
 				super.set(property, value);
 				return this;
@@ -1132,7 +1210,8 @@ public class HeaderInfo extends SwaggerElement {
 			.appendIf(minItems != null, "minItems")
 			.appendIf(uniqueItems != null, "uniqueItems")
 			.appendIf(_enum != null, "enum")
-			.appendIf(multipleOf != null, "multipleOf");
+			.appendIf(multipleOf != null, "multipleOf")
+			.appendIf(examples != null, "x-examples");
 		return new MultiSet<>(s, super.keySet());
 		
 	}
diff --git a/juneau-core/juneau-dto/src/main/resources/org/apache/juneau/dto/swagger/ui/SwaggerUI.css b/juneau-core/juneau-dto/src/main/resources/org/apache/juneau/dto/swagger/ui/SwaggerUI.css
index b118da2..e1c8a21 100644
--- a/juneau-core/juneau-dto/src/main/resources/org/apache/juneau/dto/swagger/ui/SwaggerUI.css
+++ b/juneau-core/juneau-dto/src/main/resources/org/apache/juneau/dto/swagger/ui/SwaggerUI.css
@@ -332,7 +332,7 @@ div.headers {
 }
 
 .section-table {
-	display: inline-block;
+/*	display: inline-block;*/
 }
 
 .responses .section-table td {
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/ObjectUtils.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/ObjectUtils.java
index 98adf11..9ac2f32 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/ObjectUtils.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/ObjectUtils.java
@@ -309,4 +309,31 @@ public final class ObjectUtils {
 	public static Enum<?>[] getEnumConstants(Class<?> c) {
 		return ((Class<Enum<?>>)c).getEnumConstants();
 	}
+	
+	/**
+	 * If the specified object is an instance of the specified class, casts it to that type.
+	 * 
+	 * @param o The object to cast.
+	 * @param c The class to cast to.
+	 * @return The cast object, or <jk>null</jk> if the object wasn't an instance of the specified class.
+	 */
+	@SuppressWarnings("unchecked")
+	public static <T> T castOrNull(Object o, Class<T> c) {
+		if (c.isInstance(o))
+			return (T)o;
+		return null;
+	}
+	
+	/**
+	 * Returns the first non-zero value in the list of ints.
+	 * 
+	 * @param ints The ints to check.
+	 * @return The first non-zero value, or <code>0</code> if they were all zero.
+	 */
+	public static int firstNonZero(int...ints) {
+		for (int i : ints)
+			if (i != 0)
+				return i;
+		return 0;
+	}
 }
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/ResponseInfo.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/utils/Value.java
similarity index 60%
copy from juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/ResponseInfo.java
copy to juneau-core/juneau-marshall/src/main/java/org/apache/juneau/utils/Value.java
index 3c300b9..452d8ac 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/ResponseInfo.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/utils/Value.java
@@ -10,56 +10,75 @@
 // * "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.annotation;
-
-import static java.lang.annotation.ElementType.*;
-import static java.lang.annotation.RetentionPolicy.*;
-
-import java.lang.annotation.*;
+package org.apache.juneau.utils;
 
 /**
- * Annotation that can be applied to exceptions and return types that identify the HTTP status they trigger and a description about the exception.
+ * Represents a simple settable value.
+ * 
+ * <p>
+ * This object is not thread safe.
+ * 
+ * @param <T> The value type.
  */
-@Documented
-@Target(TYPE)
-@Retention(RUNTIME)
-@Inherited
-public @interface ResponseInfo {
+public class Value<T> {
+
+	private T t;
+	private ValueListener<T> listener;
 	
 	/**
-	 * The HTTP status of the response.
+	 * Constructor.
 	 */
-	int code() default 0;
-	
+	public Value() {
+	}
+
 	/**
-	 * Description.
+	 * Constructor.
 	 * 
-	 * <p>
-	 * Format is plain text.
+	 * @param t Initial value.
 	 */
-	String description() default "";
-
+	public Value(T t) {
+		set(t);
+	}
+	
 	/**
-	 * Schema information.
+	 * Adds a listener for this value.
 	 * 
-	 * <p>
-	 * Format is a JSON object consisting of a Swagger SchemaInfo object.
+	 * @param listener The new listener for this value.
+	 * @return This object (for method chaining).
 	 */
-	String[] schema() default {};
+	public Value<T> listener(ValueListener<T> listener) {
+		this.listener = listener;
+		return this;
+	}
 	
 	/**
-	 * Header information.
+	 * Sets the value.
 	 * 
-	 * <p>
-	 * Format is a JSON array consisting of Swagger HeaderInfo objects.
+	 * @param t The new value.
+	 * @return This object (for method chaining).
 	 */
-	String[] headers() default {};
+	public Value<T> set(T t) {
+		this.t = t;
+		if (listener != null)
+			listener.onSet(t);
+		return this;
+	}
 	
 	/**
-	 * Example.
+	 * Returns the value.
+	 * 
+	 * @return The value, or <jk>null</jk> if it is not set.
+	 */
+	public T get() {
+		return t;
+	}
+
+	/**
+	 * Returns <jk>true</jk> if the value is set.
 	 * 
-	 * <p>
-	 * Format is a JSON primitive, array, or object.
+	 * @return <jk>true</jk> if the value is set.
 	 */
-	String[] example() default {};
+	public boolean isSet() {
+		return get() != null;
+	}
 }
diff --git a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/InvalidSpecies.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/utils/ValueListener.java
similarity index 78%
copy from juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/InvalidSpecies.java
copy to juneau-core/juneau-marshall/src/main/java/org/apache/juneau/utils/ValueListener.java
index d856988..25fefa0 100644
--- a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/InvalidSpecies.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/utils/ValueListener.java
@@ -10,22 +10,18 @@
 // * "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.examples.rest.petstore;
-
-import org.apache.juneau.rest.annotation.*;
-import org.apache.juneau.rest.exception.*;
+package org.apache.juneau.utils;
 
 /**
- * Exception thrown when an invalid species is looked up.
+ * Simple listener for the {@link Value} class.
+ * @param <T> 
  */
-@SuppressWarnings("serial")
-@ResponseInfo(description="Invalid species provided")
-public class InvalidSpecies extends BadRequest {
+public interface ValueListener<T> {
 
 	/**
-	 * Constructor.
+	 * Called when {@link Value#set(Object)} is called.
+	 * 
+	 * @param newValue The new value.
 	 */
-	public InvalidSpecies() {
-		super("Invalid species provided.");
-	}
+	void onSet(T newValue);
 }
diff --git a/juneau-doc/src/main/javadoc/overview.html b/juneau-doc/src/main/javadoc/overview.html
index 8b37669..75f9ce4 100644
--- a/juneau-doc/src/main/javadoc/overview.html
+++ b/juneau-doc/src/main/javadoc/overview.html
@@ -21286,7 +21286,7 @@
 			<li>
 				Newlines were being stripped from <code><ja>@HtmlDoc</ja>(script)</code> when serialized which could cause script lines to become commented out.
 			<li>
-				New {@link org.apache.juneau.rest.annotation.ResponseInfo @ResponseInfo} annotation that can be applied to
+				New {@link org.apache.juneau.rest.annotation.Response @Response} and {@link org.apache.juneau.rest.annotation.Responses @Responses} annotations that can be applied to
 				throwables thrown from REST methods and POJOs returned by REST methods to specify non-200 status return codes and descriptions in Swagger documentation.
 			<li>
 				Swagger fields added to the following annotations:
diff --git a/juneau-examples/juneau-examples-rest/files/htdocs/styles/SwaggerUI.css b/juneau-examples/juneau-examples-rest/files/htdocs/styles/SwaggerUI.css
index b118da2..e1c8a21 100644
--- a/juneau-examples/juneau-examples-rest/files/htdocs/styles/SwaggerUI.css
+++ b/juneau-examples/juneau-examples-rest/files/htdocs/styles/SwaggerUI.css
@@ -332,7 +332,7 @@ div.headers {
 }
 
 .section-table {
-	display: inline-block;
+/*	display: inline-block;*/
 }
 
 .responses .section-table td {
diff --git a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/SystemPropertiesResource.java b/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/SystemPropertiesResource.java
index dc1faf2..e2fcf1e 100644
--- a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/SystemPropertiesResource.java
+++ b/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/SystemPropertiesResource.java
@@ -222,7 +222,7 @@ public class SystemPropertiesResource extends BasicRestServlet {
 	// Beans
 	//--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 	
-	@ResponseInfo( description="User is not an administrator.")
+	@Response(description="User is not an administrator.")
 	public static class UserNotAdminException extends Forbidden {
 		private static final long serialVersionUID = 1L;
 
diff --git a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/IdConflict.java b/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/IdConflict.java
index 7b1f07b..f7d5b37 100644
--- a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/IdConflict.java
+++ b/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/IdConflict.java
@@ -19,7 +19,7 @@ import org.apache.juneau.rest.exception.*;
  * Exception thrown when trying to add an entry where the ID is already in use.
  */
 @SuppressWarnings("serial")
-@ResponseInfo(description="ID already in use")
+@Response(description="ID already in use")
 public class IdConflict extends Conflict {
 
 	/**
diff --git a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/IdNotFound.java b/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/IdNotFound.java
index 6fd2e43..fc5c53c 100644
--- a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/IdNotFound.java
+++ b/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/IdNotFound.java
@@ -19,7 +19,7 @@ import org.apache.juneau.rest.exception.*;
  * Exception thrown when trying to add an entry where the ID is already in use.
  */
 @SuppressWarnings("serial")
-@ResponseInfo(description="ID not found")
+@Response(description="ID not found")
 public class IdNotFound extends NotFound {
 
 	/**
diff --git a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/InvalidId.java b/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/InvalidId.java
index 88848dd..0c1e430 100644
--- a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/InvalidId.java
+++ b/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/InvalidId.java
@@ -19,7 +19,7 @@ import org.apache.juneau.rest.exception.*;
  * Exception thrown when trying to add an entry where the ID is already in use.
  */
 @SuppressWarnings("serial")
-@ResponseInfo(description="Invalid ID provided")
+@Response(description="Invalid ID provided")
 public class InvalidId extends BadRequest {
 
 	/**
diff --git a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/InvalidLogin.java b/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/InvalidLogin.java
index 4fc42e4..2053b17 100644
--- a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/InvalidLogin.java
+++ b/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/InvalidLogin.java
@@ -19,7 +19,7 @@ import org.apache.juneau.rest.exception.*;
  * Exception thrown when an invalid username or password is provided.
  */
 @SuppressWarnings("serial")
-@ResponseInfo(description="Invalid username or password provided")
+@Response(description="Invalid username or password provided")
 public class InvalidLogin extends Unauthorized {
 	
 	/**
diff --git a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/InvalidSpecies.java b/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/InvalidSpecies.java
index d856988..d5f987d 100644
--- a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/InvalidSpecies.java
+++ b/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/InvalidSpecies.java
@@ -19,7 +19,7 @@ import org.apache.juneau.rest.exception.*;
  * Exception thrown when an invalid species is looked up.
  */
 @SuppressWarnings("serial")
-@ResponseInfo(description="Invalid species provided")
+@Response(description="Invalid species provided")
 public class InvalidSpecies extends BadRequest {
 
 	/**
diff --git a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/InvalidTag.java b/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/InvalidTag.java
index 3d1e4b2..3f3643c 100644
--- a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/InvalidTag.java
+++ b/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/InvalidTag.java
@@ -19,7 +19,7 @@ import org.apache.juneau.rest.exception.*;
  * Exception thrown when trying to add an entry where the ID is already in use.
  */
 @SuppressWarnings("serial")
-@ResponseInfo(description="Invalid tag provided")
+@Response(description="Invalid tag provided")
 public class InvalidTag extends BadRequest {
 
 	/**
diff --git a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/InvalidUsername.java b/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/InvalidUsername.java
index d830f82..c35fea5 100644
--- a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/InvalidUsername.java
+++ b/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/InvalidUsername.java
@@ -19,7 +19,7 @@ import org.apache.juneau.rest.exception.*;
  * Exception thrown when trying to add an entry where the ID is already in use.
  */
 @SuppressWarnings("serial")
-@ResponseInfo(description="Invalid username provided")
+@Response(description="Invalid username provided")
 public class InvalidUsername extends BadRequest {
 
 	/**
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 1ee8ba3..0c0773d 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
@@ -33,6 +33,7 @@ import org.apache.juneau.rest.exception.*;
 import org.apache.juneau.rest.helper.*;
 import org.apache.juneau.rest.widget.*;
 import org.apache.juneau.transforms.*;
+import org.apache.juneau.utils.*;
 import org.apache.juneau.rest.converters.*;
 
 /**
@@ -581,20 +582,14 @@ public class PetStoreResource extends BasicRestServletJena {
 		path="/user/login",
 		summary="Logs user into the system",
 		swagger=@MethodSwagger(
-			tags="user",
-			responses={
-				"200:{",
-					"headers:{",
-						"X-Rate-Limit:{ type:'integer', format:'int32', description:'calls per hour allowed by the user', 'x-example':123},",
-						"X-Expires-After:{ type:'string', format:'date-time', description:'date in UTC when token expires', 'x-example':'2012-10-21'}",
-					"}",
-				"}"
-			}
+			tags="user"
 		)
 	)
 	public Ok login(
 			@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,
 			RestRequest req, 
 			RestResponse res
 		) throws InvalidLogin, NotAcceptable {
@@ -604,10 +599,13 @@ public class PetStoreResource extends BasicRestServletJena {
 		
 		Date d = new Date(System.currentTimeMillis() + 30 * 60 * 1000);
 		req.getSession().setAttribute("login-expires", d);
-		res.setHeader("X-Rate-Limit", "1000");
-		res.setHeader("X-Expires-After", DateUtils.formatDate(d));
+		rateLimit.set(1000);
+		expiresAfter.set(DateUtils.formatDate(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> {}
 
 	@RestMethod(
 		name="GET", 
diff --git a/juneau-microservice/juneau-microservice-server/src/main/java/org/apache/juneau/microservice/resources/ConfigResource.java b/juneau-microservice/juneau-microservice-server/src/main/java/org/apache/juneau/microservice/resources/ConfigResource.java
index 5203a2b..40b476a 100755
--- a/juneau-microservice/juneau-microservice-server/src/main/java/org/apache/juneau/microservice/resources/ConfigResource.java
+++ b/juneau-microservice/juneau-microservice-server/src/main/java/org/apache/juneau/microservice/resources/ConfigResource.java
@@ -202,7 +202,7 @@ public class ConfigResource extends BasicRestServlet {
 	// Helper beans
 	//-----------------------------------------------------------------------------------------------------------------
 
-	@ResponseInfo(description="Section not found.")
+	@Response(description="Section not found.")
 	private class SectionNotFound extends NotFound {
 		private static final long serialVersionUID = 1L;
 
@@ -211,7 +211,7 @@ public class ConfigResource extends BasicRestServlet {
 		}
 	}
 	
-	@ResponseInfo(description="The configuration file contained syntax errors and could not be parsed.")
+	@Response(description="The configuration file contained syntax errors and could not be parsed.")
 	private class BadConfig extends InternalServerError {
 		private static final long serialVersionUID = 1L;
 
diff --git a/juneau-microservice/juneau-microservice-server/src/main/java/org/apache/juneau/microservice/resources/DirectoryResource.java b/juneau-microservice/juneau-microservice-server/src/main/java/org/apache/juneau/microservice/resources/DirectoryResource.java
index 732b108..870e0af 100755
--- a/juneau-microservice/juneau-microservice-server/src/main/java/org/apache/juneau/microservice/resources/DirectoryResource.java
+++ b/juneau-microservice/juneau-microservice-server/src/main/java/org/apache/juneau/microservice/resources/DirectoryResource.java
@@ -209,24 +209,24 @@ public class DirectoryResource extends BasicRestServlet {
 	// Helper beans
 	//-----------------------------------------------------------------------------------------------------------------
 
-	@ResponseInfo(schema="{schema:{type:'string',format:'binary'}}", description="Contents of file")
+	@Response(schema="{schema:{type:'string',format:'binary'}}", description="Contents of file")
 	static class FileContents extends FileInputStream {
 		public FileContents(File file) throws FileNotFoundException {
 			super(file);
 		}
 	}
 	
-	@ResponseInfo(description="Redirect to root page on success")
+	@Response(description="Redirect to root page on success")
 	static class RedirectToRoot extends RedirectToServletRoot {}
 
-	@ResponseInfo(description="File action")
+	@Response(description="File action")
 	public static class Action extends LinkString {
 		public Action(String name, String uri, Object...uriArgs) {
 			super(name, uri, uriArgs);
 		}
 	}
 
-	@ResponseInfo(description="File or directory details")
+	@Response(description="File or directory details")
 	@Bean(properties="type,name,size,lastModified,actions,files")
 	public class FileResource {
 		private final File f;
diff --git a/juneau-microservice/juneau-microservice-server/src/main/java/org/apache/juneau/microservice/resources/LogsResource.java b/juneau-microservice/juneau-microservice-server/src/main/java/org/apache/juneau/microservice/resources/LogsResource.java
index aa8c40d..fe1cf8e 100755
--- a/juneau-microservice/juneau-microservice-server/src/main/java/org/apache/juneau/microservice/resources/LogsResource.java
+++ b/juneau-microservice/juneau-microservice-server/src/main/java/org/apache/juneau/microservice/resources/LogsResource.java
@@ -249,24 +249,24 @@ public class LogsResource extends BasicRestServlet {
 	// Helper beans
 	//-----------------------------------------------------------------------------------------------------------------
 
-	@ResponseInfo(schema="{schema:{type:'string',format:'binary'}}", description="Contents of file")
+	@Response(schema="{schema:{type:'string',format:'binary'}}", description="Contents of file")
 	static class FileContents extends FileInputStream {
 		public FileContents(File file) throws FileNotFoundException {
 			super(file);
 		}
 	}
 	
-	@ResponseInfo(description="Redirect to root page on success")
+	@Response(description="Redirect to root page on success")
 	static class RedirectToRoot extends RedirectToServletRoot {}
 
-	@ResponseInfo(description="File action")
+	@Response(description="File action")
 	public static class Action extends LinkString {
 		public Action(String name, String uri, Object...uriArgs) {
 			super(name, uri, uriArgs);
 		}
 	}
 
-	@ResponseInfo(description="File or directory details")
+	@Response(description="File or directory details")
 	@Bean(properties="type,name,size,lastModified,actions,files")
 	public static class FileResource {
 		private final File f;
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/BasicRestCallHandler.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/BasicRestCallHandler.java
index 5077ae3..b0d007b 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/BasicRestCallHandler.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/BasicRestCallHandler.java
@@ -23,6 +23,7 @@ import java.util.*;
 import javax.servlet.*;
 import javax.servlet.http.*;
 
+import org.apache.juneau.internal.*;
 import org.apache.juneau.rest.annotation.*;
 import org.apache.juneau.rest.exception.*;
 import org.apache.juneau.rest.helper.*;
@@ -193,8 +194,9 @@ public class BasicRestCallHandler implements RestCallHandler {
 			r1.setAttribute("ExecTime", System.currentTimeMillis() - startTime);
 			handleError(r1, r2, e);
 		} catch (Throwable e) {
-			ResponseInfo ri = e.getClass().getAnnotation(ResponseInfo.class);
-			RestException e2 = new RestException(e, ri == null || ri.code() == 0 ? SC_INTERNAL_SERVER_ERROR : ri.code());
+			Response ri = e.getClass().getAnnotation(Response.class);
+			int code = ri == null ? SC_INTERNAL_SERVER_ERROR : ObjectUtils.firstNonZero(ri.code(), ri.value(), SC_INTERNAL_SERVER_ERROR);
+			RestException e2 = new RestException(e, code);
 			r1.setAttribute("Exception", e);
 			r1.setAttribute("ExecTime", System.currentTimeMillis() - startTime);
 			handleError(r1, r2, e2);
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 bdf6aea..3f8c4f2 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
@@ -326,7 +326,7 @@ public class BasicRestInfoProvider implements RestInfoProvider {
 				
 				RestParamType in = mp.getParamType();
 				
-				if (in == OTHER)
+				if (in == OTHER || in == RESPONSE || in == RESPONSE_HEADER || in == RESPONSE_STATUS)
 					continue;
 				
 				String key = in.toString() + '.' + (in == BODY ? null : mp.getName());
@@ -386,7 +386,7 @@ public class BasicRestInfoProvider implements RestInfoProvider {
 				}
 			}
 			
-			// Gather responses from @ResponseInfo-annotated exceptions.
+			// Gather responses from @Response-annotated exceptions.
 			for (RestMethodThrown rt : context.getRestMethodThrowns(m)) {
 				int code = rt.getCode();
 				if (code != 0) {
@@ -421,6 +421,58 @@ public class BasicRestInfoProvider implements RestInfoProvider {
 					responses.getObjectMap(key).appendIf(false, true, true, "description", RestUtils.getHttpResponseText(Integer.parseInt(key)));
 			}
 			
+			// Finally, look for @ResponseHeader parameters defined on method.
+			for (RestMethodParam mp : context.getRestMethodParams(m)) {
+				
+				RestParamType in = mp.getParamType();
+				
+				if (in == RESPONSE_HEADER) {
+					ObjectMap pi = mp.getMetaData();
+					String code = pi.getString("status", "200");  
+					String name = mp.getName();
+					
+					ObjectMap header = responses.getObjectMap(code, true).getObjectMap("headers", true).getObjectMap(name, true);
+
+					header.appendIf(false, true, true, "description", vr.resolve(pi.getString("description")));
+					header.appendIf(false, true, true, "type", vr.resolve(pi.getString("type")));
+					header.appendIf(false, true, true, "format", vr.resolve(pi.getString("format")));
+					header.appendIf(false, true, true, "collectionFormat", vr.resolve(pi.getString("collectionFormat")));
+					header.appendIf(false, true, true, "maximum", vr.resolve(pi.getString("maximum")));
+					header.appendIf(false, true, true, "minimum", vr.resolve(pi.getString("minimum")));
+					header.appendIf(false, true, true, "multipleOf", vr.resolve(pi.getString("multipleOf")));
+					header.appendIf(false, true, true, "maxLength", vr.resolve(pi.getString("maxLength")));
+					header.appendIf(false, true, true, "minLength", vr.resolve(pi.getString("minLength")));
+					header.appendIf(false, true, true, "maxItems", vr.resolve(pi.getString("maxItems")));
+					header.appendIf(false, true, true, "minItems", vr.resolve(pi.getString("minItems")));
+					header.appendIf(false, true, true, "exclusiveMaximum", vr.resolve(pi.getString("exclusiveMaximum")));
+					header.appendIf(false, true, true, "exclusiveMimimum", vr.resolve(pi.getString("exclusiveMimimum")));
+					header.appendIf(false, true, true, "uniqueItems", vr.resolve(pi.getString("uniqueItems")));
+					header.appendIf(false, true, true, "default", JsonParser.DEFAULT.parse(vr.resolve(pi.getString("default")), Object.class));
+					header.appendIf(false, true, true, "enum", parseList(pi.getString("enum"), vr, false, true, "ParameterInfo/enum on class {0} method {1}", c, m));
+					header.appendIf(false, true, true, "x-example", parseAnything(vr.resolve(pi.getString("example"))));
+					if (pi.containsKeyNotEmpty("items"))
+						header.appendIf(false, true, true, "items", new ObjectMap(vr.resolve(pi.getString("items"))));
+				
+				} else if (in == RESPONSE) {
+					ObjectMap pi = mp.getMetaData();
+					String code = pi.getString("status", "200");  
+					
+					ObjectMap response = responses.getObjectMap(code, true);
+					
+					response.appendIf(false, true, true, "description", vr.resolve(pi.getString("description")));
+					response.appendIf(false, true, true, "schema", vr.resolve(pi.getString("schema")));
+					response.appendIf(false, true, true, "x-example", parseAnything(vr.resolve(pi.getString("example"))));
+					
+				} else if (in == RESPONSE_STATUS) {
+					ObjectMap pi = mp.getMetaData();
+					String code = pi.getString("status", "200");  
+					
+					ObjectMap response = responses.getObjectMap(code, true);
+
+					response.appendIf(false, true, true, "description", vr.resolve(pi.getString("description")));
+				}
+			}
+			
 			if (responses.isEmpty())
 				op.remove("responses");
 			else
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 867e90b..b5ea4e8 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
@@ -17,6 +17,7 @@ import static org.apache.juneau.internal.ClassUtils.*;
 import static org.apache.juneau.internal.CollectionUtils.*;
 import static org.apache.juneau.internal.IOUtils.*;
 import static org.apache.juneau.internal.StringUtils.*;
+import static org.apache.juneau.internal.ObjectUtils.*;
 
 import java.io.*;
 import java.lang.annotation.*;
@@ -4274,25 +4275,65 @@ public final class RestContext extends BeanContext {
 				rp[i] = paramResolvers.get(c);
 				if (rp[i] == null)
 					rp[i] = RestParamDefaults.STANDARD_RESOLVERS.get(c);
+				for (Annotation a : c.getAnnotations()) {
+					if (a instanceof Header)
+						rp[i] = new RestParamDefaults.HeaderObject(method, (Header)a, t, ps, rp[i]);
+					else if (a instanceof FormData)
+						rp[i] = new RestParamDefaults.FormDataObject(method, (FormData)a, t, ps, rp[i]);
+					else if (a instanceof Query)
+						rp[i] = new RestParamDefaults.QueryObject(method, (Query)a, t, ps, rp[i]);
+					else if (a instanceof HasFormData)
+						rp[i] = new RestParamDefaults.HasFormDataObject(method, (HasFormData)a, t);
+					else if (a instanceof HasQuery)
+						rp[i] = new RestParamDefaults.HasQueryObject(method, (HasQuery)a, t);
+					else if (a instanceof Body)
+						rp[i] = new RestParamDefaults.BodyObject(method, (Body)a, t, null);
+					else if (a instanceof PathRemainder)
+						rp[i] = new RestParamDefaults.PathRemainderObject(method, t);					
+					else if (a instanceof Response)
+						rp[i] = new RestParamDefaults.ResponseObject(method, (Response)a, t, ps, rp[i]);					
+					else if (a instanceof ResponseHeader)
+						rp[i] = new RestParamDefaults.ResponseHeaderObject(method, (ResponseHeader)a, t, ps, rp[i]);					
+					else if (a instanceof ResponseStatus)
+						rp[i] = new RestParamDefaults.ResponseStatusObject(method, (ResponseStatus)a, t, ps, rp[i]);			
+					else if (a instanceof Responses) 
+						for (Response r : ((Responses)a).value())
+							rp[i] = new RestParamDefaults.ResponseObject(method, r, t, ps, rp[i]);			
+					else if (a instanceof ResponseStatuses)
+						for (ResponseStatus rs : ((ResponseStatuses)a).value())
+							rp[i] = new RestParamDefaults.ResponseStatusObject(method, rs, t, ps, rp[i]);			
+				}
 			}
 
 			for (Annotation a : pa[i]) {
 				if (a instanceof Header)
-					rp[i] = new RestParamDefaults.HeaderObject(method, (Header)a, t, ps);
+					rp[i] = new RestParamDefaults.HeaderObject(method, (Header)a, t, ps, rp[i]);
 				else if (a instanceof FormData)
-					rp[i] = new RestParamDefaults.FormDataObject(method, (FormData)a, t, ps);
+					rp[i] = new RestParamDefaults.FormDataObject(method, (FormData)a, t, ps, rp[i]);
 				else if (a instanceof Query)
-					rp[i] = new RestParamDefaults.QueryObject(method, (Query)a, t, ps);
+					rp[i] = new RestParamDefaults.QueryObject(method, (Query)a, t, ps, rp[i]);
 				else if (a instanceof HasFormData)
 					rp[i] = new RestParamDefaults.HasFormDataObject(method, (HasFormData)a, t);
 				else if (a instanceof HasQuery)
 					rp[i] = new RestParamDefaults.HasQueryObject(method, (HasQuery)a, t);
 				else if (a instanceof Body)
-					rp[i] = new RestParamDefaults.BodyObject(method, (Body)a, t);
+					rp[i] = new RestParamDefaults.BodyObject(method, (Body)a, t, rp[i]);
 				else if (a instanceof org.apache.juneau.rest.annotation.Method)
 					rp[i] = new RestParamDefaults.MethodObject(method, t);
 				else if (a instanceof PathRemainder)
 					rp[i] = new RestParamDefaults.PathRemainderObject(method, t);
+				else if (a instanceof Response)
+					rp[i] = new RestParamDefaults.ResponseObject(method, (Response)a, t, ps, rp[i]);
+				else if (a instanceof ResponseHeader)
+					rp[i] = new RestParamDefaults.ResponseHeaderObject(method, (ResponseHeader)a, t, ps, rp[i]);
+				else if (a instanceof ResponseStatus)
+					rp[i] = new RestParamDefaults.ResponseStatusObject(method, (ResponseStatus)a, t, ps, rp[i]);
+				else if (a instanceof Responses) 
+					for (Response r : ((Responses)a).value())
+						rp[i] = new RestParamDefaults.ResponseObject(method, r, t, ps, rp[i]);			
+				else if (a instanceof ResponseStatuses)
+					for (ResponseStatus rs : ((ResponseStatuses)a).value())
+						rp[i] = new RestParamDefaults.ResponseStatusObject(method, rs, t, ps, rp[i]);			
 			}
 
 			if (rp[i] == null) {
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
index ccdecc3..e6a11f7 100644
--- 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
@@ -35,9 +35,8 @@ public class RestMethodReturn {
 		
 		int code = 200;
 		if (type instanceof Class)
-		for (ResponseInfo ri : ReflectionUtils.findAnnotationsParentFirst(ResponseInfo.class, (Class<?>)type)) {
-			if (ri.code() != 0)
-				code = ri.code();
+		for (Response ri : ReflectionUtils.findAnnotationsParentFirst(Response.class, (Class<?>)type)) {
+			code = ObjectUtils.firstNonZero(ri.code(), ri.value(), code);
 			metaData.appendSkipEmpty("description", ri.description());
 			metaData.appendSkipEmpty("example", join(ri.example(), ""));
 			metaData.appendSkipEmpty("headers", join(ri.headers(), ""));
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
index ff9e511..65203b2 100644
--- 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
@@ -34,9 +34,8 @@ public class RestMethodThrown {
 		this.metaData = new ObjectMap();
 		
 		int code = 500;
-		for (ResponseInfo ri : ReflectionUtils.findAnnotationsParentFirst(ResponseInfo.class, type)) {
-			if (ri.code() != 0)
-				code = ri.code();
+		for (Response ri : ReflectionUtils.findAnnotationsParentFirst(Response.class, type)) {
+			code = ObjectUtils.firstNonZero(ri.code(), ri.value(), code);
 			metaData.appendSkipEmpty("description", ri.description());
 			metaData.appendSkipEmpty("example", join(ri.example(), ""));
 			metaData.appendSkipEmpty("headers", join(ri.headers(), ""));
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 3e7f48a..5778f6c 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
@@ -13,6 +13,7 @@
 package org.apache.juneau.rest;
 
 import static org.apache.juneau.internal.StringUtils.*;
+import static org.apache.juneau.internal.ObjectUtils.*;
 import static org.apache.juneau.rest.RestParamType.*;
 
 import java.io.*;
@@ -30,6 +31,7 @@ import org.apache.juneau.http.*;
 import org.apache.juneau.http.Date;
 import org.apache.juneau.httppart.*;
 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.utils.*;
@@ -579,8 +581,8 @@ class RestParamDefaults {
 
 	static final class BodyObject extends RestMethodParam {
 
-		protected BodyObject(Method method, Body a, Type type) {
-			super(BODY, null, type, getMetaData(a));
+		protected BodyObject(Method method, Body a, Type type, RestMethodParam existing) {
+			super(BODY, null, type, getMetaData(a, castOrNull(existing, BodyObject.class)));
 		}
 
 		@Override /* RestMethodParam */
@@ -588,11 +590,12 @@ class RestParamDefaults {
 			return req.getBody().asType(type);
 		}
 		
-		private static final ObjectMap getMetaData(Body a) {
+		private static final ObjectMap getMetaData(Body a, BodyObject existing) {
+			ObjectMap om = existing == null ? new ObjectMap() : existing.metaData;
 			if (a == null)
-				return ObjectMap.EMPTY_MAP;
-			return new ObjectMap()
-				.appendSkipEmpty("description", a.description())
+				return om;
+			return om
+				.appendSkipEmpty("description", join(a.description()))
 				.appendSkipEmpty("required", a.required())
 				.appendSkipEmpty("type", a.type())
 				.appendSkipEmpty("format", a.format())
@@ -609,11 +612,11 @@ class RestParamDefaults {
 				.appendSkipEmpty("exclusiveMaximum", a.exclusiveMaximum())
 				.appendSkipEmpty("exclusiveMimimum", a.exclusiveMimimum())
 				.appendSkipEmpty("uniqueItems", a.uniqueItems())
-				.appendSkipEmpty("schema", a.schema())
-				.appendSkipEmpty("default", a._default())
-				.appendSkipEmpty("enum", a._enum())
-				.appendSkipEmpty("items", a.items())
-				.appendSkipEmpty("example", a.example())
+				.appendSkipEmpty("schema", join(a.schema()))
+				.appendSkipEmpty("default", join(a._default()))
+				.appendSkipEmpty("enum", join(a._enum()))
+				.appendSkipEmpty("items", join(a.items()))
+				.appendSkipEmpty("example", join(a.example()))
 			;
 		}
 	}
@@ -621,8 +624,8 @@ class RestParamDefaults {
 	static final class HeaderObject extends RestMethodParam {
 		private final HttpPartParser partParser;
 
-		protected HeaderObject(Method method, Header a, Type type, PropertyStore ps) {
-			super(HEADER, firstNonEmpty(a.name(), a.value()), type, getMetaData(a));
+		protected HeaderObject(Method method, Header a, Type type, PropertyStore ps, RestMethodParam existing) {
+			super(HEADER, firstNonEmpty(a.name(), a.value()), type, getMetaData(a, castOrNull(existing, HeaderObject.class)));
 			this.partParser = a.parser() == HttpPartParser.Null.class ? null : ClassUtils.newInstance(HttpPartParser.class, a.parser(), true, ps);
 		}
 
@@ -631,10 +634,11 @@ class RestParamDefaults {
 			return req.getHeaders().get(partParser, name, type);
 		}
 		
-		private static ObjectMap getMetaData(Header a) {
+		private static ObjectMap getMetaData(Header a, HeaderObject existing) {
+			ObjectMap om = existing == null ? new ObjectMap() : existing.metaData;
 			if (a == null)
-				return ObjectMap.EMPTY_MAP;
-			return new ObjectMap()
+				return om;
+			return om
 				.appendSkipEmpty("description", a.description())
 				.appendSkipEmpty("required", a.required())
 				.appendSkipEmpty("type", a.type())
@@ -650,7 +654,7 @@ class RestParamDefaults {
 				.appendSkipEmpty("minItems", a.minItems())
 				.appendSkipEmpty("allowEmptyVals", a.allowEmptyVals())
 				.appendSkipEmpty("exclusiveMaximum", a.exclusiveMaximum())
-				.appendSkipEmpty("exclusiveMimimum", a.exclusiveMimimum())
+				.appendSkipEmpty("exclusiveMinimum", a.exclusiveMinimum())
 				.appendSkipEmpty("uniqueItems", a.uniqueItems())
 				.appendSkipEmpty("schema", a.schema())
 				.appendSkipEmpty("default", a._default())
@@ -661,6 +665,178 @@ class RestParamDefaults {
 		}
 	}
 
+	static final class ResponseHeaderObject extends RestMethodParam {
+		final HttpPartSerializer partSerializer;
+
+		protected ResponseHeaderObject(Method method, ResponseHeader a, Type type, PropertyStore ps, RestMethodParam existing) {
+			super(RESPONSE_HEADER, firstNonEmpty(a.name(), a.value(), "Unknown"), type, getMetaData(a, castOrNull(existing, ResponseHeaderObject.class)));
+			this.partSerializer = a.serializer() == HttpPartSerializer.Null.class ? null : ClassUtils.newInstance(HttpPartSerializer.class, a.serializer(), true, ps);
+		}
+
+		@SuppressWarnings({ "unchecked", "rawtypes" })
+		@Override /* RestMethodParam */
+		public Object resolve(RestRequest req, final RestResponse res) throws Exception {
+			if (type instanceof Class) {
+				Class<?> c = (Class<?>)type;
+				if (ClassUtils.isParentClass(Value.class, c)) {
+					try {
+						Value<Object> v = (Value<Object>)c.newInstance();
+						v.listener(new ValueListener() {
+							@Override
+							public void onSet(Object newValue) {
+								res.setHeader(name, partSerializer.serialize(HttpPartType.HEADER, newValue));
+							}
+						});
+						String def = getMetaData().getString("default");
+						if (def != null) {
+							Class<?> pc = ClassUtils.resolveParameterType(Value.class, 0, c);
+							v.set(JsonParser.DEFAULT.parse(def, req.getBeanSession().getClassMeta(pc)));
+						}
+							
+						return v;
+					} catch (Exception e) {
+						throw new RestException(500, "Invalid type {0} specified with @ResponseHeader annotation.  It must have a public no-arg constructor.", type);
+					}
+				}
+			}
+			throw new RestException(500, "Invalid type {0} specified with @ResponseHeader annotation.  It must be a subclass of Value.", type);
+		}
+		
+		public HttpPartSerializer getPartSerializer() {
+			return partSerializer;
+		}
+		
+		private static ObjectMap getMetaData(ResponseHeader a, ResponseHeaderObject existing) {
+			ObjectMap om = existing == null ? new ObjectMap() : existing.metaData;
+			if (a == null)
+				return om;
+			String code = firstNonEmpty(a.code(), "200");
+			for (String c : StringUtils.split(code)) {
+				ObjectMap om2 = om.getObjectMap(c, true);
+				om2
+					.appendSkipEmpty("description", join(a.description()))
+					.appendSkipEmpty("type", a.type())
+					.appendSkipEmpty("format", a.format())
+					.appendSkipEmpty("collectionFormat", a.collectionFormat())
+					.appendSkipEmpty("maximum", a.maximum())
+					.appendSkipEmpty("minimum", a.minimum())
+					.appendSkipEmpty("multipleOf", a.multipleOf())
+					.appendSkipEmpty("maxLength", a.maxLength())
+					.appendSkipEmpty("minLength", a.minLength())
+					.appendSkipEmpty("maxItems", a.maxItems())
+					.appendSkipEmpty("minItems", a.minItems())
+					.appendSkipEmpty("exclusiveMaximum", a.exclusiveMaximum())
+					.appendSkipEmpty("exclusiveMimimum", a.exclusiveMinimum())
+					.appendSkipEmpty("uniqueItems", a.uniqueItems())
+					.appendSkipEmpty("default", join(a._default()))
+					.appendSkipEmpty("enum", join(a._enum()))
+					.appendSkipEmpty("items", join(a.items()))
+					.appendSkipEmpty("example", join(a.example()))
+				;
+			}
+			return om;
+		}
+	}
+
+	static final class ResponseObject extends RestMethodParam {
+
+		protected ResponseObject(Method method, Response a, Type type, PropertyStore ps, RestMethodParam existing) {
+			super(RESPONSE, "body", type, getMetaData(a, castOrNull(existing, ResponseObject.class)));
+		}
+
+		@SuppressWarnings({ "unchecked", "rawtypes" })
+		@Override /* RestMethodParam */
+		public Object resolve(RestRequest req, final RestResponse res) throws Exception {
+			if (type instanceof Class) {
+				Class<?> c = (Class<?>)type;
+				if (ClassUtils.isParentClass(Value.class, c)) {
+					try {
+						Value<Object> v = (Value<Object>)c.newInstance();
+						v.listener(new ValueListener() {
+							@Override
+							public void onSet(Object newValue) {
+								res.setOutput(newValue);
+							}
+						});
+						String def = getMetaData().getString("default");
+						if (def != null) {
+							Class<?> pc = ClassUtils.resolveParameterType(Value.class, 0, c);
+							v.set(JsonParser.DEFAULT.parse(def, req.getBeanSession().getClassMeta(pc)));
+						}
+							
+						return v;
+					} catch (Exception e) {
+						throw new RestException(500, "Invalid type {0} specified with @ResponseHeader annotation.  It must have a public no-arg constructor.", type);
+					}
+				}
+			}
+			throw new RestException(500, "Invalid type {0} specified with @ResponseHeader annotation.  It must be a subclass of Value.", type);
+		}
+		
+		private static ObjectMap getMetaData(Response a, ResponseObject existing) {
+			ObjectMap om = existing == null ? new ObjectMap() : existing.metaData;
+			if (a == null)
+				return om;
+			int status = ObjectUtils.firstNonZero(a.code(), a.value(), 200);
+			ObjectMap om2 = om.getObjectMap(String.valueOf(status), true);
+			om2
+				.appendSkipEmpty("description", join(a.description()))
+				.appendSkipEmpty("schema", join(a.schema()))
+				.appendSkipEmpty("headers", join(a.headers()))
+				.appendSkipEmpty("example", join(a.example()))
+			;
+			return om;
+		}
+	}
+
+	static final class ResponseStatusObject extends RestMethodParam {
+
+		protected ResponseStatusObject(Method method, ResponseStatus a, Type type, PropertyStore ps, RestMethodParam existing) {
+			super(RESPONSE_STATUS, "", type, getMetaData(a, castOrNull(existing, ResponseStatusObject.class)));
+		}
+
+		@SuppressWarnings({ "unchecked", "rawtypes" })
+		@Override /* RestMethodParam */
+		public Object resolve(RestRequest req, final RestResponse res) throws Exception {
+			if (type instanceof Class) {
+				Class<?> c = (Class<?>)type;
+				if (ClassUtils.isParentClass(Value.class, c)) {
+					try {
+						Value<Object> v = (Value<Object>)c.newInstance();
+						v.listener(new ValueListener() {
+							@Override
+							public void onSet(Object newValue) {
+								res.setStatus(Integer.parseInt(newValue.toString()));
+							}
+						});
+						String def = getMetaData().getString("default");
+						if (def != null) {
+							Class<?> pc = ClassUtils.resolveParameterType(Value.class, 0, c);
+							v.set(JsonParser.DEFAULT.parse(def, req.getBeanSession().getClassMeta(pc)));
+						}
+							
+						return v;
+					} catch (Exception e) {
+						throw new RestException(500, "Invalid type {0} specified with @ResponseStatus annotation.  It must have a public no-arg constructor.", type);
+					}
+				}
+			}
+			throw new RestException(500, "Invalid type {0} specified with @ResponseStatus annotation.  It must be a subclass of Value.", type);
+		}
+		
+		private static ObjectMap getMetaData(ResponseStatus a, ResponseStatusObject existing) {
+			ObjectMap om = existing == null ? new ObjectMap() : existing.metaData;
+			if (a == null)
+				return om;
+			int status = firstNonZero(a.code(), a.value(), 200);
+			ObjectMap om2 = om.getObjectMap(String.valueOf(status), true);
+			om2
+				.appendSkipEmpty("description", join(a.description()))
+			;
+			return om;
+		}
+	}
+
 	static final class MethodObject extends RestMethodParam {
 
 		protected MethodObject(Method method, Type type) throws ServletException {
@@ -679,8 +855,8 @@ class RestParamDefaults {
 		private final boolean multiPart;
 		private final HttpPartParser partParser;
 
-		protected FormDataObject(Method method, FormData a, Type type, PropertyStore ps) throws ServletException {
-			super(FORM_DATA, firstNonEmpty(a.name(), a.value()), type, getMetaData(a));
+		protected FormDataObject(Method method, FormData a, Type type, PropertyStore ps, RestMethodParam existing) throws ServletException {
+			super(FORM_DATA, firstNonEmpty(a.name(), a.value()), type, getMetaData(a, castOrNull(existing, FormDataObject.class)));
 			if (a.multipart() && ! isCollection(type))
 					throw new RestServletException("Use of multipart flag on @FormData parameter that's not an array or Collection on method ''{0}''", method);
 			this.multiPart = a.multipart();
@@ -694,10 +870,11 @@ class RestParamDefaults {
 			return req.getFormData().get(partParser, name, type);
 		}
 		
-		private static final ObjectMap getMetaData(FormData a) {
+		private static final ObjectMap getMetaData(FormData a, FormDataObject existing) {
+			ObjectMap om = existing == null ? new ObjectMap() : existing.metaData;
 			if (a == null)
-				return ObjectMap.EMPTY_MAP;
-			return new ObjectMap()
+				return om;
+			return om
 				.appendSkipEmpty("description", a.description())
 				.appendSkipEmpty("required", a.required())
 				.appendSkipEmpty("type", a.type())
@@ -728,8 +905,8 @@ class RestParamDefaults {
 		private final boolean multiPart;
 		private final HttpPartParser partParser;
 
-		protected QueryObject(Method method, Query a, Type type, PropertyStore ps) throws ServletException {
-			super(QUERY, firstNonEmpty(a.name(), a.value()), type, getMetaData(a));
+		protected QueryObject(Method method, Query a, Type type, PropertyStore ps, RestMethodParam existing) throws ServletException {
+			super(QUERY, firstNonEmpty(a.name(), a.value()), type, getMetaData(a, castOrNull(existing, QueryObject.class)));
 			if (a.multipart() && ! isCollection(type))
 					throw new RestServletException("Use of multipart flag on @Query parameter that's not an array or Collection on method ''{0}''", method);
 			this.multiPart = a.multipart();
@@ -743,10 +920,11 @@ class RestParamDefaults {
 			return req.getQuery().get(partParser, name, type);
 		}
 		
-		private static final ObjectMap getMetaData(Query a) {
+		private static final ObjectMap getMetaData(Query a, QueryObject existing) {
+			ObjectMap om = existing == null ? new ObjectMap() : existing.metaData;
 			if (a == null)
-				return ObjectMap.EMPTY_MAP;
-			return new ObjectMap()
+				return om;
+			return om
 				.appendSkipEmpty("description", a.description())
 				.appendSkipEmpty("required", a.required())
 				.appendSkipEmpty("type", a.type())
@@ -1125,4 +1303,8 @@ class RestParamDefaults {
 	static final boolean isCollection(Type t) {
 		return BeanContext.DEFAULT.getClassMeta(t).isCollectionOrArray();
 	}
+	
+	static final String join(String...s) {
+		return StringUtils.join(s, '\n');
+	}
 }
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 ff913c5..ed51fb2 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,6 +37,15 @@ public enum RestParamType {
 	/** 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");
 
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/Body.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/Body.java
index d3187ff..72f5744 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/Body.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/Body.java
@@ -58,7 +58,7 @@ import org.apache.juneau.rest.*;
  * </ul>
  */
 @Documented
-@Target(PARAMETER)
+@Target({PARAMETER,TYPE})
 @Retention(RUNTIME)
 @Inherited
 public @interface Body {
@@ -70,12 +70,13 @@ public @interface Body {
 	 * <ul class='spaced-list'>
 	 * 	<li>
 	 * 		The format of the value 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 "";
+	String[] description() default {};
 	
 	/**
 	 * Defines the swagger value <code>/paths/{path}/{method}/parameters/#/required</code>.
@@ -323,12 +324,13 @@ public @interface Body {
 	 * <ul class='spaced-list'>
 	 * 	<li>
 	 * 		The format of the value is a JSON object.
+	 * 		<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 schema() default "";
+	String[] schema() default {};
 	
 	/**
 	 * Defines the swagger value <code>/paths/{path}/{method}/parameters/#/default</code>.
@@ -337,12 +339,13 @@ public @interface Body {
 	 * <ul class='spaced-list'>
 	 * 	<li>
 	 * 		The format of the value is JSON.
+	 * 		<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 _default() default "";
+	String[] _default() default {};
 	
 	/**
 	 * Defines the swagger value <code>/paths/{path}/{method}/parameters/#/enum</code>.
@@ -351,12 +354,13 @@ public @interface Body {
 	 * <ul class='spaced-list'>
 	 * 	<li>
 	 * 		The format of the value is a JSON array or comma-delimited list.
+	 * 		<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 _enum() default "";
+	String[] _enum() default {};
 	
 	/**
 	 * Defines the swagger value <code>/paths/{path}/{method}/parameters/#/items</code>.
@@ -365,12 +369,13 @@ public @interface Body {
 	 * <ul class='spaced-list'>
 	 * 	<li>
 	 * 		The format of the value is a JSON object.
+	 * 		<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 items() default "";	
+	String[] items() default {};	
 	
 	/**
 	 * Defines the swagger value <code>/paths/{path}/{method}/parameters/#/x-example</code>.
@@ -383,10 +388,11 @@ public @interface Body {
 	 * <ul class='spaced-list'>
 	 * 	<li>
 	 * 		The format of the value is a JSON object or plain-text string.
+	 * 		<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 example() default "";
+	String[] example() default {};
 }
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/FormData.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/FormData.java
index d9c1bfa..4b7c666 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/FormData.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/FormData.java
@@ -61,7 +61,7 @@ import org.apache.juneau.rest.*;
  * </ul>
  */
 @Documented
-@Target(PARAMETER)
+@Target({PARAMETER,TYPE})
 @Retention(RUNTIME)
 @Inherited
 public @interface FormData {
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/HasFormData.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/HasFormData.java
index dd378d0..0bc4867 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/HasFormData.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/HasFormData.java
@@ -90,7 +90,7 @@ import org.apache.juneau.rest.*;
  * </ul>
  */
 @Documented
-@Target(PARAMETER)
+@Target({PARAMETER,TYPE})
 @Retention(RUNTIME)
 @Inherited
 public @interface HasFormData {
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/HasQuery.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/HasQuery.java
index a1545c9..8dfb9ba 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/HasQuery.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/HasQuery.java
@@ -53,7 +53,7 @@ import org.apache.juneau.rest.*;
  * </ul>
  */
 @Documented
-@Target(PARAMETER)
+@Target({PARAMETER,TYPE})
 @Retention(RUNTIME)
 @Inherited
 public @interface HasQuery {
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/Header.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/Header.java
index 01ad591..cc0f474 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/Header.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/Header.java
@@ -48,7 +48,7 @@ import org.apache.juneau.rest.*;
  * </ul>
  */
 @Documented
-@Target(PARAMETER)
+@Target({PARAMETER,TYPE})
 @Retention(RUNTIME)
 @Inherited
 public @interface Header {
@@ -317,7 +317,7 @@ public @interface Header {
 	 * 		(e.g. <js>"$L{my.localized.variable}"</js>).
 	 * </ul>
 	 */
-	String exclusiveMimimum() default "";
+	String exclusiveMinimum() default "";
 	
 	/**
 	 * Defines the swagger value <code>/paths/{path}/{method}/parameters/#/uniqueItems</code>.
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/Path.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/Path.java
index fa30b8e..518dd66 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/Path.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/Path.java
@@ -75,7 +75,7 @@ import org.apache.juneau.rest.*;
  * </ul>
  */
 @Documented
-@Target(PARAMETER)
+@Target({PARAMETER,TYPE})
 @Retention(RUNTIME)
 @Inherited
 public @interface Path {
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/Query.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/Query.java
index c3c60e7..cfb4d33 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/Query.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/Query.java
@@ -57,7 +57,7 @@ import org.apache.juneau.rest.*;
  * </ul>
  */
 @Documented
-@Target(PARAMETER)
+@Target({PARAMETER,TYPE})
 @Retention(RUNTIME)
 @Inherited
 public @interface Query {
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/ResponseInfo.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/Response.java
similarity index 81%
rename from juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/ResponseInfo.java
rename to juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/Response.java
index 3c300b9..23a22d6 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/ResponseInfo.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/Response.java
@@ -24,42 +24,17 @@ import java.lang.annotation.*;
 @Target(TYPE)
 @Retention(RUNTIME)
 @Inherited
-public @interface ResponseInfo {
+public @interface Response {
 	
-	/**
-	 * The HTTP status of the response.
-	 */
 	int code() default 0;
 	
-	/**
-	 * Description.
-	 * 
-	 * <p>
-	 * Format is plain text.
-	 */
+	int value() default 0;
+	
 	String description() default "";
 
-	/**
-	 * Schema information.
-	 * 
-	 * <p>
-	 * Format is a JSON object consisting of a Swagger SchemaInfo object.
-	 */
 	String[] schema() default {};
 	
-	/**
-	 * Header information.
-	 * 
-	 * <p>
-	 * Format is a JSON array consisting of Swagger HeaderInfo objects.
-	 */
 	String[] headers() default {};
 	
-	/**
-	 * Example.
-	 * 
-	 * <p>
-	 * Format is a JSON primitive, array, or object.
-	 */
 	String[] example() default {};
 }
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/Header.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/ResponseHeader.java
similarity index 63%
copy from juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/Header.java
copy to juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/ResponseHeader.java
index 01ad591..abe609c 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/Header.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/ResponseHeader.java
@@ -1,409 +1,414 @@
-// ***************************************************************************************************************************
-// * 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.annotation;
-
-import static java.lang.annotation.ElementType.*;
-import static java.lang.annotation.RetentionPolicy.*;
-
-import java.lang.annotation.*;
-
-import org.apache.juneau.httppart.*;
-import org.apache.juneau.rest.*;
-
-/**
- * Annotation that can be applied to a parameter of a {@link RestMethod @RestMethod} annotated method to identify it as a HTTP
- * request header converted to a POJO.
- * 
- * <h5 class='section'>Example:</h5>
- * <p class='bcode'>
- * 	<ja>@RestMethod</ja>(name=<jsf>GET</jsf>)
- * 	<jk>public void</jk> doGet(RestRequest req, RestResponse res, <ja>@Header</ja>(<js>"ETag"</js>) UUID etag) {
- * 		...
- * 	}
- * </p>
- * 
- * <p>
- * This is functionally equivalent to the following code...
- * <p class='bcode'>
- * 	<ja>@RestMethod</ja>(name=<jsf>GET</jsf>)
- * 	<jk>public void</jk> doPostPerson(RestRequest req, RestResponse res) {
- * 		UUID etag = req.getHeader(UUID.<jk>class</jk>, "ETag");
- * 		...
- * 	}
- * </p>
- * 
- * <h5 class='section'>See Also:</h5>
- * <ul>
- * 	<li class='link'><a class="doclink" href="../../../../../overview-summary.html#juneau-rest-server.Header">Overview &gt; juneau-rest-server &gt; @Header</a>
- * </ul>
- */
-@Documented
-@Target(PARAMETER)
-@Retention(RUNTIME)
-@Inherited
-public @interface Header {
-
-	/**
-	 * The default value for this header if it's not present in the request.
-	 */
-	String def() default "";
-
-	/**
-	 * HTTP header name.
-	 */
-	String name() default "";
-
-	/**
-	 * Specifies the {@link HttpPartParser} class used for parsing values from strings.
-	 * 
-	 * <p>
-	 * The default value for this parser is inherited from the servlet/method which defaults to {@link UonPartParser}.
-	 * <br>You can use {@link SimplePartParser} to parse POJOs that are directly convertible from <code>Strings</code>.
-	 */
-	Class<? extends HttpPartParser> parser() default HttpPartParser.Null.class;
-
-	/**
-	 * A synonym for {@link #name()}.
-	 * 
-	 * <p>
-	 * Allows you to use shortened notation if you're only specifying the name.
-	 */
-	String value() default "";
-	
-	/**
-	 * Defines the swagger value <code>/paths/{path}/{method}/parameters/#/description</code>.
-	 * 
-	 * <h5 class='section'>Notes:</h5>
-	 * <ul class='spaced-list'>
-	 * 	<li>
-	 * 		The format of the value is plain-text.
-	 * 	<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 "";
-	
-	/**
-	 * Defines the swagger value <code>/paths/{path}/{method}/parameters/#/required</code>.
-	 * 
-	 * <h5 class='section'>Notes:</h5>
-	 * <ul class='spaced-list'>
-	 * 	<li>
-	 * 		The format of the value is boolean.
-	 * 	<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 required() default "";
-	
-	/**
-	 * Defines the swagger value <code>/paths/{path}/{method}/parameters/#/type</code>.
-	 * 
-	 * <h5 class='section'>Notes:</h5>
-	 * <ul class='spaced-list'>
-	 * 	<li>
-	 * 		The possible values are:
-	 * 		<ul>
-	 * 			<li><js>"string"</js>
-	 * 			<li><js>"number"</js>
-	 * 			<li><js>"integer"</js>
-	 * 			<li><js>"boolean"</js>
-	 * 			<li><js>"array"</js>
-	 * 			<li><js>"file"</js>
-	 * 		</ul>
-	 * 	<li>
-	 * 		Supports <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 type() default "";
-	
-	/**
-	 * Defines the swagger value <code>/paths/{path}/{method}/parameters/#/format</code>.
-	 * 
-	 * <h5 class='section'>Notes:</h5>
-	 * <ul class='spaced-list'>
-	 * 	<li>
-	 * 		The format of the value is plain-text:
-	 * 	<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 format() default "";
-	
-	/**
-	 * Defines the swagger value <code>/paths/{path}/{method}/parameters/#/pattern</code>.
-	 * 
-	 * <h5 class='section'>Notes:</h5>
-	 * <ul class='spaced-list'>
-	 * 	<li>
-	 * 		The format of the value is plain-text.
-	 * 	<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 pattern() default "";
-
-	/**
-	 * Defines the swagger value <code>/paths/{path}/{method}/parameters/#/collectionFormat</code>.
-	 * 
-	 * <h5 class='section'>Notes:</h5>
-	 * <ul class='spaced-list'>
-	 * 	<li>
-	 * 		The possible value are:
-	 * 		<ul>
-	 * 			<li><js>"csv"</js>
-	 * 			<li><js>"ssv"</js>
-	 * 			<li><js>"tsv"</js>
-	 * 			<li><js>"pipes"</js>
-	 * 			<li><js>"multi"</js>
-	 * 		</ul>
-	 * 	<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 collectionFormat() default "";
-
-	/**
-	 * Defines the swagger value <code>/paths/{path}/{method}/parameters/#/maximum</code>.
-	 * 
-	 * <h5 class='section'>Notes:</h5>
-	 * <ul class='spaced-list'>
-	 * 	<li>
-	 * 		The format of the value is numeric.
-	 * 	<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 maximum() default "";
-	
-	/**
-	 * Defines the swagger value <code>/paths/{path}/{method}/parameters/#/minimum</code>.
-	 * 
-	 * <h5 class='section'>Notes:</h5>
-	 * <ul class='spaced-list'>
-	 * 	<li>
-	 * 		The format of the value is numeric.
-	 * 	<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 minimum() default "";
-
-	/**
-	 * Defines the swagger value <code>/paths/{path}/{method}/parameters/#/multipleOf</code>.
-	 * 
-	 * <h5 class='section'>Notes:</h5>
-	 * <ul class='spaced-list'>
-	 * 	<li>
-	 * 		The format of the value is numeric.
-	 * 	<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 multipleOf() default "";
-	
-	/**
-	 * Defines the swagger value <code>/paths/{path}/{method}/parameters/#/maxLength</code>.
-	 * 
-	 * <h5 class='section'>Notes:</h5>
-	 * <ul class='spaced-list'>
-	 * 	<li>
-	 * 		The format of the value is numeric.
-	 * 	<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 maxLength() default "";
-	
-	/**
-	 * Defines the swagger value <code>/paths/{path}/{method}/parameters/#/minLength</code>.
-	 * 
-	 * <h5 class='section'>Notes:</h5>
-	 * <ul class='spaced-list'>
-	 * 	<li>
-	 * 		The format of the value is numeric.
-	 * 	<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 minLength() default "";
-	
-	/**
-	 * Defines the swagger value <code>/paths/{path}/{method}/parameters/#/maxItems</code>.
-	 * 
-	 * <h5 class='section'>Notes:</h5>
-	 * <ul class='spaced-list'>
-	 * 	<li>
-	 * 		The format of the value is numeric.
-	 * 	<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 maxItems() default "";
-
-	/**
-	 * Defines the swagger value <code>/paths/{path}/{method}/parameters/#/minItems</code>.
-	 * 
-	 * <h5 class='section'>Notes:</h5>
-	 * <ul class='spaced-list'>
-	 * 	<li>
-	 * 		The format of the value is numeric.
-	 * 	<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 minItems() default "";
-
-	/**
-	 * Defines the swagger value <code>/paths/{path}/{method}/parameters/#/allowEmptyVals</code>.
-	 * 
-	 * <h5 class='section'>Notes:</h5>
-	 * <ul class='spaced-list'>
-	 * 	<li>
-	 * 		The format of the value is boolean.
-	 * 	<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 allowEmptyVals() default "";
-
-	/**
-	 * Defines the swagger value <code>/paths/{path}/{method}/parameters/#/exclusiveMaximum</code>.
-	 * 
-	 * <h5 class='section'>Notes:</h5>
-	 * <ul class='spaced-list'>
-	 * 	<li>
-	 * 		The format of the value is numeric.
-	 * 	<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 exclusiveMaximum() default "";
-
-	/**
-	 * Defines the swagger value <code>/paths/{path}/{method}/parameters/#/exclusiveMimimum</code>.
-	 * 
-	 * <h5 class='section'>Notes:</h5>
-	 * <ul class='spaced-list'>
-	 * 	<li>
-	 * 		The format of the value is numeric.
-	 * 	<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 exclusiveMimimum() default "";
-	
-	/**
-	 * Defines the swagger value <code>/paths/{path}/{method}/parameters/#/uniqueItems</code>.
-	 * 
-	 * <h5 class='section'>Notes:</h5>
-	 * <ul class='spaced-list'>
-	 * 	<li>
-	 * 		The format of the value is boolean.
-	 * 	<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 uniqueItems() default "";
-	
-	/**
-	 * Defines the swagger value <code>/paths/{path}/{method}/parameters/#/schema</code>.
-	 * 
-	 * <h5 class='section'>Notes:</h5>
-	 * <ul class='spaced-list'>
-	 * 	<li>
-	 * 		The format of the value is a JSON object.
-	 * 	<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 schema() default "";
-	
-	/**
-	 * Defines the swagger value <code>/paths/{path}/{method}/parameters/#/default</code>.
-	 * 
-	 * <h5 class='section'>Notes:</h5>
-	 * <ul class='spaced-list'>
-	 * 	<li>
-	 * 		The format of the value is JSON.
-	 * 	<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 _default() default "";
-	
-	/**
-	 * Defines the swagger value <code>/paths/{path}/{method}/parameters/#/enum</code>.
-	 * 
-	 * <h5 class='section'>Notes:</h5>
-	 * <ul class='spaced-list'>
-	 * 	<li>
-	 * 		The format of the value is a JSON array or comma-delimited list.
-	 * 	<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 _enum() default "";
-	
-	/**
-	 * Defines the swagger value <code>/paths/{path}/{method}/parameters/#/items</code>.
-	 * 
-	 * <h5 class='section'>Notes:</h5>
-	 * <ul class='spaced-list'>
-	 * 	<li>
-	 * 		The format of the value is a JSON object.
-	 * 	<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 items() default "";	
-	
-	/**
-	 * Defines the swagger value <code>/paths/{path}/{method}/parameters/#/x-example</code>.
-	 * 
-	 * <p>
-	 * This attribute defines a JSON representation of the value that is used by {@link BasicRestInfoProvider} to construct
-	 * an example of the header entry.
-	 * 
-	 * <h5 class='section'>Notes:</h5>
-	 * <ul class='spaced-list'>
-	 * 	<li>
-	 * 		The format of the value is a JSON object or plain-text string.
-	 * 	<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 example() 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.rest.annotation;
+
+import static java.lang.annotation.ElementType.*;
+import static java.lang.annotation.RetentionPolicy.*;
+
+import java.lang.annotation.*;
+
+import org.apache.juneau.httppart.*;
+import org.apache.juneau.rest.*;
+import org.apache.juneau.utils.*;
+
+/**
+ * Annotation that can be applied to parameters and types to denote them as an HTTP response headers.
+ * 
+ * <p>
+ * This annotation can only be applied to subclasses of type {@link Value}.
+ * 
+ * <p>
+ * The following examples show 3 different ways of accomplishing the same task of setting an HTTP header
+ * on a response:
+ * 
+ * <p class='bcode'>
+ * 	<jc>// Example #1 - Setting header directly on RestResponse object.</jc>
+ * 	<ja>@RestMethod</ja>(...)
+ * 	<jk>public void</jk> login(RestResponse res) {
+ * 		res.setHeader(<js>"X-Rate-Limit"</js>, 1000);
+ * 		...
+ * 	}
+ * 
+ *	<jc>// Example #2 - Use on parameter.</jc>
+ * 	<ja>@RestMethod</ja>(...)
+ * 	<jk>public void</jk> login(
+ * 			<ja>@ResponseHeader</ja>(name=<js>"X-Rate-Limit"</js>, type=<js>"integer"</js>, format=<js>"int32"</js>, description=<js>"Calls per hour allowed by the user."</js>, example=<js>"123"</js>) 
+ * 			Value&lt;Integer&gt; rateLimit
+ *		) {
+ *		rateLimit.set(1000);
+ *		...
+ * 	}
+ *
+ *	<jc>// Example #3 - Use on type.</jc>
+ * 	<ja>@RestMethod</ja>(...)
+ * 	<jk>public void</jk> login(RateLimit rateLimit) {
+ * 		rateLimit.set(1000);
+ * 		...
+ * 	} 
+ * 
+ * 	<ja>@ResponseHeader</ja>(name=<js>"X-Rate-Limit"</js>, type=<js>"integer"</js>, format=<js>"int32"</js>, description=<js>"Calls per hour allowed by the user."</js>, example=<js>"123"</js>)
+ * 	<jk>public static class</jk> RateLimit <jk>extends</jk> Value&lt;Integer&gt; {}
+ * </p>
+ */
+@Documented
+@Target({PARAMETER,TYPE})
+@Retention(RUNTIME)
+@Inherited
+public @interface ResponseHeader {
+	
+	/**
+	 * The HTTP status (or statuses) of the response.
+	 * 
+	 * <h5 class='section'>Notes:</h5>
+	 * <ul class='spaced-list'>
+	 * 	<li>
+	 * 		The format of the value is a comma-delimited list of HTTP status codes that this header applies to.
+	 * 	<li>
+	 * 		The default value is <js>"200"</js>.
+	 * </ul>
+	 */
+	String code() default "";
+	
+	/**
+	 * The HTTP header name.
+	 * 
+	 * <h5 class='section'>Notes:</h5>
+	 * <ul class='spaced-list'>
+	 * 	<li>
+	 * 		At least one of {@link #name()} or {@link #value()} must be specified}.
+	 * </ul>
+	 */
+	String name() default "";
+	
+	/**
+	 * A synonym to {@link #name()}.
+	 * 
+	 * <p>
+	 * Useful if you only want to specify a header name.
+	 * 
+	 * <p class='bcode'>
+	 * 	<ja>@RestMethod</ja>(...)
+	 * 	<jk>public void</jk> login(<ja>@ResponseHeader</ja>(<js>"X-Rate-Limit"</js>) Value&lt;Integer&gt; rateLimit) {
+	 *		rateLimit.set(1000);
+	 *		...
+	 * 	}
+	 * </p>
+	 * 
+	 * <h5 class='section'>Notes:</h5>
+	 * <ul class='spaced-list'>
+	 * 	<li>
+	 * 		At least one of {@link #name()} or {@link #value()} must be specified}.
+	 * </ul>
+	 */
+	String value() default "";
+
+	/**
+	 * Specifies the {@link HttpPartSerializer} class used for serializing values.
+	 * 
+	 * <p>
+	 * The default value for this parser is inherited from the servlet/method which defaults to {@link SimpleUonPartSerializer}.
+	 */
+	Class<? extends HttpPartSerializer> serializer() default HttpPartSerializer.Null.class;
+
+	/**
+	 * Defines the swagger value <code>/paths/{path}/{method}/responses/{status-code}/headers/{header-name}/description</code>.
+	 * 
+	 * <h5 class='section'>Notes:</h5>
+	 * <ul class='spaced-list'>
+	 * 	<li>
+	 * 		The format of the value 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 {};
+	
+	/**
+	 * Defines the swagger value <code>/paths/{path}/{method}/responses/{status-code}/headers/{header-name}/type</code>.
+	 * 
+	 * <h5 class='section'>Notes:</h5>
+	 * <ul class='spaced-list'>
+	 * 	<li>
+	 * 		The possible values are:
+	 * 		<ul>
+	 * 			<li><js>"string"</js>
+	 * 			<li><js>"number"</js>
+	 * 			<li><js>"integer"</js>
+	 * 			<li><js>"boolean"</js>
+	 * 			<li><js>"array"</js>
+	 * 		</ul>
+	 * 	<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 type() default "";
+	
+	/**
+	 * Defines the swagger value <code>/paths/{path}/{method}/responses/{status-code}/headers/{header-name}/format</code>.
+	 * 
+	 * <h5 class='section'>Notes:</h5>
+	 * <ul class='spaced-list'>
+	 * 	<li>
+	 * 		The format of the value is plain-text:
+	 * 	<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 format() default "";
+	
+	/**
+	 * Defines the swagger value <code>/paths/{path}/{method}/responses/{status-code}/headers/{header-name}/collectionFormat</code>.
+	 * 
+	 * <h5 class='section'>Notes:</h5>
+	 * <ul class='spaced-list'>
+	 * 	<li>
+	 * 		The possible value are:
+	 * 		<ul>
+	 * 			<li><js>"csv"</js>
+	 * 			<li><js>"ssv"</js>
+	 * 			<li><js>"tsv"</js>
+	 * 			<li><js>"pipes"</js>
+	 * 			<li><js>"multi"</js>
+	 * 		</ul>
+	 * 	<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 collectionFormat() default "";
+	
+	/**
+	 * Defines the swagger value <code>/paths/{path}/{method}/responses/{status-code}/headers/{header-name}/$ref</code>.
+	 * 
+	 * <p>
+	 * Denotes a reference to a definition object.
+	 * 
+	 * <h5 class='section'>Notes:</h5>
+	 * <ul class='spaced-list'>
+	 * 	<li>
+	 * 		The format of the value is plain-text:
+	 * 	<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 $ref() default "";
+	
+	/**
+	 * Defines the swagger value <code>/paths/{path}/{method}/responses/{status-code}/headers/{header-name}/maximum</code>.
+	 * 
+	 * <h5 class='section'>Notes:</h5>
+	 * <ul class='spaced-list'>
+	 * 	<li>
+	 * 		The format of the value is numeric.
+	 * 	<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 maximum() default "";
+	
+	/**
+	 * Defines the swagger value <code>/paths/{path}/{method}/responses/{status-code}/headers/{header-name}/minimum</code>.
+	 * 
+	 * <h5 class='section'>Notes:</h5>
+	 * <ul class='spaced-list'>
+	 * 	<li>
+	 * 		The format of the value is numeric.
+	 * 	<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 minimum() default "";
+	
+	/**
+	 * Defines the swagger value <code>/paths/{path}/{method}/responses/{status-code}/headers/{header-name}/multipleOf</code>.
+	 * 
+	 * <h5 class='section'>Notes:</h5>
+	 * <ul class='spaced-list'>
+	 * 	<li>
+	 * 		The format of the value is numeric.
+	 * 	<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 multipleOf() default "";
+	
+	/**
+	 * Defines the swagger value <code>/paths/{path}/{method}/responses/{status-code}/headers/{header-name}/maxLength</code>.
+	 * 
+	 * <h5 class='section'>Notes:</h5>
+	 * <ul class='spaced-list'>
+	 * 	<li>
+	 * 		The format of the value is numeric.
+	 * 	<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 maxLength() default "";
+	
+	/**
+	 * Defines the swagger value <code>/paths/{path}/{method}/responses/{status-code}/headers/{header-name}/minLength</code>.
+	 * 
+	 * <h5 class='section'>Notes:</h5>
+	 * <ul class='spaced-list'>
+	 * 	<li>
+	 * 		The format of the value is numeric.
+	 * 	<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 minLength() default "";
+	
+	/**
+	 * Defines the swagger value <code>/paths/{path}/{method}/responses/{status-code}/headers/{header-name}/maxItems</code>.
+	 * 
+	 * <h5 class='section'>Notes:</h5>
+	 * <ul class='spaced-list'>
+	 * 	<li>
+	 * 		The format of the value is numeric.
+	 * 	<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 maxItems() default "";
+	
+	/**
+	 * Defines the swagger value <code>/paths/{path}/{method}/responses/{status-code}/headers/{header-name}/minItems</code>.
+	 * 
+	 * <h5 class='section'>Notes:</h5>
+	 * <ul class='spaced-list'>
+	 * 	<li>
+	 * 		The format of the value is numeric.
+	 * 	<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 minItems() default "";
+	
+	/**
+	 * Defines the swagger value <code>/paths/{path}/{method}/responses/{status-code}/headers/{header-name}/exclusiveMaximum</code>.
+	 * 
+	 * <h5 class='section'>Notes:</h5>
+	 * <ul class='spaced-list'>
+	 * 	<li>
+	 * 		The format of the value is numeric.
+	 * 	<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 exclusiveMaximum() default "";
+	
+	/**
+	 * Defines the swagger value <code>/paths/{path}/{method}/responses/{status-code}/headers/{header-name}/exclusiveMimimum</code>.
+	 * 
+	 * <h5 class='section'>Notes:</h5>
+	 * <ul class='spaced-list'>
+	 * 	<li>
+	 * 		The format of the value is numeric.
+	 * 	<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 exclusiveMinimum() default "";
+	
+	/**
+	 * Defines the swagger value <code>/paths/{path}/{method}/responses/{status-code}/headers/{header-name}/uniqueItems</code>.
+	 * 
+	 * <h5 class='section'>Notes:</h5>
+	 * <ul class='spaced-list'>
+	 * 	<li>
+	 * 		The format of the value is boolean.
+	 * 	<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 uniqueItems() default "";
+	
+	/**
+	 * Defines the swagger value <code>/paths/{path}/{method}/responses/{status-code}/headers/{header-name}/items</code>.
+	 * 
+	 * <h5 class='section'>Notes:</h5>
+	 * <ul class='spaced-list'>
+	 * 	<li>
+	 * 		The format of the value is a JSON object.
+	 * 		<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[] items() default {};
+
+	/**
+	 * Defines the swagger value <code>/paths/{path}/{method}/responses/{status-code}/headers/{header-name}/default</code>.
+	 * 
+	 * <h5 class='section'>Notes:</h5>
+	 * <ul class='spaced-list'>
+	 * 	<li>
+	 * 		The format of the value is JSON.
+	 * 		<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[] _default() default {};
+	
+	/**
+	 * Defines the swagger value <code>/paths/{path}/{method}/responses/{status-code}/headers/{header-name}/enum</code>.
+	 * 
+	 * <h5 class='section'>Notes:</h5>
+	 * <ul class='spaced-list'>
+	 * 	<li>
+	 * 		The format of the value is a JSON array or comma-delimited list.
+	 * 		<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[] _enum() default {};
+	
+	/**
+	 * Defines the swagger value <code>/paths/{path}/{method}/responses/{status-code}/headers/{header-name}/x-example</code>.
+	 * 
+	 * <p>
+	 * This attribute defines a JSON representation of the body value that is used by {@link BasicRestInfoProvider} to construct
+	 * media-type-based examples of the header value.
+	 * 
+	 * <h5 class='section'>Notes:</h5>
+	 * <ul class='spaced-list'>
+	 * 	<li>
+	 * 		The format of the value is a JSON object or plain-text string.
+	 * 		<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[] example() default {};
+}
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/helper/RedirectToServletRoot.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/ResponseStatus.java
similarity index 75%
copy from juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/helper/RedirectToServletRoot.java
copy to juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/ResponseStatus.java
index b1acdeb..6413740 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/helper/RedirectToServletRoot.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/ResponseStatus.java
@@ -10,25 +10,28 @@
 // * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
 // * specific language governing permissions and limitations under the License.                                              *
 // ***************************************************************************************************************************
-package org.apache.juneau.rest.helper;
+package org.apache.juneau.rest.annotation;
 
-import org.apache.juneau.rest.annotation.*;
+import static java.lang.annotation.ElementType.*;
+import static java.lang.annotation.RetentionPolicy.*;
+
+import java.lang.annotation.*;
 
 /**
- * Convenience subclass of {@link Redirect} for redirecting a response to the servlet root.
+ * Annotation that can be applied to parameters and types to denote them as an HTTP response status.
  */
-@ResponseInfo(description="Redirect to servlet root")
-public class RedirectToServletRoot extends Redirect {
+@Documented
+@Target({PARAMETER,TYPE})
+@Retention(RUNTIME)
+@Inherited
+public @interface ResponseStatus {
 	
 	/**
-	 * Reusable instance.
+	 * The HTTP status of the response.
 	 */
-	public static final RedirectToServletRoot INSTANCE = new RedirectToServletRoot();
+	int code() default 0;
 	
-	/**
-	 * Constructor.
-	 */
-	public RedirectToServletRoot() {
-		super("servlet:/");
-	}
-}
\ No newline at end of file
+	int value() default 0;
+
+	String[] description() default {};
+}
diff --git a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/InvalidSpecies.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/ResponseStatuses.java
similarity index 74%
copy from juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/InvalidSpecies.java
copy to juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/ResponseStatuses.java
index d856988..d5bbee4 100644
--- a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/InvalidSpecies.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/ResponseStatuses.java
@@ -1,31 +1,27 @@
-// ***************************************************************************************************************************
-// * 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.examples.rest.petstore;
-
-import org.apache.juneau.rest.annotation.*;
-import org.apache.juneau.rest.exception.*;
-
-/**
- * Exception thrown when an invalid species is looked up.
- */
-@SuppressWarnings("serial")
-@ResponseInfo(description="Invalid species provided")
-public class InvalidSpecies extends BadRequest {
-
-	/**
-	 * Constructor.
-	 */
-	public InvalidSpecies() {
-		super("Invalid species provided.");
-	}
-}
+// ***************************************************************************************************************************
+// * 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.annotation;
+
+import static java.lang.annotation.ElementType.*;
+import static java.lang.annotation.RetentionPolicy.*;
+
+import java.lang.annotation.*;
+
+@Documented
+@Target({TYPE})
+@Retention(RUNTIME)
+@Inherited
+public @interface ResponseStatuses {
+
+	ResponseStatus[] value() default {};
+}
\ No newline at end of file
diff --git a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/InvalidSpecies.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/Responses.java
similarity index 74%
copy from juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/InvalidSpecies.java
copy to juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/Responses.java
index d856988..b8c7870 100644
--- a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/InvalidSpecies.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/Responses.java
@@ -1,31 +1,27 @@
-// ***************************************************************************************************************************
-// * 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.examples.rest.petstore;
-
-import org.apache.juneau.rest.annotation.*;
-import org.apache.juneau.rest.exception.*;
-
-/**
- * Exception thrown when an invalid species is looked up.
- */
-@SuppressWarnings("serial")
-@ResponseInfo(description="Invalid species provided")
-public class InvalidSpecies extends BadRequest {
-
-	/**
-	 * Constructor.
-	 */
-	public InvalidSpecies() {
-		super("Invalid species provided.");
-	}
-}
+// ***************************************************************************************************************************
+// * 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.annotation;
+
+import static java.lang.annotation.ElementType.*;
+import static java.lang.annotation.RetentionPolicy.*;
+
+import java.lang.annotation.*;
+
+@Documented
+@Target({TYPE})
+@Retention(RUNTIME)
+@Inherited
+public @interface Responses {
+
+	Response[] value() default {};
+}
\ No newline at end of file
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/exception/BadRequest.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/exception/BadRequest.java
index 0c2a0c1..8416498 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/exception/BadRequest.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/exception/BadRequest.java
@@ -25,7 +25,7 @@ import org.apache.juneau.rest.annotation.*;
  * <p>
  * The server cannot or will not process the request due to an apparent client error (e.g., malformed request syntax, size too large, invalid request message framing, or deceptive request routing).
  */
-@ResponseInfo(
+@Response(
 	code=CODE,
 	description=MESSAGE
 )
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/exception/Conflict.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/exception/Conflict.java
index 2fc9528..3a202e8 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/exception/Conflict.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/exception/Conflict.java
@@ -25,7 +25,7 @@ import org.apache.juneau.rest.annotation.*;
  * <p>
  * Indicates that the request could not be processed because of conflict in the request, such as an edit conflict between multiple simultaneous updates.
  */
-@ResponseInfo(
+@Response(
 	code=CODE,
 	description=MESSAGE
 )
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/exception/ExpectationFailed.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/exception/ExpectationFailed.java
index ba5f1f0..49b9e69 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/exception/ExpectationFailed.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/exception/ExpectationFailed.java
@@ -25,7 +25,7 @@ import org.apache.juneau.rest.annotation.*;
  * <p>
  * The server cannot meet the requirements of the Expect request-header field.
  */
-@ResponseInfo(
+@Response(
 	code=CODE,
 	description=MESSAGE
 )
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/exception/FailedDependency.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/exception/FailedDependency.java
index 97242a7..32f9109 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/exception/FailedDependency.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/exception/FailedDependency.java
@@ -25,7 +25,7 @@ import org.apache.juneau.rest.annotation.*;
  * <p>
  * The request failed because it depended on another request and that request failed (e.g., a PROPPATCH).
  */
-@ResponseInfo(
+@Response(
 	code=CODE,
 	description=MESSAGE
 )
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/exception/Forbidden.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/exception/Forbidden.java
index d019699..bfab8f0 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/exception/Forbidden.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/exception/Forbidden.java
@@ -26,7 +26,7 @@ import org.apache.juneau.rest.annotation.*;
  * The request was valid, but the server is refusing action. 
  * <br>The user might not have the necessary permissions for a resource, or may need an account of some sort.
  */
-@ResponseInfo(
+@Response(
 	code=CODE,
 	description=MESSAGE
 )
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/exception/Gone.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/exception/Gone.java
index beca699..254c615 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/exception/Gone.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/exception/Gone.java
@@ -29,7 +29,7 @@ import org.apache.juneau.rest.annotation.*;
  * <br>Clients such as search engines should remove the resource from their indices.
  * <br>Most use cases do not require clients and search engines to purge the resource, and a <js>"404 Not Found"</js> may be used instead.
  */
-@ResponseInfo(
+@Response(
 	code=CODE,
 	description=MESSAGE
 )
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/exception/HttpVersionNotSupported.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/exception/HttpVersionNotSupported.java
index 31c4319..c735643 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/exception/HttpVersionNotSupported.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/exception/HttpVersionNotSupported.java
@@ -25,7 +25,7 @@ import org.apache.juneau.rest.annotation.*;
  * <p>
  * The server does not support the HTTP protocol version used in the request.
  */
-@ResponseInfo(
+@Response(
 	code=CODE,
 	description=MESSAGE
 )
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/exception/InsufficientStorage.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/exception/InsufficientStorage.java
index fd919ef..8e20322 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/exception/InsufficientStorage.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/exception/InsufficientStorage.java
@@ -25,7 +25,7 @@ import org.apache.juneau.rest.annotation.*;
  * <p>
  * The server is unable to store the representation needed to complete the request.
  */
-@ResponseInfo(
+@Response(
 	code=CODE,
 	description=MESSAGE
 )
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/exception/InternalServerError.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/exception/InternalServerError.java
index 9d53925..a530016 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/exception/InternalServerError.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/exception/InternalServerError.java
@@ -25,7 +25,7 @@ import org.apache.juneau.rest.annotation.*;
  * <p>
  * A generic error message, given when an unexpected condition was encountered and no more specific message is suitable.
  */
-@ResponseInfo(
+@Response(
 	code=CODE,
 	description=MESSAGE
 )
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/exception/LengthRequired.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/exception/LengthRequired.java
index be37718..fa2d5d8 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/exception/LengthRequired.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/exception/LengthRequired.java
@@ -25,7 +25,7 @@ import org.apache.juneau.rest.annotation.*;
  * <p>
  * The request did not specify the length of its content, which is required by the requested resource.
  */
-@ResponseInfo(
+@Response(
 	code=CODE,
 	description=MESSAGE
 )
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/exception/Locked.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/exception/Locked.java
index 65df3d3..2d1403d 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/exception/Locked.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/exception/Locked.java
@@ -25,7 +25,7 @@ import org.apache.juneau.rest.annotation.*;
  * <p>
  * The resource that is being accessed is locked.
  */
-@ResponseInfo(
+@Response(
 	code=CODE,
 	description=MESSAGE
 )
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/exception/LoopDetected.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/exception/LoopDetected.java
index 2f0c88d..2a61ebb 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/exception/LoopDetected.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/exception/LoopDetected.java
@@ -25,7 +25,7 @@ import org.apache.juneau.rest.annotation.*;
  * <p>
  * The server detected an infinite loop while processing the request (sent in lieu of 208 Already Reported).
  */
-@ResponseInfo(
+@Response(
 	code=CODE,
 	description=MESSAGE
 )
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/exception/MethodNotAllowed.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/exception/MethodNotAllowed.java
index f3c54f4..0415f64 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/exception/MethodNotAllowed.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/exception/MethodNotAllowed.java
@@ -25,7 +25,7 @@ import org.apache.juneau.rest.annotation.*;
  * <p>
  * A request method is not supported for the requested resource; for example, a GET request on a form that requires data to be presented via POST, or a PUT request on a read-only resource.
  */
-@ResponseInfo(
+@Response(
 	code=CODE,
 	description=MESSAGE
 )
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/exception/MisdirectedRequest.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/exception/MisdirectedRequest.java
index 174a3c6..2531134 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/exception/MisdirectedRequest.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/exception/MisdirectedRequest.java
@@ -25,7 +25,7 @@ import org.apache.juneau.rest.annotation.*;
  * <p>
  * The request was directed at a server that is not able to produce a response (for example because of connection reuse).
  */
-@ResponseInfo(
+@Response(
 	code=CODE,
 	description=MESSAGE
 )
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/exception/NetworkAuthenticationRequired.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/exception/NetworkAuthenticationRequired.java
index cd1a77a..0437013 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/exception/NetworkAuthenticationRequired.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/exception/NetworkAuthenticationRequired.java
@@ -26,7 +26,7 @@ import org.apache.juneau.rest.annotation.*;
  * The client needs to authenticate to gain network access. 
  * <br>Intended for use by intercepting proxies used to control access to the network (e.g., "captive portals" used to require agreement to Terms of Service before granting full Internet access via a Wi-Fi hotspot).
  */
-@ResponseInfo(
+@Response(
 	code=CODE,
 	description=MESSAGE
 )
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/exception/NotAcceptable.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/exception/NotAcceptable.java
index 44dd802..11652e9 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/exception/NotAcceptable.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/exception/NotAcceptable.java
@@ -25,7 +25,7 @@ import org.apache.juneau.rest.annotation.*;
  * <br>
  * The requested resource is capable of generating only content not acceptable according to the Accept headers sent in the request.
  */
-@ResponseInfo(
+@Response(
 	code=CODE,
 	description=MESSAGE
 )
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/exception/NotExtended.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/exception/NotExtended.java
index 834f609..58f0e0a 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/exception/NotExtended.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/exception/NotExtended.java
@@ -25,7 +25,7 @@ import org.apache.juneau.rest.annotation.*;
  * <p>
  * Further extensions to the request are required for the server to fulfill it.
  */
-@ResponseInfo(
+@Response(
 	code=CODE,
 	description=MESSAGE
 )
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/exception/NotFound.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/exception/NotFound.java
index 42aefab..fb551fb 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/exception/NotFound.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/exception/NotFound.java
@@ -26,7 +26,7 @@ import org.apache.juneau.rest.annotation.*;
  * The requested resource could not be found but may be available in the future. 
  * <br>Subsequent requests by the client are permissible.
  */
-@ResponseInfo(
+@Response(
 	code=CODE,
 	description=MESSAGE
 )
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/exception/NotImplemented.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/exception/NotImplemented.java
index 184d117..342fa22 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/exception/NotImplemented.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/exception/NotImplemented.java
@@ -26,7 +26,7 @@ import org.apache.juneau.rest.annotation.*;
  * The server either does not recognize the request method, or it lacks the ability to fulfill the request. 
  * <br>Usually this implies future availability (e.g., a new feature of a web-service API).
  */
-@ResponseInfo(
+@Response(
 	code=CODE,
 	description=MESSAGE
 )
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/exception/PayloadTooLarge.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/exception/PayloadTooLarge.java
index 90f5855..2e9d0ad 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/exception/PayloadTooLarge.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/exception/PayloadTooLarge.java
@@ -25,7 +25,7 @@ import org.apache.juneau.rest.annotation.*;
  * <p>
  * The request is larger than the server is willing or able to process. 
  */
-@ResponseInfo(
+@Response(
 	code=CODE,
 	description=MESSAGE
 )
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/exception/PreconditionFailed.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/exception/PreconditionFailed.java
index a9e806c..3e39ae1 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/exception/PreconditionFailed.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/exception/PreconditionFailed.java
@@ -25,7 +25,7 @@ import org.apache.juneau.rest.annotation.*;
  * <p>
  * The server does not meet one of the preconditions that the requester put on the request.
  */
-@ResponseInfo(
+@Response(
 	code=CODE,
 	description=MESSAGE
 )
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/exception/PreconditionRequired.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/exception/PreconditionRequired.java
index 00f90df..c66222e 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/exception/PreconditionRequired.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/exception/PreconditionRequired.java
@@ -26,7 +26,7 @@ import org.apache.juneau.rest.annotation.*;
  * The origin server requires the request to be conditional. 
  * <br>Intended to prevent the 'lost update' problem, where a client GETs a resource's state, modifies it, and PUTs it back to the server, when meanwhile a third party has modified the state on the server, leading to a conflict.
  */
-@ResponseInfo(
+@Response(
 	code=CODE,
 	description=MESSAGE
 )
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/exception/RangeNotSatisfiable.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/exception/RangeNotSatisfiable.java
index 953fdef..49ff505 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/exception/RangeNotSatisfiable.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/exception/RangeNotSatisfiable.java
@@ -26,7 +26,7 @@ import org.apache.juneau.rest.annotation.*;
  * The client has asked for a portion of the file (byte serving), but the server cannot supply that portion. 
  * <br>For example, if the client asked for a part of the file that lies beyond the end of the file.
  */
-@ResponseInfo(
+@Response(
 	code=CODE,
 	description=MESSAGE
 )
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/exception/RequestHeaderFieldsTooLarge.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/exception/RequestHeaderFieldsTooLarge.java
index 398a63c..9a83dbf 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/exception/RequestHeaderFieldsTooLarge.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/exception/RequestHeaderFieldsTooLarge.java
@@ -25,7 +25,7 @@ import org.apache.juneau.rest.annotation.*;
  * <p>
  * The server is unwilling to process the request because either an individual header field, or all the header fields collectively, are too large.
  */
-@ResponseInfo(
+@Response(
 	code=CODE,
 	description=MESSAGE
 )
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/exception/ServiceUnavailable.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/exception/ServiceUnavailable.java
index 2628e37..5e80977 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/exception/ServiceUnavailable.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/exception/ServiceUnavailable.java
@@ -26,7 +26,7 @@ import org.apache.juneau.rest.annotation.*;
  * The server is currently unavailable (because it is overloaded or down for maintenance). 
  * <br>Generally, this is a temporary state.
  */
-@ResponseInfo(
+@Response(
 	code=CODE,
 	description=MESSAGE
 )
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/exception/TooManyRequests.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/exception/TooManyRequests.java
index 275067c..3dff3b1 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/exception/TooManyRequests.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/exception/TooManyRequests.java
@@ -26,7 +26,7 @@ import org.apache.juneau.rest.annotation.*;
  * The user has sent too many requests in a given amount of time. 
  * <br>Intended for use with rate-limiting schemes.
  */
-@ResponseInfo(
+@Response(
 	code=CODE,
 	description=MESSAGE
 )
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/exception/Unauthorized.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/exception/Unauthorized.java
index fecbc8a..49f27f6 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/exception/Unauthorized.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/exception/Unauthorized.java
@@ -28,7 +28,7 @@ import org.apache.juneau.rest.annotation.*;
  * <br>401 semantically means "unauthenticated",i.e. the user does not have the necessary credentials.
  * <br>Note: Some sites issue HTTP 401 when an IP address is banned from the website (usually the website domain) and that specific address is refused permission to access a website.
  */
-@ResponseInfo(
+@Response(
 	code=CODE,
 	description=MESSAGE
 )
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/exception/UnavailableForLegalReasons.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/exception/UnavailableForLegalReasons.java
index d84de7e..5b2f6dc 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/exception/UnavailableForLegalReasons.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/exception/UnavailableForLegalReasons.java
@@ -25,7 +25,7 @@ import org.apache.juneau.rest.annotation.*;
  * <p>
  * A server operator has received a legal demand to deny access to a resource or to a set of resources that includes the requested resource.
  */
-@ResponseInfo(
+@Response(
 	code=CODE,
 	description=MESSAGE
 )
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/exception/UnprocessableEntity.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/exception/UnprocessableEntity.java
index 8e81565..635e6a3 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/exception/UnprocessableEntity.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/exception/UnprocessableEntity.java
@@ -25,7 +25,7 @@ import org.apache.juneau.rest.annotation.*;
  * <p>
  * The request was well-formed but was unable to be followed due to semantic errors.
  */
-@ResponseInfo(
+@Response(
 	code=CODE,
 	description=MESSAGE
 )
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/exception/UnsupportedMediaType.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/exception/UnsupportedMediaType.java
index 2074e5c..c5c29e8 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/exception/UnsupportedMediaType.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/exception/UnsupportedMediaType.java
@@ -26,7 +26,7 @@ import org.apache.juneau.rest.annotation.*;
  * The request entity has a media type which the server or resource does not support. 
  * <br>For example, the client uploads an image as image/svg+xml, but the server requires that images use a different format.
  */
-@ResponseInfo(
+@Response(
 	code=CODE,
 	description=MESSAGE
 )
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/exception/UpgradeRequired.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/exception/UpgradeRequired.java
index b047ab8..5f84ea4 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/exception/UpgradeRequired.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/exception/UpgradeRequired.java
@@ -25,7 +25,7 @@ import org.apache.juneau.rest.annotation.*;
  * <p>
  * The client should switch to a different protocol such as TLS/1.0, given in the Upgrade header field.
  */
-@ResponseInfo(
+@Response(
 	code=CODE,
 	description=MESSAGE
 )
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/exception/UriTooLong.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/exception/UriTooLong.java
index 5edee8b..fad2e41 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/exception/UriTooLong.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/exception/UriTooLong.java
@@ -26,7 +26,7 @@ import org.apache.juneau.rest.annotation.*;
  * The URI provided was too long for the server to process. 
  * <br>Often the result of too much data being encoded as a query-string of a GET request, in which case it should be converted to a POST request.
  */
-@ResponseInfo(
+@Response(
 	code=CODE,
 	description=MESSAGE
 )
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/exception/VariantAlsoNegotiates.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/exception/VariantAlsoNegotiates.java
index d413cd8..cde7b29 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/exception/VariantAlsoNegotiates.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/exception/VariantAlsoNegotiates.java
@@ -25,7 +25,7 @@ import org.apache.juneau.rest.annotation.*;
  * <p>
  * Transparent content negotiation for the request results in a circular reference.
  */
-@ResponseInfo(
+@Response(
 	code=CODE,
 	description=MESSAGE
 )
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/helper/Ok.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/helper/Ok.java
index 99c7d85..2bb09a8 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/helper/Ok.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/helper/Ok.java
@@ -20,7 +20,7 @@ import org.apache.juneau.rest.annotation.*;
  * <p>
  * The response consist of the serialized string <js>"OK"</js>.
  */
-@ResponseInfo(code=200, example="'OK'")
+@Response(code=200, example="'OK'")
 public class Ok {
 	
 	/**
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/helper/Redirect.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/helper/Redirect.java
index 3dcd402..6495b72 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/helper/Redirect.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/helper/Redirect.java
@@ -27,7 +27,7 @@ import org.apache.juneau.rest.annotation.*;
  * 	<li class='link'><a class="doclink" href="../../../../overview-summary.html#juneau-rest-server.Redirect">Overview &gt; juneau-rest-server &gt; Redirect</a>
  * </ul>
  */
-@ResponseInfo(code=302, description="Redirect", headers={"Location:{description:'Redirect URI', type:'string', format:'uri'}"}, schema="IGNORE")
+@Response(code=302, description="Redirect", headers={"Location:{description:'Redirect URI', type:'string', format:'uri'}"}, schema="IGNORE")
 public class Redirect {
 
 	private final int httpResponseCode;
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/helper/RedirectToServletRoot.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/helper/RedirectToServletRoot.java
index b1acdeb..3c721e1 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/helper/RedirectToServletRoot.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/helper/RedirectToServletRoot.java
@@ -17,7 +17,7 @@ import org.apache.juneau.rest.annotation.*;
 /**
  * Convenience subclass of {@link Redirect} for redirecting a response to the servlet root.
  */
-@ResponseInfo(description="Redirect to servlet root")
+@Response(description="Redirect to servlet root")
 public class RedirectToServletRoot extends Redirect {
 	
 	/**
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/helper/ResourceDescription.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/helper/ResourceDescription.java
index d419358..732e506 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/helper/ResourceDescription.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/helper/ResourceDescription.java
@@ -30,7 +30,7 @@ import org.apache.juneau.rest.annotation.*;
  * </ul>
  */
 @Bean(properties="name,description", fluentSetters=true)
-@ResponseInfo(schema="IGNORE")
+@Response(schema="IGNORE")
 public final class ResourceDescription implements Comparable<ResourceDescription> {
 
 	private String name, description;

-- 
To stop receiving notification emails like this one, please contact
jamesbognar@apache.org.