REST refactoring.
diff --git a/juneau-core/juneau-core-utest/src/test/java/org/apache/juneau/utils/MethodInvokerTest.java b/juneau-core/juneau-core-utest/src/test/java/org/apache/juneau/utils/MethodInvokerTest.java
index 608e808..bad0383 100644
--- a/juneau-core/juneau-core-utest/src/test/java/org/apache/juneau/utils/MethodInvokerTest.java
+++ b/juneau-core/juneau-core-utest/src/test/java/org/apache/juneau/utils/MethodInvokerTest.java
@@ -83,7 +83,7 @@
 
 		assertEquals(m, mi.inner().inner());
 		assertEquals("A", mi.getDeclaringClass().getSimpleName());
-		assertEquals("foo", mi.getName());
+		assertEquals(A.class.getName() + ".foo()", mi.getFullName());
 	}
 
 }
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/StringUtils.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/StringUtils.java
index f87d395..9e035fa 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/StringUtils.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/StringUtils.java
@@ -2428,7 +2428,13 @@
 		Object[] args2 = new Object[args.length];

 		for (int i = 0; i < args.length; i++)

 			args2[i] = convertToReadable(args[i]);

-		return MessageFormat.format(pattern, args2);

+

+		int c = countChars(pattern, '\'');

+		if (c % 2 != 0)

+			throw new AssertionError("Dangling single quote found in pattern: " + pattern);

+

+		String msg = MessageFormat.format(pattern, args2);

+		return msg;

 	}

 

 	private static String convertToReadable(Object o) {

diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/reflect/ClassInfo.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/reflect/ClassInfo.java
index ac5e52b..7a4cdaa 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/reflect/ClassInfo.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/reflect/ClassInfo.java
@@ -2353,6 +2353,15 @@
 		return c != null && c.isAnnotation();
 	}
 
+	/**
+	 * Returns <jk>true</jk> if this class is a {@link Collection} or an array.
+	 *
+	 * @return <jk>true</jk> if this class is a {@link Collection} or an array.
+	 */
+	public boolean isCollectionOrArray() {
+		return c != null && (Collection.class.isAssignableFrom(c) || c.isArray());
+	}
+
 	//-----------------------------------------------------------------------------------------------------------------
 	// Instantiation
 	//-----------------------------------------------------------------------------------------------------------------
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/reflect/ParamInfo.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/reflect/ParamInfo.java
index 3d95f76..8d92627 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/reflect/ParamInfo.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/reflect/ParamInfo.java
@@ -234,6 +234,16 @@
 	//-----------------------------------------------------------------------------------------------------------------
 
 	/**
+	 * Returns <jk>true</jk> if the parameter type is an exact match for the specified class.
+	 * 
+	 * @param c The type to check.
+	 * @return <jk>true</jk> if the parameter type is an exact match for the specified class.
+	 */
+	public boolean isType(Class<?> c) {
+		return getParameterType().is(c);
+	}
+
+	/**
 	 * Returns <jk>true</jk> if the parameter has a name provided by the class file.
 	 *
 	 * @return <jk>true</jk> if the parameter has a name provided by the class file.
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/utils/MethodInvoker.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/utils/MethodInvoker.java
index 91006cd..af0ae2c 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/utils/MethodInvoker.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/utils/MethodInvoker.java
@@ -85,7 +85,7 @@
 		missing = beanFactory.getMissingParamTypes(m.getParamTypes());
 		if (missing.isEmpty())
 			return invoke(o, beanFactory.getParams(m.getParamTypes()));
-		throw new ExecutableException("Could not find prerequisites to invoke method ''{0}'': {1}", m.getFullName(), missing.stream().map(x->x.getSimpleName()).collect(Collectors.joining(",")));
+		throw new ExecutableException("Could not find prerequisites to invoke method ''{0}'': {1}", getFullName(), missing.stream().map(x->x.getSimpleName()).collect(Collectors.joining(",")));
 	}
 
 	/**
@@ -102,7 +102,7 @@
 	 *
 	 * @return The name of the method.
 	 */
-	public String getName() {
-		return m.getName();
+	public String getFullName() {
+		return m.getFullName();
 	}
 }
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/utils/ThrowingFunction.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/utils/ThrowingFunction.java
new file mode 100644
index 0000000..f57ca9c
--- /dev/null
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/utils/ThrowingFunction.java
@@ -0,0 +1,45 @@
+// ***************************************************************************************************************************
+// * 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.utils;
+
+import java.util.function.*;
+
+/**
+ * A subclass of {@link Function} that allows for thrown exceptions.
+ *
+ * @param <T> the type of the input to the function.
+ * @param <R> the type of the result of the function.
+ */
+@FunctionalInterface
+public interface ThrowingFunction<T,R> extends Function<T,R> {
+
+	@Override
+	default R apply(T t) {
+		try {
+			return applyThrows(t);
+		} catch (RuntimeException e) {
+			throw e;
+		} catch (Exception e) {
+			throw new RuntimeException(e);
+		}
+	}
+
+	/**
+	 * The functional method to implement.
+	 *
+	 * @param t The type of the input to the function.
+	 * @return The type of the result of the function.
+	 * @throws Exception
+	 */
+	R applyThrows(T t) throws Exception;
+}
diff --git a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/RestMethod_Params_Test.java b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/RestMethod_Params_Test.java
index 5a86bf2..00bdaf8 100644
--- a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/RestMethod_Params_Test.java
+++ b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/RestMethod_Params_Test.java
@@ -30,6 +30,7 @@
 import org.apache.juneau.json.*;
 import org.apache.juneau.parser.*;
 import org.apache.juneau.plaintext.*;
+import org.apache.juneau.reflect.*;
 import org.apache.juneau.rest.annotation.*;
 import org.apache.juneau.rest.client.*;
 import org.apache.juneau.rest.mock.*;
@@ -366,7 +367,7 @@
 	//------------------------------------------------------------------------------------------------------------------
 
 	@Rest(
-		paramResolvers=B2a.class,
+		restParams=B2a.class,
 		allowedHeaderParams="Custom"
 	)
 	public static class B2 {
@@ -376,10 +377,14 @@
 		}
 	}
 
-	public static class B2a extends RestMethodParam {
-		public B2a() {
-			super(RestParamType.HEADER, "Custom", B2b.class);
+	public static class B2a implements RestParam {
+
+		public static B2a create(ParamInfo pi) {
+			if (pi.isType(B2b.class))
+				return new B2a();
+			return null;
 		}
+
 		@Override
 		public Object resolve(RestCall call) throws Exception {
 			return new B2b(call.getRestRequest().getHeader("Custom"));
diff --git a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/RestAnnotation_Test.java b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/RestAnnotation_Test.java
index 5a3bcfd..67fb3ab 100644
--- a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/RestAnnotation_Test.java
+++ b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/RestAnnotation_Test.java
@@ -66,7 +66,6 @@
 		.messages("messages")
 		.on("on")
 		.onClass(RestAnnotation_Test.class)
-		.paramResolvers(RestMethodParam.class)
 		.parsers(Parser.class)
 		.partParser(HttpPartParser.class)
 		.partSerializer(HttpPartSerializer.class)
@@ -74,6 +73,7 @@
 		.produces("produces")
 		.renderResponseStackTraces("renderResponseStackTraces")
 		.responseHandlers(ResponseHandler.class)
+		.restParams(RestParam.class)
 		.roleGuard("roleGuard")
 		.rolesDeclared("rolesDeclared")
 		.serializers(Serializer.class)
@@ -117,7 +117,6 @@
 		.messages("messages")
 		.on("on")
 		.onClass(RestAnnotation_Test.class)
-		.paramResolvers(RestMethodParam.class)
 		.parsers(Parser.class)
 		.partParser(HttpPartParser.class)
 		.partSerializer(HttpPartSerializer.class)
@@ -125,6 +124,7 @@
 		.produces("produces")
 		.renderResponseStackTraces("renderResponseStackTraces")
 		.responseHandlers(ResponseHandler.class)
+		.restParams(RestParam.class)
 		.roleGuard("roleGuard")
 		.rolesDeclared("rolesDeclared")
 		.serializers(Serializer.class)
@@ -171,7 +171,6 @@
 				+ "messages:'messages',"
 				+ "on:['on'],"
 				+ "onClass:['"+CNAME+"'],"
-				+ "paramResolvers:['org.apache.juneau.rest.RestMethodParam'],"
 				+ "parsers:['org.apache.juneau.parser.Parser'],"
 				+ "partParser:'org.apache.juneau.httppart.HttpPartParser',"
 				+ "partSerializer:'org.apache.juneau.httppart.HttpPartSerializer',"
@@ -179,6 +178,7 @@
 				+ "produces:['produces'],"
 				+ "renderResponseStackTraces:'renderResponseStackTraces',"
 				+ "responseHandlers:['org.apache.juneau.rest.ResponseHandler'],"
+				+ "restParams:['org.apache.juneau.rest.RestParam'],"
 				+ "roleGuard:'roleGuard',"
 				+ "rolesDeclared:'rolesDeclared',"
 				+ "serializers:['org.apache.juneau.serializer.Serializer'],"
@@ -267,7 +267,6 @@
 		messages="messages",
 		on="on",
 		onClass=RestAnnotation_Test.class,
-		paramResolvers=RestMethodParam.class,
 		parsers=Parser.class,
 		partParser=HttpPartParser.class,
 		partSerializer=HttpPartSerializer.class,
@@ -275,6 +274,7 @@
 		produces="produces",
 		renderResponseStackTraces="renderResponseStackTraces",
 		responseHandlers=ResponseHandler.class,
+		restParams=RestParam.class,
 		roleGuard="roleGuard",
 		rolesDeclared="rolesDeclared",
 		serializers=Serializer.class,
@@ -320,7 +320,6 @@
 		messages="messages",
 		on="on",
 		onClass=RestAnnotation_Test.class,
-		paramResolvers=RestMethodParam.class,
 		parsers=Parser.class,
 		partParser=HttpPartParser.class,
 		partSerializer=HttpPartSerializer.class,
@@ -328,6 +327,7 @@
 		produces="produces",
 		renderResponseStackTraces="renderResponseStackTraces",
 		responseHandlers=ResponseHandler.class,
+		restParams=RestParam.class,
 		roleGuard="roleGuard",
 		rolesDeclared="rolesDeclared",
 		serializers=Serializer.class,
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RequestBody.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RequestBody.java
index 61645c7..73dfae0 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RequestBody.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RequestBody.java
@@ -68,7 +68,13 @@
 		return this;
 	}
 
-	RequestBody schema(HttpPartSchema schema) {
+	/**
+	 * Sets the schema for this body.
+	 *
+	 * @param schema The new schema for this body.
+	 * @return This object (for method chaining).
+	 */
+	public RequestBody schema(HttpPartSchema schema) {
 		this.schema = schema;
 		return this;
 	}
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 8e44a99..160fdea 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
@@ -47,14 +47,6 @@
 import org.apache.juneau.html.*;

 import org.apache.juneau.html.annotation.*;

 import org.apache.juneau.http.*;

-import org.apache.juneau.http.annotation.*;

-import org.apache.juneau.http.annotation.Body;

-import org.apache.juneau.http.annotation.FormData;

-import org.apache.juneau.http.annotation.HasFormData;

-import org.apache.juneau.http.annotation.HasQuery;

-import org.apache.juneau.http.annotation.Header;

-import org.apache.juneau.http.annotation.Path;

-import org.apache.juneau.http.annotation.Query;

 import org.apache.juneau.http.annotation.Response;

 import org.apache.juneau.httppart.*;

 import org.apache.juneau.httppart.bean.*;

@@ -69,6 +61,7 @@
 import org.apache.juneau.rest.annotation.*;

 import org.apache.juneau.rest.converters.*;

 import org.apache.juneau.rest.logging.*;

+import org.apache.juneau.rest.params.*;

 import org.apache.juneau.http.exception.*;

 import org.apache.juneau.http.remote.*;

 import org.apache.juneau.rest.reshandlers.*;

@@ -1482,98 +1475,6 @@
 	public static final String REST_messages = PREFIX + ".messages.lo";

 

 	/**

-	 * Configuration property:  Java method parameter resolvers.

-	 *

-	 * <h5 class='section'>Property:</h5>

-	 * <ul class='spaced-list'>

-	 * 	<li><b>ID:</b>  {@link org.apache.juneau.rest.RestContext#REST_paramResolvers REST_paramResolvers}

-	 * 	<li><b>Name:</b>  <js>"RestContext.paramResolvers.lo"</js>

-	 * 	<li><b>Data type:</b>  <c>List&lt;{@link org.apache.juneau.rest.RestMethodParam}|Class&lt;{@link org.apache.juneau.rest.RestMethodParam}&gt;&gt;</c>

-	 * 	<li><b>Default:</b>  empty list

-	 * 	<li><b>Session property:</b>  <jk>false</jk>

-	 * 	<li><b>Annotations:</b>

-	 * 		<ul>

-	 * 			<li class='ja'>{@link org.apache.juneau.rest.annotation.Rest#paramResolvers()}

-	 * 		</ul>

-	 * 	<li><b>Methods:</b>

-	 * 		<ul>

-	 * 			<li class='jm'>{@link org.apache.juneau.rest.RestContextBuilder#paramResolvers(Class...)}

-	 * 			<li class='jm'>{@link org.apache.juneau.rest.RestContextBuilder#paramResolvers(RestMethodParam...)}

-	 * 		</ul>

-	 * </ul>

-	 *

-	 * <h5 class='section'>Description:</h5>

-	 * <p>

-	 * By default, the Juneau framework will automatically Java method parameters of various types (e.g.

-	 * <c>RestRequest</c>, <c>Accept</c>, <c>Reader</c>).

-	 * This setting allows you to provide your own resolvers for your own class types that you want resolved.

-	 *

-	 * <p>

-	 * For example, if you want to pass in instances of <c>MySpecialObject</c> to your Java method, define

-	 * the following resolver:

-	 * <p class='bcode w800'>

-	 * 	<jc>// Define a parameter resolver for resolving MySpecialObject objects.</jc>

-	 * 	<jk>public class</jk> MyRestParam <jk>extends</jk> RestMethodParam {

-	 *

-	 * 		<jc>// Must have no-arg constructor!</jc>

-	 * 		<jk>public</jk> MyRestParam() {

-	 * 			<jc>// First two parameters help with Swagger doc generation.</jc>

-	 * 			<jk>super</jk>(<jsf>QUERY</jsf>, <js>"myparam"</js>, MySpecialObject.<jk>class</jk>);

-	 * 		}

-	 *

-	 * 		<jc>// The method that creates our object.

-	 * 		// In this case, we're taking in a query parameter and converting it to our object.</jc>

-	 * 		<jk>public</jk> Object resolve(RestRequest req, RestResponse res) <jk>throws</jk> Exception {

-	 * 			<jk>return new</jk> MySpecialObject(req.getQuery().get(<js>"myparam"</js>));

-	 * 		}

-	 * 	}

-	 *

-	 * 	<jc>// Option #1 - Registered via annotation.</jc>

-	 * 	<ja>@Rest</ja>(paramResolvers=MyRestParam.<jk>class</jk>)

-	 * 	<jk>public class</jk> MyResource {

-	 *

-	 * 		<jc>// Option #2 - Registered via builder passed in through resource constructor.</jc>

-	 * 		<jk>public</jk> MyResource(RestContextBuilder builder) <jk>throws</jk> Exception {

-	 *

-	 * 			<jc>// Using method on builder.</jc>

-	 * 			builder.paramResolvers(MyRestParam.<jk>class</jk>);

-	 *

-	 * 			<jc>// Same, but using property.</jc>

-	 * 			builder.addTo(<jsf>REST_paramResolver</jsf>, MyRestParam.<jk>class</jk>);

-	 * 		}

-	 *

-	 * 		<jc>// Option #3 - Registered via builder passed in through init method.</jc>

-	 * 		<ja>@RestHook</ja>(<jsf>INIT</jsf>)

-	 * 		<jk>public void</jk> init(RestContextBuilder builder) <jk>throws</jk> Exception {

-	 * 			builder.paramResolvers(MyRestParam.<jk>class</jk>);

-	 * 		}

-	 *

-	 * 		<jc>// Now pass it into your method.</jc>

-	 * 		<ja>@RestMethod</ja>(...)

-	 * 		<jk>public</jk> Object doMyMethod(MySpecialObject mySpeciaObject) {

-	 * 			<jc>// Do something with it.</jc>

-	 * 		}

-	 * 	}

-	 * </p>

-	 *

-	 * <ul class='notes'>

-	 * 	<li>

-	 * 		When defined as a class, the implementation must have one of the following constructors:

-	 * 		<ul>

-	 * 			<li><code><jk>public</jk> T(BeanContext)</code>

-	 * 			<li><code><jk>public</jk> T()</code>

-	 * 			<li><code><jk>public static</jk> T <jsm>create</jsm>(RestContext)</code>

-	 * 			<li><code><jk>public static</jk> T <jsm>create</jsm>()</code>

-	 * 		</ul>

-	 * 	<li>

-	 * 		Inner classes of the REST resource class are allowed.

-	 * 	<li>

-	 * 		Refer to {@link RestMethodParam} for the list of predefined parameter resolvers.

-	 * </ul>

-	 */

-	public static final String REST_paramResolvers = PREFIX + ".paramResolvers.lo";

-

-	/**

 	 * Configuration property:  Parsers.

 	 *

 	 * <h5 class='section'>Property:</h5>

@@ -2325,6 +2226,94 @@
 	public static final String REST_responseHandlers = PREFIX + ".responseHandlers.lo";

 

 	/**

+	 * Configuration property:  Java REST method parameter resolvers.

+	 *

+	 * <h5 class='section'>Property:</h5>

+	 * <ul class='spaced-list'>

+	 * 	<li><b>ID:</b>  {@link org.apache.juneau.rest.RestContext#REST_restParams REST_restParams}

+	 * 	<li><b>Name:</b>  <js>"RestContext.restParams.lo"</js>

+	 * 	<li><b>Data type:</b>  <c>List&lt;Class&lt;{@link org.apache.juneau.rest.RestParam}&gt;&gt;</c>

+	 * 	<li><b>Default:</b>  empty list

+	 * 	<li><b>Session property:</b>  <jk>false</jk>

+	 * 	<li><b>Annotations:</b>

+	 * 		<ul>

+	 * 			<li class='ja'>{@link org.apache.juneau.rest.annotation.Rest#restParams()}

+	 * 		</ul>

+	 * 	<li><b>Methods:</b>

+	 * 		<ul>

+	 * 			<li class='jm'>{@link org.apache.juneau.rest.RestContextBuilder#restParams(Class...)}

+	 * 		</ul>

+	 * </ul>

+	 *

+	 * <h5 class='section'>Description:</h5>

+	 * <p>

+	 * By default, the Juneau framework will automatically Java method parameters of various types (e.g.

+	 * <c>RestRequest</c>, <c>Accept</c>, <c>Reader</c>).

+	 * This setting allows you to provide your own resolvers for your own class types that you want resolved.

+	 *

+	 * <p>

+	 * For example, if you want to pass in instances of <c>MySpecialObject</c> to your Java method, define

+	 * the following resolver:

+	 * <p class='bcode w800'>

+	 * 	<jc>// Define a parameter resolver for resolving MySpecialObject objects.</jc>

+	 * 	<jk>public class</jk> MyRestParam <jk>implements</jk> RestParam {

+	 *

+	 *		<jc>// Must implement a static creator method that takes in a ParamInfo that describes the parameter

+	 *		// being checked.  If the parameter isn't of type MySpecialObject, then it should return null.</jc>

+	 *		<jk>public static</jk> MyRestParam <jsm>create</jsm>(ParamInfo <jv>paramInfo</jv>) {

+	 *			<jk>if</jk> (<jv>paramInfo</jv>.isType(MySpecialObject.<jk>class</jk>)

+	 *				<jk>return new</jk> MyRestParam();

+	 *			<jk>return null</jk>;

+	 *		}

+	 *

+	 * 		<jk>public</jk> MyRestParam() {}

+	 *

+	 * 		<jc>// The method that creates our object.

+	 * 		// In this case, we're taking in a query parameter and converting it to our object.</jc>

+	 * 		<ja>@Override</ja>

+	 * 		<jk>public</jk> Object resolve(RestCall <jv>call</jv>) <jk>throws</jk> Exception {

+	 * 			<jk>return new</jk> MySpecialObject(<jv>call</jv>.getRestRequest().getQuery().get(<js>"myparam"</js>));

+	 * 		}

+	 * 	}

+	 *

+	 * 	<jc>// Option #1 - Registered via annotation.</jc>

+	 * 	<ja>@Rest</ja>(restParams=MyRestParam.<jk>class</jk>)

+	 * 	<jk>public class</jk> MyResource {

+	 *

+	 * 		<jc>// Option #2 - Registered via builder passed in through resource constructor.</jc>

+	 * 		<jk>public</jk> MyResource(RestContextBuilder <jv>builder</jv>) <jk>throws</jk> Exception {

+	 *

+	 * 			<jc>// Using method on builder.</jc>

+	 * 			<jv>builder</jv>.restParams(MyRestParam.<jk>class</jk>);

+	 *

+	 * 			<jc>// Same, but using property.</jc>

+	 * 			<jv>builder</jv>.addTo(<jsf>REST_restParams</jsf>, MyRestParam.<jk>class</jk>);

+	 * 		}

+	 *

+	 * 		<jc>// Option #3 - Registered via builder passed in through init method.</jc>

+	 * 		<ja>@RestHook</ja>(<jsf>INIT</jsf>)

+	 * 		<jk>public void</jk> init(RestContextBuilder <jv>builder</jv>) <jk>throws</jk> Exception {

+	 * 			<jv>builder</jv>.restParams(MyRestParam.<jk>class</jk>);

+	 * 		}

+	 *

+	 * 		<jc>// Now pass it into your method.</jc>

+	 * 		<ja>@RestMethod</ja>(...)

+	 * 		<jk>public</jk> Object doMyMethod(MySpecialObject <jv>mySpecialObject</jv>) {

+	 * 			<jc>// Do something with it.</jc>

+	 * 		}

+	 * 	}

+	 * </p>

+	 *

+	 * <ul class='notes'>

+	 * 	<li>

+	 * 		Inner classes of the REST resource class are allowed.

+	 * 	<li>

+	 * 		Refer to {@link RestParam} for the list of predefined parameter resolvers.

+	 * </ul>

+	 */

+	public static final String REST_restParams = PREFIX + ".restParams.lo";

+

+	/**

 	 * Configuration property:  Declared roles.

 	 *

 	 * <h5 class='section'>Property:</h5>

@@ -3179,7 +3168,7 @@
 

 	private final Set<String> allowedMethodParams, allowedHeaderParams, allowedMethodHeaders;

 

-	private final Map<Class<?>,RestMethodParam> paramResolvers;

+	private final Class<? extends RestParam>[] restParams, hookMethodParams;

 	private final SerializerGroup serializers;

 	private final ParserGroup parsers;

 	private final HttpPartSerializer partSerializer;

@@ -3334,12 +3323,8 @@
 			defaultResponseHeaders = createDefaultResponseHeaders(r, beanFactory);

 			defaultRequestAttributes = createDefaultRequestAttributes(r, beanFactory);

 

-			RestMethodParam[] _paramResolvers = createParamResolvers(r, beanFactory);

-			beanFactory.addBean(RestMethodParam[].class, _paramResolvers);

-			AMap<Class<?>,RestMethodParam> _paramResolvers2 = AMap.of();

-			for (RestMethodParam rp : _paramResolvers)

-				_paramResolvers2.put(rp.forClass(), rp);

-			paramResolvers = _paramResolvers2.unmodifiable();

+			restParams = createRestParams(r, beanFactory);

+			hookMethodParams = createHookMethodParams(r, beanFactory);

 

 			uriContext = nullIfEmpty(getStringProperty(REST_uriContext));

 			uriAuthority = nullIfEmpty(getStringProperty(REST_uriAuthority));

@@ -3561,7 +3546,7 @@
 	}

 

 	private MethodInvoker toRestMethodInvoker(Method m) {

-		return new RestMethodInvoker(m, findParams(m, true, null),  getMethodExecStats(m));

+		return new RestMethodInvoker(m, findHookMethodParams(m, getBeanFactory()), getMethodExecStats(m));

 	}

 

 	/**

@@ -4191,20 +4176,14 @@
 	 * <p>

 	 * Instantiates based on the following logic:

 	 * <ul>

-	 * 	<li>Looks for {@link #REST_paramResolvers} value set via any of the following:

+	 * 	<li>Looks for {@link #REST_restParams} value set via any of the following:

 	 * 		<ul>

-	 * 			<li>{@link RestContextBuilder#paramResolvers(Class...)}/{@link RestContextBuilder#paramResolvers(RestMethodParam...)}

-	 * 			<li>{@link Rest#paramResolvers()}.

+	 * 			<li>{@link RestContextBuilder#restParams(Class...)}/{@link RestContextBuilder#restParams(Class...)}

+	 * 			<li>{@link Rest#restParams()}.

 	 * 		</ul>

-	 * 	<li>Looks for a static or non-static <c>createParamResolvers()</> method that returns <c>{@link RestMethodParam}[]</c> on the

-	 * 		resource class with any of the following arguments:

-	 * 		<ul>

-	 * 			<li>{@link RestContext}

-	 * 			<li>{@link BeanFactory}

-	 * 			<li>Any {@doc RestInjection injected beans}.

-	 * 		</ul>

+	 * 	<li>Looks for a static or non-static <c>createRestParams()</> method that returns <c>{@link Class}[]</c>.

 	 * 	<li>Resolves it via the bean factory registered in this context.

-	 * 	<li>Instantiates a <c>RestMethodParam[0]</c>.

+	 * 	<li>Instantiates a default set of parameters.

 	 * </ul>

 	 *

 	 * @param resource The REST resource object.

@@ -4213,24 +4192,114 @@
 	 * @throws Exception If parameter resolvers could not be instantiated.

 	 * @seealso #REST_paramResolvers

 	 */

-	protected RestMethodParam[] createParamResolvers(Object resource, BeanFactory beanFactory) throws Exception {

-		RestMethodParam[] x = getInstanceArrayProperty(REST_paramResolvers, RestMethodParam.class, null, beanFactory);

+	@SuppressWarnings("unchecked")

+	protected Class<? extends RestParam>[] createRestParams(Object resource, BeanFactory beanFactory) throws Exception {

+		@SuppressWarnings("rawtypes")

+		AList<Class> x = AList.of(getListProperty(REST_restParams, Class.class, AList.of()));

 

-		if (x == null)

-			x = beanFactory.getBean(RestMethodParam[].class).orElse(null);

+		x.a(

+			AttributeParam.class,

+			BodyParam.class,

+			ConfigParam.class,

+			FormDataParam.class,

+			HasFormDataParam.class,

+			HasQueryParam.class,

+			HeaderParam.class,

+			HttpServletRequestParam.class,

+			HttpServletResponseParam.class,

+			InputStreamParam.class,

+			InputStreamParserParam.class,

+			LocaleParam.class,

+			MessagesParam.class,

+			MethodParam.class,

+			OutputStreamParam.class,

+			ParserParam.class,

+			PathParam.class,

+			QueryParam.class,

+			ReaderParam.class,

+			ReaderParserParam.class,

+			RequestAttributesParam.class,

+			RequestBeanParam.class,

+			RequestBodyParam.class,

+			RequestFormDataParam.class,

+			RequestHeadersParam.class,

+			RequestPathParam.class,

+			RequestQueryParam.class,

+			ResourceBundleParam.class,

+			ResponseBeanParam.class,

+			ResponseHeaderParam.class,

+			ResponseStatusParam.class,

+			RestContextParam.class,

+			RestRequestParam.class,

+			ServetInputStreamParam.class,

+			ServletOutputStreamParam.class,

+			SwaggerParam.class,

+			TimeZoneParam.class,

+			UriContextParam.class,

+			UriResolverParam.class,

+			WriterParam.class,

+			DefaultParam.class

+		);

 

-		if (x == null)

-			x = new RestMethodParam[0];

+		Class<?>[] x2 = x.toArray(new Class[x.size()]);

 

-		x = BeanFactory

+		x2 = BeanFactory

 			.of(beanFactory, resource)

-			.addBean(RestMethodParam[].class, x)

-			.beanCreateMethodFinder(RestMethodParam[].class, resource)

-			.find("createParamResolvers")

-			.withDefault(x)

+			.addBean(Class[].class, x2)

+			.beanCreateMethodFinder(Class[].class, resource)

+			.find("createRestParams")

+			.withDefault(x2)

 			.run();

 

-		return x;

+		return (Class<? extends RestParam>[])x2;

+	}

+

+	/**

+	 * Instantiates the hook method parameter resolvers for this REST resource.

+	 *

+	 * @param resource The REST resource object.

+	 * @param beanFactory The bean factory to use for retrieving and creating beans.

+	 * @return The REST method parameter resolvers for this REST resource.

+	 * @throws Exception If parameter resolvers could not be instantiated.

+	 * @seealso #REST_paramResolvers

+	 */

+	@SuppressWarnings("unchecked")

+	protected Class<? extends RestParam>[] createHookMethodParams(Object resource, BeanFactory beanFactory) throws Exception {

+		@SuppressWarnings("rawtypes")

+		AList<Class> x = AList.of();

+

+		x.a(

+			ConfigParam.class,

+			HeaderParam.class,

+			HttpServletRequestParam.class,

+			HttpServletResponseParam.class,

+			InputStreamParam.class,

+			LocaleParam.class,

+			MessagesParam.class,

+			MethodParam.class,

+			OutputStreamParam.class,

+			ReaderParam.class,

+			ResourceBundleParam.class,

+			RestContextParam.class,

+			RestRequestParam.class,

+			ServetInputStreamParam.class,

+			ServletOutputStreamParam.class,

+			TimeZoneParam.class,

+			WriterParam.class,

+			DefaultParam.class

+		);

+

+		Class<?>[] x2 = x.toArray(new Class[x.size()]);

+

+		x2 = BeanFactory

+			.of(beanFactory, resource)

+			.addBean(Class[].class, x2)

+			.beanCreateMethodFinder(Class[].class, resource)

+			.find("createHookMethodParams")

+			.withDefault(x2)

+			.run();

+

+		return (Class<? extends RestParam>[])x2;

 	}

 

 	/**

@@ -5264,66 +5333,71 @@
 	}

 

 	/**

-	 * Finds the {@link RestMethodParam} instances to handle resolving objects on the calls to the specified Java method.

+	 * Finds the {@link RestParam} instances to handle resolving objects on the calls to the specified Java method.

 	 *

 	 * @param m The Java method being called.

-	 * @param isPreOrPost Whether this is a {@link HookEvent#PRE_CALL} or {@link HookEvent#POST_CALL}.

-	 * @param urlPathMatcher The path pattern to match against.

+	 * @param beanFactory The method context bean factory.

 	 * @return The array of resolvers.

 	 */

-	protected RestMethodParam[] findParams(Method m, boolean isPreOrPost, UrlPathMatcher urlPathMatcher) {

+	protected RestParam[] findRestMethodParams(Method m, BeanFactory beanFactory) {

 

 		MethodInfo mi = MethodInfo.of(m);

 		List<ClassInfo> pt = mi.getParamTypes();

-		RestMethodParam[] rp = new RestMethodParam[pt.size()];

-		PropertyStore ps = getPropertyStore();

+		RestParam[] rp = new RestParam[pt.size()];

+

+		beanFactory = new BeanFactory(beanFactory, getResource());

 

 		for (int i = 0; i < pt.size(); i++) {

-

-			ClassInfo t = pt.get(i);

-			if (t.inner() != null) {

-				Class<?> c = t.inner();

-				rp[i] = paramResolvers.get(c);

-				if (rp[i] == null)

-					rp[i] = RestParamDefaults.STANDARD_RESOLVERS.get(c);

+			ParamInfo pi = mi.getParam(i);

+			beanFactory.addBean(ParamInfo.class, pi);

+			for (Class<? extends RestParam> c : restParams) {

+				try {

+					rp[i] = beanFactory.createBean(c);

+					if (rp[i] != null)

+						break;

+				} catch (ExecutableException e) {

+					throw new InternalServerError(e.unwrap(), "Could not resolve parameter {0} on method {1}.", i, mi.getFullName());

+				}

 			}

-

-			ParamInfo mpi = mi.getParam(i);

-

-			if (mpi.hasAnnotation(Header.class)) {

-				rp[i] = new RestParamDefaults.HeaderObject(mpi, ps);

-			} else if (mpi.hasAnnotation(Attr.class)) {

-				rp[i] = new RestParamDefaults.AttributeObject(mpi, ps);

-			} else if (mpi.hasAnnotation(Query.class)) {

-				rp[i] = new RestParamDefaults.QueryObject(mpi, ps);

-			} else if (mpi.hasAnnotation(FormData.class)) {

-				rp[i] = new RestParamDefaults.FormDataObject(mpi, ps);

-			} else if (mpi.hasAnnotation(Path.class)) {

-				rp[i] = new RestParamDefaults.PathObject(mpi, ps, urlPathMatcher);

-			} else if (mpi.hasAnnotation(Body.class)) {

-				rp[i] = new RestParamDefaults.BodyObject(mpi, ps);

-			} else if (mpi.hasAnnotation(Request.class)) {

-				rp[i] = new RestParamDefaults.RequestObject(mpi, ps);

-			} else if (mpi.hasAnnotation(Response.class)) {

-				rp[i] = new RestParamDefaults.ResponseObject(mpi, ps);

-			} else if (mpi.hasAnnotation(ResponseHeader.class)) {

-				rp[i] = new RestParamDefaults.ResponseHeaderObject(mpi, ps);

-			} else if (mpi.hasAnnotation(ResponseStatus.class)) {

-				rp[i] = new RestParamDefaults.ResponseStatusObject(t);

-			} else if (mpi.hasAnnotation(HasFormData.class)) {

-				rp[i] = new RestParamDefaults.HasFormDataObject(mpi);

-			} else if (mpi.hasAnnotation(HasQuery.class)) {

-				rp[i] = new RestParamDefaults.HasQueryObject(mpi);

-			} else if (mpi.hasAnnotation(org.apache.juneau.rest.annotation.Method.class)) {

-				rp[i] = new RestParamDefaults.MethodObject(mi, t, mpi);

-			} else if (rp[i] == null) {

-				rp[i] = new RestParamDefaults.BeanFactoryObject(mi, t, mpi);

-			}

+			if (rp[i] == null)

+				throw new InternalServerError("Could not resolve parameter {0} on method {1}.", i, mi.getFullName());

 		}

 

 		return rp;

 	}

 

+	/**

+	 * Finds the {@link RestParam} instances to handle resolving objects on pre-call and post-call Java methods.

+	 *

+	 * @param m The Java method being called.

+	 * @param beanFactory The method context bean factory.

+	 * @return The array of resolvers.

+	 */

+	protected RestParam[] findHookMethodParams(Method m, BeanFactory beanFactory) {

+		MethodInfo mi = MethodInfo.of(m);

+		List<ClassInfo> pt = mi.getParamTypes();

+		RestParam[] rp = new RestParam[pt.size()];

+

+		beanFactory = new BeanFactory(beanFactory, getResource());

+

+		for (int i = 0; i < pt.size(); i++) {

+			ParamInfo pi = mi.getParam(i);

+			beanFactory.addBean(ParamInfo.class, pi);

+			for (Class<? extends RestParam> c : hookMethodParams) {

+				try {

+					rp[i] = beanFactory.createBean(c);

+					if (rp[i] != null)

+						break;

+				} catch (ExecutableException e) {

+					throw new InternalServerError(e.unwrap(), "Could not resolve parameter {0} on method {1}.", i, mi.getFullName());

+				}

+			}

+			if (rp[i] == null)

+				throw new InternalServerError("Could not resolve parameter {0} on method {1}.", i, mi.getFullName());

+		}

+

+		return rp;

+	}

 

 	//------------------------------------------------------------------------------------------------------------------

 	// Call handling

@@ -5765,7 +5839,7 @@
 			try {

 				x.invokeUsingFactory(call.getBeanFactory(), call.getResource());

 			} catch (ExecutableException e) {

-				logger.log(Level.WARNING, e.unwrap(), ()->format("Error occurred invoking finish-call method ''{0}''.", x.getName()));

+				logger.log(Level.WARNING, e.unwrap(), ()->format("Error occurred invoking finish-call method ''{0}''.", x.getFullName()));

 			}

 		}

 	}

@@ -5830,7 +5904,7 @@
 			try {

 				x.invokeUsingFactory(beanFactory, getResource());

 			} catch (ExecutableException e) {

-				getLogger().log(Level.WARNING, e.unwrap(), ()->format("Error occurred invoking servlet-destroy method ''{0}''.", x.getName()));

+				getLogger().log(Level.WARNING, e.unwrap(), ()->format("Error occurred invoking servlet-destroy method ''{0}''.", x.getFullName()));

 			}

 		}

 

@@ -5928,13 +6002,13 @@
 				.a("defaultResponseHeaders", defaultResponseHeaders)

 				.a("fileFinder", fileFinder)

 				.a("infoProvider", infoProvider)

-				.a("paramResolvers", paramResolvers)

 				.a("parsers", parsers)

 				.a("partParser", partParser)

 				.a("partSerializer", partSerializer)

 				.a("produces", produces)

 				.a("renderResponseStackTraces", renderResponseStackTraces)

 				.a("responseHandlers", responseHandlers)

+				.a("restParams", restParams)

 				.a("serializers", serializers)

 				.a("staticFiles", staticFiles)

 				.a("uriAuthority", uriAuthority)

diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestContextBuilder.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestContextBuilder.java
index 225e442..9079e9d 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestContextBuilder.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestContextBuilder.java
@@ -1372,45 +1372,6 @@
 	}
 
 	/**
-	 * <i><l>RestContext</l> configuration property:&emsp;</i>  Java method parameter resolvers.
-	 *
-	 * <p>
-	 * By default, the Juneau framework will automatically Java method parameters of various types (e.g.
-	 * <c>RestRequest</c>, <c>Accept</c>, <c>Reader</c>).
-	 * This annotation allows you to provide your own resolvers for your own class types that you want resolved.
-	 *
-	 * <ul class='seealso'>
-	 * 	<li class='jf'>{@link RestContext#REST_paramResolvers}
-	 * </ul>
-	 *
-	 * @param values The values to add to this setting.
-	 * @return This object (for method chaining).
-	 */
-	@FluentSetter
-	@SuppressWarnings("unchecked")
-	public RestContextBuilder paramResolvers(Class<? extends RestMethodParam>...values) {
-		return prependTo(REST_paramResolvers, values);
-	}
-
-	/**
-	 * <i><l>RestContext</l> configuration property:&emsp;</i>  Java method parameter resolvers.
-	 *
-	 * <p>
-	 * Same as {@link #paramResolvers(Class...)} except input is pre-constructed instances.
-	 *
-	 * <ul class='seealso'>
-	 * 	<li class='jf'>{@link RestContext#REST_paramResolvers}
-	 * </ul>
-	 *
-	 * @param values The values to add to this setting.
-	 * @return This object (for method chaining).
-	 */
-	@FluentSetter
-	public RestContextBuilder paramResolvers(RestMethodParam...values) {
-		return prependTo(REST_paramResolvers, values);
-	}
-
-	/**
 	 * <i><l>RestContext</l> configuration property:&emsp;</i>  Parser listener.
 	 *
 	 * <p>
@@ -1668,6 +1629,27 @@
 	}
 
 	/**
+	 * <i><l>RestContext</l> configuration property:&emsp;</i>  Java method parameter resolvers.
+	 *
+	 * <p>
+	 * By default, the Juneau framework will automatically Java method parameters of various types (e.g.
+	 * <c>RestRequest</c>, <c>Accept</c>, <c>Reader</c>).
+	 * This annotation allows you to provide your own resolvers for your own class types that you want resolved.
+	 *
+	 * <ul class='seealso'>
+	 * 	<li class='jf'>{@link RestContext#REST_restParams}
+	 * </ul>
+	 *
+	 * @param values The values to add to this setting.
+	 * @return This object (for method chaining).
+	 */
+	@FluentSetter
+	@SuppressWarnings("unchecked")
+	public RestContextBuilder restParams(Class<? extends RestParam>...values) {
+		return prependTo(REST_restParams, values);
+	}
+
+	/**
 	 * <i><l>RestContext</l> configuration property:&emsp;</i>  Declared roles.
 	 *
 	 * <p>
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestMethodContext.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestMethodContext.java
index 1e95f74..0f4329d 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestMethodContext.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestMethodContext.java
@@ -599,7 +599,7 @@
 
 	private final String httpMethod;
 	private final UrlPathMatcher[] pathMatchers;
-	final RestMethodParam[] methodParams;
+	final RestParam[] methodParams;
 	private final RestGuard[] guards;
 	private final RestMatcher[] optionalMatchers;
 	private final RestMatcher[] requiredMatchers;
@@ -649,7 +649,8 @@
 
 			beanFactory = new BeanFactory(context.rootBeanFactory, r)
 				.addBean(RestMethodContext.class, this)
-				.addBean(Method.class, method);
+				.addBean(Method.class, method)
+				.addBean(PropertyStore.class, ps);
 			beanFactory.addBean(BeanFactory.class, beanFactory);
 
 			serializers = createSerializers(r, beanFactory, ps);
@@ -676,6 +677,7 @@
 
 			pathMatchers = createPathMatchers(r, beanFactory, b.dotAll);
 			beanFactory.addBean(UrlPathMatcher[].class, pathMatchers);
+			beanFactory.addBean(UrlPathMatcher.class, pathMatchers.length > 0 ? pathMatchers[0] : null);
 
 			encoders = createEncoders(r, beanFactory);
 			beanFactory.addBean(EncoderGroup.class, encoders);
@@ -713,7 +715,7 @@
 
 			responseMeta = ResponseBeanMeta.create(mi, ps);
 
-			methodParams = context.findParams(mi.inner(), false, pathMatchers[this.pathMatchers.length-1]);
+			methodParams = context.findRestMethodParams(mi.inner(), beanFactory);
 
 			this.priority = getIntegerProperty(RESTMETHOD_priority, 0);
 
@@ -1680,10 +1682,11 @@
 
 		Object[] args = new Object[methodParams.length];
 		for (int i = 0; i < methodParams.length; i++) {
+			ParamInfo pi = methodInvoker.inner().getParam(i);
 			try {
 				args[i] = methodParams[i].resolve(call);
 			} catch (Exception e) {
-				throw toHttpException(e, BadRequest.class, "Invalid data conversion.  Could not convert {0} ''{1}'' to type ''{2}'' on method ''{3}.{4}''.", methodParams[i].getParamType().name(), methodParams[i].getName(), methodParams[i].getType(), mi.getDeclaringClass().getFullName(), mi.getSimpleName());
+				throw toHttpException(e, BadRequest.class, "Could not convert resolve parameter {0} of type ''{1}'' on method ''{2}''.", i, pi.getParameterType(), mi.getFullName());
 			}
 		}
 
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestMethodInvoker.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestMethodInvoker.java
index c77bb39..01fff11 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestMethodInvoker.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestMethodInvoker.java
@@ -19,6 +19,7 @@
 import org.apache.juneau.*;
 import org.apache.juneau.http.exception.*;
 import org.apache.juneau.mstat.*;
+import org.apache.juneau.reflect.*;
 import org.apache.juneau.utils.*;
 
 /**
@@ -26,7 +27,7 @@
  */
 public class RestMethodInvoker extends MethodInvoker {
 
-	private final RestMethodParam[] params;
+	private final RestParam[] params;
 
 	/**
 	 * Constructor.
@@ -35,7 +36,7 @@
 	 * @param params The parameter resolvers.
 	 * @param stats The instrumentor.
 	 */
-	public RestMethodInvoker(Method m, RestMethodParam[] params, MethodExecStats stats) {
+	public RestMethodInvoker(Method m, RestParam[] params, MethodExecStats stats) {
 		super(m, stats);
 		this.params = params;
 	}
@@ -51,16 +52,17 @@
 	public Object invokeFromCall(RestCall call, Object resource) throws HttpException {
 		Object[] args = new Object[params.length];
 		for (int i = 0; i < params.length; i++) {
+			ParamInfo pi = inner().getParam(i);
 			try {
 				args[i] = params[i].resolve(call);
 			} catch (Exception e) {
-				throw toHttpException(e, BadRequest.class, "Could not resolve parameter {0} of type ''{1}'' on method ''{2}.{3}''.", i, params[i].getParamType(), getDeclaringClass().getName(), getName());
+				throw toHttpException(e, BadRequest.class, "Could not resolve parameter {0} of type ''{1}'' on method ''{2}''.", i, pi.getParameterType(), getFullName());
 			}
 		}
 		try {
 			return invoke(resource, args);
 		} catch (ExecutableException e) {
-			throw toHttpException(e.unwrap(), InternalServerError.class, "Method ''{0}.{1}'' threw an unexpected exception.", getDeclaringClass().getName(), getName());
+			throw toHttpException(e.unwrap(), InternalServerError.class, "Method ''{0}'' threw an unexpected exception.", getFullName());
 		}
 	}
 }
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestMethodParam.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestMethodParam.java
deleted file mode 100644
index f7c7eb7..0000000
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestMethodParam.java
+++ /dev/null
@@ -1,258 +0,0 @@
-// ***************************************************************************************************************************
-// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
-// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
-// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
-// * with the License.  You may obtain a copy of the License at                                                              *
-// *                                                                                                                         *
-// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
-// *                                                                                                                         *
-// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
-// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
-// * specific language governing permissions and limitations under the License.                                              *
-// ***************************************************************************************************************************
-package org.apache.juneau.rest;
-
-import java.io.*;
-import java.lang.reflect.*;
-import java.util.*;
-
-import javax.servlet.*;
-import javax.servlet.http.*;
-
-import org.apache.juneau.*;
-import org.apache.juneau.config.*;
-import org.apache.juneau.cp.Messages;
-import org.apache.juneau.dto.swagger.*;
-import org.apache.juneau.http.header.*;
-import org.apache.juneau.http.header.Date;
-import org.apache.juneau.parser.*;
-import org.apache.juneau.reflect.*;
-
-/**
- * REST java method parameter resolver.
- *
- * <p>
- * Used to resolve instances of classes being passed to Java REST methods.
- *
- * <p>
- * By default, the following parameter types can be passed into Java methods in any order:
- *
- * <h5 class='topic'>Standard top-level objects</h5>
- * <ul>
- * 	<li><b>Standard top-level objects</b>
- * 	<ul>
- * 		<li class='jc'>{@link HttpServletRequest}
- * 		<li class='jc'>{@link RestRequest}
- * 		<li class='jc'>{@link HttpServletResponse}
- * 		<li class='jc'>{@link RestResponse}
- * 	</ul>
- * 	<li><b>Headers</b>
- * 	<ul>
- * 		<li class='jc'>{@link Accept}
- * 		<li class='jc'>{@link AcceptCharset}
- * 		<li class='jc'>{@link AcceptEncoding}
- * 		<li class='jc'>{@link AcceptLanguage}
- * 		<li class='jc'>{@link Authorization}
- * 		<li class='jc'>{@link CacheControl}
- * 		<li class='jc'>{@link Connection}
- * 		<li class='jc'>{@link ContentLength}
- * 		<li class='jc'>{@link ContentType}
- * 		<li class='jc'>{@link Date}
- * 		<li class='jc'>{@link Expect}
- * 		<li class='jc'>{@link From}
- * 		<li class='jc'>{@link Host}
- * 		<li class='jc'>{@link IfMatch}
- * 		<li class='jc'>{@link IfModifiedSince}
- * 		<li class='jc'>{@link IfNoneMatch}
- * 		<li class='jc'>{@link IfRange}
- * 		<li class='jc'>{@link IfUnmodifiedSince}
- * 		<li class='jc'>{@link MaxForwards}
- * 		<li class='jc'>{@link Pragma}
- * 		<li class='jc'>{@link ProxyAuthorization}
- * 		<li class='jc'>{@link Range}
- * 		<li class='jc'>{@link Referer}
- * 		<li class='jc'>{@link TE}
- * 		<li class='jc'>{@link TimeZone}
- * 		<li class='jc'>{@link UserAgent}
- * 		<li class='jc'>{@link Upgrade}
- * 		<li class='jc'>{@link Via}
- * 		<li class='jc'>{@link Warning}
- * 	</ul>
- * 	<li><b>Other objects</b>
- * 	<ul>
- * 		<li class='jc'>{@link Config}
- * 		<li class='jc'>{@link InputStream}
- * 		<li class='jc'>{@link Locale}
- * 		<li class='jc'>{@link Messages}
- * 		<li class='jc'>{@link OutputStream}
- * 		<li class='jc'>{@link Parser}
- * 		<li class='jc'>{@link Reader}
- * 		<li class='jc'>{@link RequestBody}
- * 		<li class='jc'>{@link RequestFormData}
- * 		<li class='jc'>{@link RequestHeaders}
- * 		<li class='jc'>{@link RequestAttributes}
- * 		<li class='jc'>{@link RequestPath}
- * 		<li class='jc'>{@link RequestQuery}
- * 		<li class='jc'>{@link ResourceBundle}
- * 		<li class='jc'>{@link RestContext}
- * 		<li class='jc'>{@link ServletInputStream}
- * 		<li class='jc'>{@link ServletOutputStream}
- * 		<li class='jc'>{@link Swagger}
- * 		<li class='jc'>{@link UriContext}
- * 		<li class='jc'>{@link UriResolver}
- * 		<li class='jc'>{@link Writer}
- *  	</ul>
- * </ul>
- *
- * <ul class='seealso'>
- * 	<li class='jf'>{@link RestContext#REST_paramResolvers}
- * 	<li class='link'>{@doc RestmParameters}
- * </ul>
- */
-public abstract class RestMethodParam {
-
-	final RestParamType paramType;
-	final ParamInfo mpi;
-	final String name;
-	final Type type;
-	final Class<?> c;
-
-	/**
-	 * Resolves the parameter object.
-	 *
-	 * @param call The rest call.
-	 * @return The resolved object.
-	 * @throws Exception Generic error occurred.
-	 */
-	public abstract Object resolve(RestCall call) throws Exception;
-
-	/**
-	 * Constructor.
-	 *
-	 * @param paramType The Swagger parameter type.
-	 * @param mpi The method parameter.
-	 * @param name
-	 * 	The parameter name.
-	 * 	Can be <jk>null</jk> if parameter doesn't have a name (e.g. the request body).
-	 * @param type The object type to convert the parameter to.
-	 */
-	protected RestMethodParam(RestParamType paramType, ParamInfo mpi, String name, Type type) {
-		this.paramType = paramType;
-		this.mpi = mpi;
-		this.name = name;
-		this.type = type;
-		this.c = type instanceof Class ? (Class<?>)type : type instanceof ParameterizedType ? (Class<?>)((ParameterizedType)type).getRawType() : null;
-	}
-
-	/**
-	 * Constructor.
-	 *
-	 * @param paramType The Swagger parameter type.
-	 * @param mpi The method parameter.
-	 * @param name
-	 * 	The parameter name.
-	 * 	Can be <jk>null</jk> if parameter doesn't have a name (e.g. the request body).
-	 */
-	protected RestMethodParam(RestParamType paramType, ParamInfo mpi, String name) {
-		this(paramType, mpi, name, mpi.getParameterType().innerType());
-	}
-
-	/**
-	 * Constructor.
-	 *
-	 * @param paramType The Swagger parameter type.
-	 * @param mpi The method parameter.
-	 */
-	protected RestMethodParam(RestParamType paramType, ParamInfo mpi) {
-		this(paramType, mpi, null, mpi.getParameterType().innerType());
-	}
-
-	/**
-	 * Constructor.
-	 *
-	 * @param paramType The Swagger parameter type.
-	 * @param type The object type to convert the parameter to.
-	 */
-	protected RestMethodParam(RestParamType paramType, Type type) {
-		this(paramType, null, null, type);
-	}
-
-	/**
-	 * Constructor.
-	 *
-	 * @param paramType The Swagger parameter type.
-	 * @param type The object type to convert the parameter to.
-	 */
-	protected RestMethodParam(RestParamType paramType, ClassInfo type) {
-		this(paramType, null, null, type.innerType());
-	}
-
-	/**
-	 * Constructor.
-	 *
-	 * @param paramType The Swagger parameter type.
-	 * @param name
-	 * 	The parameter name.
-	 * 	Can be <jk>null</jk> if parameter doesn't have a name (e.g. the request body).
-	 * @param type The object type to convert the parameter to.
-	 */
-	protected RestMethodParam(RestParamType paramType, String name, Type type) {
-		this(paramType, null, name, type);
-	}
-
-	/**
-	 * Returns the parameter class type that this parameter resolver is meant for.
-	 *
-	 * @return The parameter class type, or <jk>null</jk> if the type passed in isn't an instance of {@link Class}.
-	 */
-	protected Class<?> forClass() {
-		if (type instanceof Class)
-			return (Class<?>)type;
-		return null;
-	}
-
-	/**
-	 * Returns the swagger parameter type for this parameter as shown in the Swagger doc.
-	 *
-	 * @return the swagger parameter type for this parameter.
-	 */
-	protected RestParamType getParamType() {
-		return paramType;
-	}
-
-	/**
-	 * Returns the parameter info.
-	 *
-	 * @return The parameter info.
-	 */
-	public ParamInfo getMethodParamInfo() {
-		return mpi;
-	}
-
-	/**
-	 * Returns the parameter name for this parameter as shown in the Swagger doc.
-	 *
-	 * @return the parameter name for this parameter.
-	 */
-	protected String getName() {
-		return name;
-	}
-
-	/**
-	 * Returns the parameter class type.
-	 *
-	 * @return the parameter class type.
-	 */
-	public Type getType() {
-		return type;
-	}
-
-	/**
-	 * Returns the parameter class type.
-	 *
-	 * @return the parameter class type.
-	 */
-	public Class<?> getTypeClass() {
-		return c;
-	}
-}
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestParam.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestParam.java
new file mode 100644
index 0000000..d870407
--- /dev/null
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestParam.java
@@ -0,0 +1,60 @@
+// ***************************************************************************************************************************
+// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
+// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
+// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
+// * with the License.  You may obtain a copy of the License at                                                              *
+// *                                                                                                                         *
+// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
+// *                                                                                                                         *
+// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
+// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
+// * specific language governing permissions and limitations under the License.                                              *
+// ***************************************************************************************************************************
+package org.apache.juneau.rest;
+
+import org.apache.juneau.rest.annotation.*;
+
+/**
+ * REST java method parameter resolver.
+ *
+ * <p>
+ * Used to resolve parameter values when invoking {@link RestMethod}-annotated methods.
+ *
+ * <h5 class='figure'>Example:</h5>
+ * <p class='bcode w800'>
+ * 	<jc>// A simple parameter resolver that resolves TimeZone parameters.</jc>
+ * 	<jk>public class</jk> TimeZoneParam <jk>implements</jk> RestParam {
+ *
+ * 		<jc>// Implementers must provide a static creator method that returns a RestParam if it's
+ * 		// applicable to the specified parameter.</jc>
+ * 		<jk>public static</jk> TimeZoneParam <jsm>create</jsm>(ParamInfo <jv>paramInfo</jv>) {
+ * 			<jk>if</jk> (<jv>paramInfo</jv>.isType(TimeZone.<jk>class</jk>))
+ * 				<jk>return new</jk> TimeZoneParam();
+ * 			<jk>return null</jk>;
+ * 		}
+ *
+ * 		<jk>protected</jk> TimeZoneParam() {}
+ *
+ * 		<ja>@Override</ja>
+ * 		<jk>public</jk> Object resolve(RestCall <jv>call</jv>) <jk>throws</jk> Exception {
+ * 			<jk>return</jk> <jv>call</jv>.getRestRequest().getHeaders().getTimeZone();
+ * 		}
+ * 	}
+ * </p>
+ *
+ * <ul class='seealso'>
+ * 	<li class='jf'>{@link RestContext#REST_restParams}
+ * 	<li class='link'>{@doc RestmParameters}
+ * </ul>
+ */
+public interface RestParam {
+
+	/**
+	 * Resolves the parameter object.
+	 *
+	 * @param call The rest call.
+	 * @return The resolved object.
+	 * @throws Exception Generic error occurred.
+	 */
+	public Object resolve(RestCall call) throws Exception;
+}
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
deleted file mode 100644
index 69dc6aa..0000000
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestParamDefaults.java
+++ /dev/null
@@ -1,872 +0,0 @@
-// ***************************************************************************************************************************
-// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
-// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
-// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
-// * with the License.  You may obtain a copy of the License at                                                              *
-// *                                                                                                                         *
-// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
-// *                                                                                                                         *
-// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
-// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
-// * specific language governing permissions and limitations under the License.                                              *
-// ***************************************************************************************************************************
-package org.apache.juneau.rest;
-
-import static org.apache.juneau.internal.ClassUtils.*;
-import static org.apache.juneau.internal.StringUtils.*;
-import static org.apache.juneau.rest.RestParamType.*;
-
-import java.io.*;
-import java.lang.reflect.*;
-import java.util.*;
-
-import javax.servlet.*;
-import javax.servlet.http.*;
-
-import org.apache.juneau.*;
-import org.apache.juneau.config.*;
-import org.apache.juneau.cp.*;
-import org.apache.juneau.dto.swagger.*;
-import org.apache.juneau.http.annotation.*;
-import org.apache.juneau.http.annotation.Body;
-import org.apache.juneau.http.annotation.FormData;
-import org.apache.juneau.http.annotation.HasFormData;
-import org.apache.juneau.http.annotation.HasQuery;
-import org.apache.juneau.http.annotation.Header;
-import org.apache.juneau.http.annotation.Path;
-import org.apache.juneau.http.annotation.Query;
-import org.apache.juneau.httppart.*;
-import org.apache.juneau.httppart.bean.*;
-import org.apache.juneau.internal.*;
-import org.apache.juneau.parser.*;
-import org.apache.juneau.reflect.*;
-import org.apache.juneau.rest.annotation.*;
-import org.apache.juneau.http.exception.*;
-import org.apache.juneau.rest.util.UrlPathMatcher;
-import org.apache.juneau.serializer.*;
-
-/**
- * Default REST method parameter resolvers.
- *
- * <p>
- * Contains the default set of parameter resolvers for REST resource methods (i.e methods annotated with {@link RestResource @RestResource}).
- *
- * <ul class='seealso'>
- * 	<li class='link'>{@doc RestmParameters}
- * </ul>
- */
-class RestParamDefaults {
-
-	/**
-	 * Standard set of method parameter resolvers.
-	 */
-	static final Map<Class<?>,RestMethodParam> STANDARD_RESOLVERS;
-
-	static {
-		Map<Class<?>,RestMethodParam> m = new HashMap<>();
-
-		@SuppressWarnings("rawtypes")
-		Class[] r = new Class[] {
-
-			// Standard top-level objects
-			HttpServletRequestObject.class,
-			RestRequestObject.class,
-			HttpServletResponseObject.class,
-			RestResponseObject.class,
-
-			// Headers
-			TimeZoneHeader.class,
-
-			// Other objects
-			ResourceBundleObject.class,
-			MessageBundleObject.class,
-			InputStreamObject.class,
-			ServletInputStreamObject.class,
-			ReaderObject.class,
-			OutputStreamObject.class,
-			ServletOutputStreamObject.class,
-			WriterObject.class,
-			RequestHeadersObject.class,
-			RequestAttributesObject.class,
-			RequestQueryObject.class,
-			RequestFormDataObject.class,
-			RestContextObject.class,
-			ParserObject.class,
-			ReaderParserObject.class,
-			InputStreamParserObject.class,
-			LocaleObject.class,
-			SwaggerObject.class,
-			RequestPathMatchObject.class,
-			RequestBodyObject.class,
-			ConfigObject.class,
-			UriContextObject.class,
-			UriResolverObject.class
-		};
-
-		for (Class<?> c : r) {
-			try {
-				RestMethodParam mpr = (RestMethodParam)c.newInstance();
-				m.put(mpr.forClass(), mpr);
-			} catch (Exception e) {
-				e.printStackTrace();
-			}
-		}
-
-		STANDARD_RESOLVERS = Collections.unmodifiableMap(m);
-	}
-
-	//-------------------------------------------------------------------------------------------------------------------
-	// Request / Response retrievers
-	//-------------------------------------------------------------------------------------------------------------------
-
-	static final class HttpServletRequestObject extends RestMethodParam {
-
-		protected HttpServletRequestObject() {
-			super(OTHER, HttpServletRequest.class);
-		}
-
-		@Override /* RestMethodParam */
-		public Object resolve(RestCall call) {
-			return call.getRequest();
-		}
-	}
-
-	static final class HttpServletResponseObject extends RestMethodParam {
-
-		protected HttpServletResponseObject() {
-			super(OTHER, HttpServletResponse.class);
-		}
-
-		@Override /* RestMethodParam */
-		public Object resolve(RestCall call) {
-			return call.getResponse();
-		}
-	}
-
-	static final class RestRequestObject extends RestMethodParam {
-
-		protected RestRequestObject() {
-			super(OTHER, RestRequest.class);
-		}
-
-		@Override /* RestMethodParam */
-		public Object resolve(RestCall call) {
-			return call.getRestRequest();
-		}
-	}
-
-	static final class RestResponseObject extends RestMethodParam {
-
-		protected RestResponseObject() {
-			super(OTHER, RestResponse.class);
-		}
-
-		@Override /* RestMethodParam */
-		public Object resolve(RestCall call) {
-			return call.getRestResponse();
-		}
-	}
-
-	//-------------------------------------------------------------------------------------------------------------------
-	// Header retrievers
-	//-------------------------------------------------------------------------------------------------------------------
-
-	static final class TimeZoneHeader extends RestMethodParam {
-
-		protected TimeZoneHeader() {
-			super(HEADER, "Time-Zone", TimeZone.class);
-		}
-
-		@Override
-		public TimeZone resolve(RestCall call) {
-			return call.getRestRequest().getHeaders().getTimeZone();
-		}
-	}
-
-	//-------------------------------------------------------------------------------------------------------------------
-	// Annotated retrievers
-	//-------------------------------------------------------------------------------------------------------------------
-
-	static final class PathObject extends RestMethodParam {
-		private final HttpPartParser partParser;
-		private final HttpPartSchema schema;
-
-		protected PathObject(ParamInfo mpi, PropertyStore ps, UrlPathMatcher pathMatcher) {
-			super(PATH, mpi, getName(mpi, pathMatcher));
-			this.schema = HttpPartSchema.create(Path.class, mpi);
-			this.partParser = createPartParser(schema.getParser(), ps);
-		}
-
-		private static String getName(ParamInfo mpi, UrlPathMatcher pathMatcher) {
-			String p = null;
-			for (Path h : mpi.getAnnotations(Path.class))
-				p = firstNonEmpty(h.name(), h.n(), h.value(), p);
-			if (p != null)
-				return p;
-			if (pathMatcher != null) {
-				int idx = 0;
-				int i = mpi.getIndex();
-				MethodInfo mi = mpi.getMethod();
-
-				for (int j = 0; j < i; j++)
-					if (mi.getParam(i).getLastAnnotation(Path.class) != null)
-						idx++;
-
-				String[] vars = pathMatcher.getVars();
-				if (vars.length <= idx)
-					throw new InternalServerError("Number of attribute parameters in method ''{0}'' exceeds the number of URL pattern variables.", mi.getFullName());
-
-				// Check for {#} variables.
-				String idxs = String.valueOf(idx);
-				for (int j = 0; j < vars.length; j++)
-					if (StringUtils.isNumeric(vars[j]) && vars[j].equals(idxs))
-						return vars[j];
-
-				return pathMatcher.getVars()[idx];
-			}
-			throw new InternalServerError("@Path used without name or value on method parameter ''{0}''.", mpi);
-		}
-
-		@Override /* RestMethodParam */
-		public Object resolve(RestCall call) throws Exception {
-			RestRequest req = call.getRestRequest();
-			HttpPartParserSession ps = partParser == null ? req.getPartParser() : partParser.createPartSession(req.getParserSessionArgs());
-			return call.getRestRequest().getPathMatch().get(ps, schema, name, type);
-		}
-	}
-
-	static final class BodyObject extends RestMethodParam {
-		private final HttpPartSchema schema;
-
-		protected BodyObject(ParamInfo mpi, PropertyStore ps) {
-			super(BODY, mpi);
-			this.schema = HttpPartSchema.create(Body.class, mpi);
-		}
-
-		@Override /* RestMethodParam */
-		public Object resolve(RestCall call) throws Exception {
-			return call.getRestRequest().getBody().schema(schema).asType(type);
-		}
-	}
-
-	static final class HeaderObject extends RestMethodParam {
-		private final HttpPartParser partParser;
-		private final HttpPartSchema schema;
-		private final boolean multi;
-
-		protected HeaderObject(ParamInfo mpi, PropertyStore ps) {
-			super(HEADER, mpi, getName(mpi));
-			this.schema = HttpPartSchema.create(Header.class, mpi);
-			this.partParser = createPartParser(schema.getParser(), ps);
-			this.multi = getMulti(mpi);
-
-			if (multi && ! isCollection(type))
-				throw new InternalServerError("Use of multipart flag on @Header parameter that's not an array or Collection on method ''{0}''", mpi.getMethod());
-		}
-
-		private static String getName(ParamInfo mpi) {
-			String n = null;
-			for (Header h : mpi.getAnnotations(Header.class))
-				n = firstNonEmpty(h.name(), h.n(), h.value(), n);
-			if (n == null)
-				throw new InternalServerError("@Header used without name or value on method parameter ''{0}''.", mpi);
-			return n;
-		}
-
-		private static boolean getMulti(ParamInfo mpi) {
-			for (Header h : mpi.getAnnotations(Header.class))
-				if (h.multi())
-					return true;
-			return false;
-		}
-
-		@Override /* RestMethodParam */
-		public Object resolve(RestCall call) throws Exception {
-			RestRequest req = call.getRestRequest();
-			HttpPartParserSession ps = partParser == null ? req.getPartParser() : partParser.createPartSession(req.getParserSessionArgs());
-			RequestHeaders rh = call.getRestRequest().getHeaders();
-			return multi ? rh.getAll(ps, schema, name, type) : rh.get(ps, schema, name, type);
-		}
-	}
-
-	static final class AttributeObject extends RestMethodParam {
-
-		protected AttributeObject(ParamInfo mpi, PropertyStore ps) {
-			super(OTHER, mpi, getName(mpi));
-		}
-
-		private static String getName(ParamInfo mpi) {
-			String n = null;
-			for (Attr h : mpi.getAnnotations(Attr.class))
-				n = firstNonEmpty(h.name(), h.value(), n);
-			if (n == null)
-				throw new InternalServerError("@Attr used without name or value on method parameter ''{0}''.", mpi);
-			return n;
-		}
-
-		@Override /* RestMethodParam */
-		public Object resolve(RestCall call) throws Exception {
-			return call.getRestRequest().getAttributes().get(name, type);
-		}
-	}
-
-	static final class RequestObject extends RestMethodParam {
-		private final RequestBeanMeta meta;
-
-		protected RequestObject(ParamInfo mpi, PropertyStore ps) {
-			super(RESPONSE_BODY, mpi);
-			this.meta = RequestBeanMeta.create(mpi, ps);
-		}
-
-		@Override /* RestMethodParam */
-		public Object resolve(RestCall call) throws Exception {
-			return call.getRestRequest().getRequest(meta);
-		}
-	}
-
-	static final class ResponseHeaderObject extends RestMethodParam {
-		final ResponsePartMeta meta;
-
-		protected ResponseHeaderObject(ParamInfo mpi, PropertyStore ps) {
-			super(RESPONSE_HEADER, mpi, getName(mpi));
-			HttpPartSchema schema = HttpPartSchema.create(ResponseHeader.class, mpi);
-			this.meta = new ResponsePartMeta(HttpPartType.HEADER, schema, createPartSerializer(schema.getSerializer(), ps));
-
-			if (getTypeClass() != Value.class)
-				throw new InternalServerError("Invalid type {0} specified with @ResponseHeader annotation.  It must be Value.", type);
-		}
-
-		private static String getName(ParamInfo mpi) {
-			String n = null;
-			for (ResponseHeader h : mpi.getAnnotations(ResponseHeader.class))
-				n = firstNonEmpty(h.name(), h.n(), h.value(), n);
-			if (n == null)
-				throw new InternalServerError("@ResponseHeader used without name or value on method parameter ''{0}''.", mpi);
-			return n;
-		}
-
-		@SuppressWarnings({ "unchecked", "rawtypes" })
-		@Override /* RestMethodParam */
-		public Object resolve(final RestCall call) throws Exception {
-			Value<Object> v = (Value<Object>)getTypeClass().newInstance();
-			v.listener(new ValueListener() {
-				@Override
-				public void onSet(Object o) {
-					try {
-						RestRequest req = call.getRestRequest();
-						RestResponse res = call.getRestResponse();
-						ResponsePartMeta rpm = req.getResponseHeaderMeta(o);
-						if (rpm == null)
-							rpm = ResponseHeaderObject.this.meta;
-						HttpPartSerializerSession pss = rpm.getSerializer() == null ? req.getPartSerializer() : rpm.getSerializer().createPartSession(req.getSerializerSessionArgs());
-						res.setHeader(new HttpPart(name, HttpPartType.HEADER, rpm.getSchema(), pss, o));
-					} catch (SerializeException | SchemaValidationException e) {
-						throw new RuntimeException(e);
-					}
-				}
-			});
-			return v;
-		}
-	}
-
-	static final class ResponseObject extends RestMethodParam {
-		final ResponseBeanMeta meta;
-
-		protected ResponseObject(ParamInfo mpi, PropertyStore ps) {
-			super(RESPONSE, mpi);
-			this.meta = ResponseBeanMeta.create(mpi, ps);
-			if (getTypeClass() != Value.class)
-				throw new InternalServerError("Invalid type {0} specified with @Response annotation.  It must be Value.", type);
-		}
-
-		@SuppressWarnings({ "unchecked", "rawtypes" })
-		@Override /* RestMethodParam */
-		public Object resolve(final RestCall call) throws Exception {
-			Value<Object> v = (Value<Object>)c.newInstance();
-			v.listener(new ValueListener() {
-				@Override
-				public void onSet(Object o) {
-					RestRequest req = call.getRestRequest();
-					RestResponse res = call.getRestResponse();
-					ResponseBeanMeta meta = req.getResponseBeanMeta(o);
-					if (meta == null)
-						meta = ResponseObject.this.meta;
-					res.setResponseMeta(meta);
-					res.setOutput(o);
-				}
-			});
-			return v;
-		}
-	}
-
-	static class ResponseStatusObject extends RestMethodParam {
-
-		protected ResponseStatusObject(ClassInfo t) {
-			super(RESPONSE_STATUS, t);
-			if (getTypeClass() != Value.class || Value.getParameterType(t.innerType()) != Integer.class)
-				throw new InternalServerError("Invalid type {0} specified with @ResponseStatus annotation.  It must Value<Integer>.", type);
-		}
-
-		@SuppressWarnings({ "unchecked", "rawtypes" })
-		@Override /* RestMethodParam */
-		public Object resolve(final RestCall call) throws Exception {
-			Value<Object> v = (Value<Object>)c.newInstance();
-			v.listener(new ValueListener() {
-				@Override
-				public void onSet(Object o) {
-					call.getRestResponse().setStatus(Integer.parseInt(o.toString()));
-				}
-			});
-			return v;
-		}
-	}
-
-	static final class MethodObject extends RestMethodParam {
-
-		protected MethodObject(MethodInfo m, ClassInfo t, ParamInfo mpi) {
-			super(OTHER, mpi);
-		}
-
-		@Override /* RestMethodParam */
-		public Object resolve(RestCall call) throws Exception {
-			return call.getRestRequest().getMethod();
-		}
-	}
-
-	static final class BeanFactoryObject extends RestMethodParam {
-
-		private final ClassInfo type;
-
-		protected BeanFactoryObject(MethodInfo m, ClassInfo t, ParamInfo mpi) {
-			super(OTHER, mpi);
-			this.type = t;
-		}
-
-		@Override /* RestMethodParam */
-		public Object resolve(RestCall call) throws Exception {
-			return call.getBeanFactory().getBean(type.inner()).orElseThrow(()->new ServletException("Could not resolve bean type: " + type.inner().getName()));
-		}
-	}
-
-	static final class FormDataObject extends RestMethodParam {
-		private final boolean multi;
-		private final HttpPartParser partParser;
-		private final HttpPartSchema schema;
-
-		protected FormDataObject(ParamInfo mpi, PropertyStore ps) {
-			super(FORM_DATA, mpi, getName(mpi));
-			this.schema = HttpPartSchema.create(FormData.class, mpi);
-			this.partParser = createPartParser(schema.getParser(), ps);
-			this.multi = getMulti(mpi) || schema.getCollectionFormat() == HttpPartCollectionFormat.MULTI;
-
-			if (multi && ! isCollection(type))
-				throw new InternalServerError("Use of multipart flag on @FormData parameter that's not an array or Collection on method ''{0}''", mpi.getMethod());
-		}
-
-		private static String getName(ParamInfo mpi) {
-			String n = null;
-			for (FormData h : mpi.getAnnotations(FormData.class))
-				n = firstNonEmpty(h.name(), h.n(), h.value(), n);
-			if (n == null)
-				throw new InternalServerError("@FormData used without name or value on method parameter ''{0}''.", mpi);
-			return n;
-		}
-
-		private static boolean getMulti(ParamInfo mpi) {
-			for (FormData f : mpi.getAnnotations(FormData.class))
-				if (f.multi())
-					return true;
-			return false;
-		}
-
-		@Override /* RestMethodParam */
-		public Object resolve(RestCall call) throws Exception {
-			RestRequest req = call.getRestRequest();
-			HttpPartParserSession ps = partParser == null ? req.getPartParser() : partParser.createPartSession(req.getParserSessionArgs());
-			RequestFormData fd = req.getFormData();
-			return multi ? fd.getAll(ps, schema, name, type) : fd.get(ps, schema, name, type);
-		}
-	}
-
-	static final class QueryObject extends RestMethodParam {
-		private final boolean multi;
-		private final HttpPartParser partParser;
-		private final HttpPartSchema schema;
-
-		protected QueryObject(ParamInfo mpi, PropertyStore ps) {
-			super(QUERY, mpi, getName(mpi));
-			this.schema = HttpPartSchema.create(Query.class, mpi);
-			this.partParser = createPartParser(schema.getParser(), ps);
-			this.multi = getMulti(mpi) || schema.getCollectionFormat() == HttpPartCollectionFormat.MULTI;
-
-			if (multi && ! isCollection(type))
-				throw new InternalServerError("Use of multipart flag on @Query parameter that's not an array or Collection on method ''{0}''", mpi.getMethod());
-		}
-
-		private static String getName(ParamInfo mpi) {
-			String n = null;
-			for (Query h : mpi.getAnnotations(Query.class))
-				n = firstNonEmpty(h.name(), h.n(), h.value(), n);
-			if (n == null)
-				throw new InternalServerError("@Query used without name or value on method param ''{0}''.", mpi);
-			return n;
-		}
-
-		private static boolean getMulti(ParamInfo mpi) {
-			for (Query q : mpi.getAnnotations(Query.class))
-				if (q.multi())
-					return true;
-			return false;
-		}
-
-		@Override /* RestMethodParam */
-		public Object resolve(RestCall call) throws Exception {
-			RestRequest req = call.getRestRequest();
-			HttpPartParserSession ps = partParser == null ? req.getPartParser() : partParser.createPartSession(req.getParserSessionArgs());
-			RequestQuery rq = req.getQuery();
-			return multi ? rq.getAll(ps, schema, name, type) : rq.get(ps, schema, name, type);
-		}
-	}
-
-	static final class HasFormDataObject extends RestMethodParam {
-
-		protected HasFormDataObject(ParamInfo mpi) {
-			super(FORM_DATA, mpi, getName(mpi));
-		}
-
-		private static String getName(ParamInfo mpi) {
-			String n = null;
-			for (HasFormData h : mpi.getAnnotations(HasFormData.class))
-				n = firstNonEmpty(h.name(), h.n(), h.value(), n);
-			if (n == null)
-				throw new InternalServerError("@HasFormData used without name or value on method parameter ''{o}''.", mpi);
-			return n;
-		}
-
-		@Override /* RestMethodParam */
-		public Object resolve(RestCall call) throws Exception {
-			RestRequest req = call.getRestRequest();
-			BeanSession bs = req.getBeanSession();
-			return bs.convertToType(req.getFormData().containsKey(name), bs.getClassMeta(type));
-		}
-	}
-
-	static final class HasQueryObject extends RestMethodParam {
-
-		protected HasQueryObject(ParamInfo mpi) {
-			super(QUERY, mpi, getName(mpi));
-		}
-
-		private static String getName(ParamInfo mpi) {
-			String n = null;
-			for (HasQuery h : mpi.getAnnotations(HasQuery.class))
-				n = firstNonEmpty(h.name(), h.n(), h.value(), n);
-			if (n == null)
-				throw new InternalServerError("@HasQuery used without name or value on method parameter ''{0}''.", mpi);
-			return n;
-		}
-
-		@Override /* RestMethodParam */
-		public Object resolve(RestCall call) throws Exception {
-			RestRequest req = call.getRestRequest();
-			BeanSession bs = req.getBeanSession();
-			return bs.convertToType(req.getQuery().containsKey(name), bs.getClassMeta(type));
-		}
-	}
-
-	//-------------------------------------------------------------------------------------------------------------------
-	// Other retrievers
-	//-------------------------------------------------------------------------------------------------------------------
-
-	static final class ResourceBundleObject extends RestMethodParam {
-
-		protected ResourceBundleObject() {
-			super(OTHER, ResourceBundle.class);
-		}
-
-		@Override /* RestMethodParam */
-		public Object resolve(RestCall call) throws Exception {
-			return call.getRestRequest().getMessages();
-		}
-	}
-
-	static final class MessageBundleObject extends RestMethodParam {
-
-		protected MessageBundleObject() {
-			super(OTHER, Messages.class);
-		}
-
-		@Override /* RestMethodParam */
-		public Object resolve(RestCall call) throws Exception {
-			return call.getRestRequest().getMessages();
-		}
-	}
-
-	static final class InputStreamObject extends RestMethodParam {
-
-		protected InputStreamObject() {
-			super(OTHER, InputStream.class);
-		}
-
-		@Override /* RestMethodParam */
-		public Object resolve(RestCall call) throws Exception {
-			return call.getRestRequest().getInputStream();
-		}
-	}
-
-	static final class ServletInputStreamObject extends RestMethodParam {
-
-		protected ServletInputStreamObject() {
-			super(OTHER, ServletInputStream.class);
-		}
-
-		@Override /* RestMethodParam */
-		public Object resolve(RestCall call) throws Exception {
-			return call.getRestRequest().getInputStream();
-		}
-	}
-
-	static final class ReaderObject extends RestMethodParam {
-
-		protected ReaderObject() {
-			super(OTHER, Reader.class);
-		}
-
-		@Override /* RestMethodParam */
-		public Object resolve(RestCall call) throws Exception {
-			return call.getRestRequest().getReader();
-		}
-	}
-
-	static final class OutputStreamObject extends RestMethodParam {
-
-		protected OutputStreamObject() {
-			super(OTHER, OutputStream.class);
-		}
-
-		@Override /* RestMethodParam */
-		public Object resolve(RestCall call) throws Exception {
-			return call.getRestResponse().getOutputStream();
-		}
-	}
-
-	static final class ServletOutputStreamObject extends RestMethodParam {
-
-		protected ServletOutputStreamObject() {
-			super(OTHER, ServletOutputStream.class);
-		}
-
-		@Override /* RestMethodParam */
-		public Object resolve(RestCall call) throws Exception {
-			return call.getRestResponse().getOutputStream();
-		}
-	}
-
-	static final class WriterObject extends RestMethodParam {
-
-		protected WriterObject() {
-			super(OTHER, Writer.class);
-		}
-
-		@Override /* RestMethodParam */
-		public Object resolve(RestCall call) throws Exception {
-			return call.getRestResponse().getWriter();
-		}
-	}
-
-	static final class RequestHeadersObject extends RestMethodParam {
-
-		protected RequestHeadersObject() {
-			super(OTHER, RequestHeaders.class);
-		}
-
-		@Override /* RestMethodParam */
-		public Object resolve(RestCall call) throws Exception {
-			return call.getRestRequest().getHeaders();
-		}
-	}
-
-	static final class RequestAttributesObject extends RestMethodParam {
-
-		protected RequestAttributesObject() {
-			super(OTHER, RequestAttributes.class);
-		}
-
-		@Override /* RestMethodParam */
-		public Object resolve(RestCall call) throws Exception {
-			return call.getRestRequest().getAttributes();
-		}
-	}
-
-	static final class RequestQueryObject extends RestMethodParam {
-
-		protected RequestQueryObject() {
-			super(OTHER, RequestQuery.class);
-		}
-
-		@Override /* RestMethodParam */
-		public Object resolve(RestCall call) throws Exception {
-			return call.getRestRequest().getQuery();
-		}
-	}
-
-	static final class RequestFormDataObject extends RestMethodParam {
-
-		protected RequestFormDataObject() {
-			super(OTHER, RequestFormData.class);
-		}
-
-		@Override /* RestMethodParam */
-		public Object resolve(RestCall call) throws Exception {
-			return call.getRestRequest().getFormData();
-		}
-	}
-
-	static final class RestContextObject extends RestMethodParam {
-
-		protected RestContextObject() {
-			super(OTHER, RestContext.class);
-		}
-
-		@Override /* RestMethodParam */
-		public Object resolve(RestCall call) throws Exception {
-			return call.getRestRequest().getContext();
-		}
-	}
-
-	static final class ParserObject extends RestMethodParam {
-
-		protected ParserObject() {
-			super(OTHER, Parser.class);
-		}
-
-		@Override /* RestMethodParam */
-		public Object resolve(RestCall call) throws Exception {
-			return call.getRestRequest().getBody().getParser();
-		}
-	}
-
-	static final class ReaderParserObject extends RestMethodParam {
-
-		protected ReaderParserObject() {
-			super(OTHER, ReaderParser.class);
-		}
-
-		@Override /* RestMethodParam */
-		public Object resolve(RestCall call) throws Exception {
-			return call.getRestRequest().getBody().getReaderParser();
-		}
-	}
-
-	static final class InputStreamParserObject extends RestMethodParam {
-
-		protected InputStreamParserObject() {
-			super(OTHER, InputStreamParser.class);
-		}
-
-		@Override /* RestMethodParam */
-		public Object resolve(RestCall call) throws Exception {
-			return call.getRestRequest().getBody().getInputStreamParser();
-		}
-	}
-
-	static final class LocaleObject extends RestMethodParam {
-
-		protected LocaleObject() {
-			super(OTHER, Locale.class);
-		}
-
-		@Override /* RestMethodParam */
-		public Object resolve(RestCall call) throws Exception {
-			return call.getRestRequest().getLocale();
-		}
-	}
-
-	static final class SwaggerObject extends RestMethodParam {
-
-		protected SwaggerObject() {
-			super(OTHER, Swagger.class);
-		}
-
-		@Override /* RestMethodParam */
-		public Object resolve(RestCall call) throws Exception {
-			return call.getRestRequest().getSwagger();
-		}
-	}
-
-	static final class RequestPathMatchObject extends RestMethodParam {
-
-		protected RequestPathMatchObject() {
-			super(OTHER, RequestPath.class);
-		}
-
-		@Override /* RestMethodParam */
-		public Object resolve(RestCall call) throws Exception {
-			return call.getRestRequest().getPathMatch();
-		}
-	}
-
-	static final class RequestBodyObject extends RestMethodParam {
-
-		protected RequestBodyObject() {
-			super(OTHER, RequestBody.class);
-		}
-
-		@Override /* RestMethodParam */
-		public Object resolve(RestCall call) throws Exception {
-			return call.getRestRequest().getBody();
-		}
-	}
-
-	static final class ConfigObject extends RestMethodParam {
-
-		protected ConfigObject() {
-			super(OTHER, Config.class);
-		}
-
-		@Override /* RestMethodParam */
-		public Object resolve(RestCall call) throws Exception {
-			return call.getRestRequest().getConfig();
-		}
-	}
-
-	static final class UriContextObject extends RestMethodParam {
-
-		protected UriContextObject() {
-			super(OTHER, UriContext.class);
-		}
-
-		@Override /* RestMethodParam */
-		public Object resolve(RestCall call) throws Exception {
-			return call.getRestRequest().getUriContext();
-		}
-	}
-
-	static final class UriResolverObject extends RestMethodParam {
-
-		protected UriResolverObject() {
-			super(OTHER, UriResolver.class);
-		}
-
-		@Override /* RestMethodParam */
-		public Object resolve(RestCall call) throws Exception {
-			return call.getRestRequest().getUriResolver();
-		}
-	}
-
-	//=================================================================================================================
-	// Utility methods
-	//=================================================================================================================
-
-	static final boolean isCollection(Type t) {
-		return BeanContext.DEFAULT.getClassMeta(t).isCollectionOrArray();
-	}
-
-	static final HttpPartParser createPartParser(Class<? extends HttpPartParser> p, PropertyStore ps) {
-		return castOrCreate(HttpPartParser.class, p, true, ps);
-	}
-
-	static final HttpPartSerializer createPartSerializer(Class<? extends HttpPartSerializer> s, PropertyStore ps) {
-		return castOrCreate(HttpPartSerializer.class, s, true, ps);
-	}
-}
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/SwaggerGenerator.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/SwaggerGenerator.java
index 69e9e3f..cdec671 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/SwaggerGenerator.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/SwaggerGenerator.java
@@ -322,56 +322,77 @@
 					paramMap.put(param.getString("in") + '.' + ("body".equals(param.getString("in")) ? "body" : param.getString("name")), param);
 
 			// Finally, look for parameters defined on method.
-			for (RestMethodParam mp : sm.methodParams) {
+			for (ParamInfo mpi : mi.getParams()) {
 
-				RestParamType in = mp.getParamType();
-				ParamInfo mpi = mp.getMethodParamInfo();
+				ClassInfo pt = mpi.getParameterType();
+				Type type = pt.innerType();
 
-				if (in.isAny(BODY, QUERY, FORM_DATA, HEADER, PATH)) {
+				if (mpi.hasAnnotation(Body.class) || pt.hasAnnotation(Body.class)) {
+					OMap param = paramMap.getMap(BODY + ".body", true).a("in", BODY);
+					for (Body a : mpi.getAnnotations(Body.class))
+						merge(param, a);
+					for (Body a : pt.getAnnotations(Body.class))
+						merge(param, a);
+					param.putIfAbsent("required", true);
+					param.ase("schema", getSchema(param.getMap("schema"), type, bs));
+					addBodyExamples(sm, param, false, type);
 
-					String key = in.toString() + '.' + (in == BODY ? "body" : mp.getName());
+				} else if (mpi.hasAnnotation(Query.class) || pt.hasAnnotation(Query.class)) {
+					String name = null;
+					for (Query a : mpi.getAnnotations(Query.class))
+						name = firstNonEmpty(a.name(), a.n(), a.value(), name);
+					for (Query a : pt.getAnnotations(Query.class))
+						name = firstNonEmpty(a.name(), a.n(), a.value(), name);
+					OMap param = paramMap.getMap(QUERY + "." + name, true).a("name", name).a("in", QUERY);
+					for (Query a : mpi.getAnnotations(Query.class))
+						merge(param, a);
+					for (Query a : pt.getAnnotations(Query.class))
+						merge(param, a);
+					mergePartSchema(param, getSchema(param.getMap("schema"), type, bs));
+					addParamExample(sm, param, QUERY, type);
 
-					OMap param = paramMap.getMap(key, true);
+				} else if (mpi.hasAnnotation(FormData.class) || pt.hasAnnotation(FormData.class)) {
+					String name = null;
+					for (FormData a : mpi.getAnnotations(FormData.class))
+						name = firstNonEmpty(a.name(), a.n(), a.value(), name);
+					for (FormData a : pt.getAnnotations(FormData.class))
+						name = firstNonEmpty(a.name(), a.n(), a.value(), name);
+					OMap param = paramMap.getMap(FORM_DATA + "." + name, true).a("name", name).a("in", FORM_DATA);
+					for (FormData a : mpi.getAnnotations(FormData.class))
+						merge(param, a);
+					for (FormData a : pt.getAnnotations(FormData.class))
+						merge(param, a);
+					mergePartSchema(param, getSchema(param.getMap("schema"), type, bs));
+					addParamExample(sm, param, FORM_DATA, type);
 
-					param.append("in", in);
+				} else if (mpi.hasAnnotation(Header.class) || pt.hasAnnotation(Header.class)) {
+					String name = null;
+					for (Header a : mpi.getAnnotations(Header.class))
+						name = firstNonEmpty(a.name(), a.n(), a.value(), name);
+					for (Header a : pt.getAnnotations(Header.class))
+						name = firstNonEmpty(a.name(), a.n(), a.value(), name);
+					OMap param = paramMap.getMap(HEADER + "." + name, true).a("name", name).a("in", HEADER);
+					for (Header a : mpi.getAnnotations(Header.class))
+						merge(param, a);
+					for (Header a : pt.getAnnotations(Header.class))
+						merge(param, a);
+					mergePartSchema(param, getSchema(param.getMap("schema"), type, bs));
+					addParamExample(sm, param, HEADER, type);
 
-					if (in != BODY)
-						param.append("name", mp.name);
-
-					try {
-						if (mpi != null) {
-							if (in == BODY) {
-								for (Body a : mpi.getAnnotations(Body.class))
-									merge(param, a);
-							} else if (in == QUERY) {
-								for (Query a : mpi.getAnnotations(Query.class))
-									merge(param, a);
-							} else if (in == FORM_DATA) {
-								for (FormData a : mpi.getAnnotations(FormData.class))
-									merge(param, a);
-							} else if (in == HEADER) {
-								for (Header a : mpi.getAnnotations(Header.class))
-									merge(param, a);
-							} else if (in == PATH) {
-								for (Path a : mpi.getAnnotations(Path.class))
-									merge(param, a);
-							}
-						}
-					} catch (ParseException e) {
-						throw new SwaggerException(e, "Malformed swagger JSON object encountered in {0} class {1} method parameter {2}", in, c, mpi);
-					}
-
-
-					if ((in == BODY || in == PATH) && ! param.containsKeyNotEmpty("required"))
-						param.put("required", true);
-
-					if (in == BODY) {
-						param.ase("schema", getSchema(param.getMap("schema"), mp.getType(), bs));
-						addBodyExamples(sm, param, false, mp.getType());
-					} else {
-						mergePartSchema(param, getSchema(param.getMap("schema"), mp.getType(), bs));
-						addParamExample(sm, param, in, mp.getType());
-					}
+				} else if (mpi.hasAnnotation(Path.class) || pt.hasAnnotation(Path.class)) {
+					String name = null;
+					for (Path a : mpi.getAnnotations(Path.class))
+						name = firstNonEmpty(a.name(), a.n(), a.value(), name);
+					for (Path a : pt.getAnnotations(Path.class))
+						name = firstNonEmpty(a.name(), a.n(), a.value(), name);
+					OMap param = paramMap.getMap(PATH + "." + name, true).a("name", name).a("in", PATH);
+					for (Path a : mpi.getAnnotations(Path.class))
+						merge(param, a);
+					for (Path a : pt.getAnnotations(Path.class))
+						merge(param, a);
+					mergePartSchema(param, getSchema(param.getMap("schema"), type, bs));
+					addParamExample(sm, param, PATH, type);
+					param.putIfAbsent("required", true);
 				}
 			}
 
@@ -443,34 +464,38 @@
 			}
 
 			// Finally, look for @ResponseHeader parameters defined on method.
-			for (RestMethodParam mp : sm.methodParams) {
+			for (ParamInfo mpi : mi.getParams()) {
 
-				RestParamType in = mp.getParamType();
-				ParamInfo mpi = mp.getMethodParamInfo();
+				ClassInfo pt = mpi.getParameterType();
 
-				if (in == RESPONSE_HEADER) {
-					List<ResponseHeader> la = mpi.getAnnotations(ResponseHeader.class);
+				if (mpi.hasAnnotation(ResponseHeader.class) || pt.hasAnnotation(ResponseHeader.class)) {
+					List<ResponseHeader> la = AList.of(mpi.getAnnotations(ResponseHeader.class)).aa(pt.getAnnotations(ResponseHeader.class));
 					Set<Integer> codes = getCodes2(la, 200);
+					String name = null;
+					for (ResponseHeader a : la)
+						name = firstNonEmpty(a.name(), a.n(), a.value(), name);
+					Type type = mpi.getParameterType().innerType();
 					for (ResponseHeader a : la) {
 						if (! isMulti(a)) {
 							for (Integer code : codes) {
-								OMap header = responses.getMap(String.valueOf(code), true).getMap("headers", true).getMap(mp.name, true);
+								OMap header = responses.getMap(String.valueOf(code), true).getMap("headers", true).getMap(name, true);
 								merge(header, a);
-								mergePartSchema(header, getSchema(header, Value.getParameterType(mp.type), bs));
+								mergePartSchema(header, getSchema(header, Value.getParameterType(type), bs));
 							}
 						}
 					}
 
-				} else if (in == RESPONSE) {
-					List<Response> la = mpi.getAnnotations(Response.class);
+				} else if (mpi.hasAnnotation(Response.class) || pt.hasAnnotation(Response.class)) {
+					List<Response> la = AList.of(mpi.getAnnotations(Response.class)).aa(pt.getAnnotations(Response.class));
 					Set<Integer> codes = getCodes(la, 200);
+					Type type = mpi.getParameterType().innerType();
 					for (Response a : la) {
 						for (Integer code : codes) {
 							OMap response = responses.getMap(String.valueOf(code), true);
 							merge(response, a);
 						}
 					}
-					Type type = Value.getParameterType(mp.type);
+					type = Value.getParameterType(type);
 					if (type != null) {
 						for (String code : responses.keySet()) {
 							OMap om = responses.getMap(code);
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/Attr.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/Attr.java
index 00a03ca..293ba99 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/Attr.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/Attr.java
@@ -46,7 +46,7 @@
  * </p>

  */

 @Documented

-@Target({PARAMETER})

+@Target({PARAMETER,TYPE})

 @Retention(RUNTIME)

 @Inherited

 public @interface Attr {

diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/Rest.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/Rest.java
index b20f061..283006b 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/Rest.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/Rest.java
@@ -731,20 +731,6 @@
 	Class<?>[] onClass() default {};

 

 	/**

-	 * Java method parameter resolvers.

-	 *

-	 * <p>

-	 * By default, the Juneau framework will automatically Java method parameters of various types (e.g.

-	 * <c>RestRequest</c>, <c>Accept</c>, <c>Reader</c>).

-	 * <br>This setting allows you to provide your own resolvers for your own class types that you want resolved.

-	 *

-	 * <ul class='seealso'>

-	 * 	<li class='jf'>{@link RestContext#REST_paramResolvers}

-	 * </ul>

-	 */

-	Class<? extends RestMethodParam>[] paramResolvers() default {};

-

-	/**

 	 * Parsers.

 	 *

 	 * <p>

@@ -968,6 +954,20 @@
 	Class<? extends ResponseHandler>[] responseHandlers() default {};

 

 	/**

+	 * Java method parameter resolvers.

+	 *

+	 * <p>

+	 * By default, the Juneau framework will automatically Java method parameters of various types (e.g.

+	 * <c>RestRequest</c>, <c>Accept</c>, <c>Reader</c>).

+	 * <br>This setting allows you to provide your own resolvers for your own class types that you want resolved.

+	 *

+	 * <ul class='seealso'>

+	 * 	<li class='jf'>{@link RestContext#REST_restParams}

+	 * </ul>

+	 */

+	Class<? extends RestParam>[] restParams() default {};

+

+	/**

 	 * Role guard.

 	 *

 	 * <p>

diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestAnnotation.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestAnnotation.java
index 7a1a8d0..8e7f88b 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestAnnotation.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestAnnotation.java
@@ -94,7 +94,7 @@
 		Class<? extends RestConverter>[] converters = new Class[0];
 		Class<? extends RestGuard>[] guards = new Class[0];
 		Class<? extends RestInfoProvider> infoProvider=RestInfoProvider.Null.class;
-		Class<? extends RestMethodParam>[] paramResolvers = new Class[0];
+		Class<? extends RestParam>[] restParams = new Class[0];
 		Class<? extends BeanFactory> beanFactory = BeanFactory.Null.class;
 		Class<?>[] children={}, parsers={}, serializers={};
 		ResourceSwagger swagger = ResourceSwaggerAnnotation.DEFAULT;
@@ -415,17 +415,6 @@
 		}
 
 		/**
-		 * Sets the {@link Rest#paramResolvers()} property on this annotation.
-		 *
-		 * @param value The new value for this property.
-		 * @return This object (for method chaining).
-		 */
-		public Builder paramResolvers(Class<? extends RestMethodParam>...value) {
-			this.paramResolvers = value;
-			return this;
-		}
-
-		/**
 		 * Sets the {@link Rest#parsers()} property on this annotation.
 		 *
 		 * @param value The new value for this property.
@@ -503,6 +492,17 @@
 		}
 
 		/**
+		 * Sets the {@link Rest#restParams()} property on this annotation.
+		 *
+		 * @param value The new value for this property.
+		 * @return This object (for method chaining).
+		 */
+		public Builder restParams(Class<? extends RestParam>...value) {
+			this.restParams = value;
+			return this;
+		}
+
+		/**
 		 * Sets the {@link Rest#roleGuard()} property on this annotation.
 		 *
 		 * @param value The new value for this property.
@@ -659,7 +659,7 @@
 		private final Class<? extends RestConverter>[] converters;
 		private final Class<? extends RestGuard>[] guards;
 		private final Class<? extends RestInfoProvider> infoProvider;
-		private final Class<? extends RestMethodParam>[] paramResolvers;
+		private final Class<? extends RestParam>[] restParams;
 		private final Class<? extends BeanFactory> beanFactory;
 		private final Class<?>[] children, parsers, serializers;
 		private final ResourceSwagger swagger;
@@ -695,7 +695,7 @@
 			this.infoProvider = b.infoProvider;
 			this.maxInput = b.maxInput;
 			this.messages = b.messages;
-			this.paramResolvers = copyOf(b.paramResolvers);
+			this.restParams = copyOf(b.restParams);
 			this.parsers = copyOf(b.parsers);
 			this.partParser = b.partParser;
 			this.partSerializer = b.partSerializer;
@@ -853,11 +853,6 @@
 		}
 
 		@Override /* Rest */
-		public Class<? extends RestMethodParam>[] paramResolvers() {
-			return paramResolvers;
-		}
-
-		@Override /* Rest */
 		public Class<?>[] parsers() {
 			return parsers;
 		}
@@ -893,6 +888,11 @@
 		}
 
 		@Override /* Rest */
+		public Class<? extends RestParam>[] restParams() {
+			return restParams;
+		}
+
+		@Override /* Rest */
 		public String roleGuard() {
 			return roleGuard;
 		}
@@ -984,7 +984,7 @@
 			psb.prependTo(REST_converters, a.converters());
 			psb.prependTo(REST_guards, reverse(a.guards()));
 			psb.prependTo(REST_children, a.children());
-			psb.prependTo(REST_paramResolvers, a.paramResolvers());
+			psb.prependTo(REST_restParams, a.restParams());
 			psb.setIf(a.context() != RestContext.Null.class, REST_context, a.context());
 			psb.setIfNotEmpty(REST_uriContext, string(a.uriContext()));
 			psb.setIfNotEmpty(REST_uriAuthority, string(a.uriAuthority()));
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/params/AttributeParam.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/params/AttributeParam.java
new file mode 100644
index 0000000..fd4162c
--- /dev/null
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/params/AttributeParam.java
@@ -0,0 +1,71 @@
+// ***************************************************************************************************************************
+// * 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.params;
+
+import static org.apache.juneau.internal.StringUtils.*;
+
+import java.lang.reflect.*;
+
+import org.apache.juneau.reflect.*;
+import org.apache.juneau.rest.*;
+import org.apache.juneau.rest.annotation.*;
+
+/**
+ * Resolves method parameters annotated with {@link Attr} on {@link RestMethod}-annotated Java methods.
+ *
+ * <p>
+ * The parameter value is resolved using <c><jv>call</jv>.{@link RestCall#getRestRequest() getRestRequest}().{@link RestRequest#getAttributes() getAttributes}().{@link RequestAttributes#get(String,Type,Type...) get}(<jv>name</jv>,<jv>type</jv>)</c>.
+ */
+public class AttributeParam implements RestParam {
+
+	private final String name;
+	private final Type type;
+
+	/**
+	 * Static creator.
+	 *
+	 * @param paramInfo The Java method parameter being resolved.
+	 * @return A new {@link AttributeParam}, or <jk>null</jk> if the parameter is not annotated with {@link Attr}.
+	 */
+	public static AttributeParam create(ParamInfo paramInfo) {
+		if (paramInfo.hasAnnotation(Attr.class) || paramInfo.getParameterType().hasAnnotation(Attr.class))
+			return new AttributeParam(paramInfo);
+		return null;
+	}
+
+	/**
+	 * Constructor.
+	 *
+	 * @param paramInfo The Java method parameter being resolved.
+	 */
+	protected AttributeParam(ParamInfo paramInfo) {
+		this.name = getName(paramInfo);
+		this.type = paramInfo.getParameterType().innerType();
+	}
+
+	private String getName(ParamInfo paramInfo) {
+		String n = null;
+		for (Attr h : paramInfo.getAnnotations(Attr.class))
+			n = firstNonEmpty(h.name(), h.value(), n);
+		for (Attr h : paramInfo.getParameterType().getAnnotations(Attr.class))
+			n = firstNonEmpty(h.name(), h.value(), n);
+		if (n == null)
+			throw new ParameterException(paramInfo, "@Attr used without name or value");
+		return n;
+	}
+
+	@Override /* RestMethodParam */
+	public Object resolve(RestCall call) throws Exception {
+		return call.getRestRequest().getAttributes().get(name, type);
+	}
+}
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/params/BodyParam.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/params/BodyParam.java
new file mode 100644
index 0000000..0908f2f
--- /dev/null
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/params/BodyParam.java
@@ -0,0 +1,61 @@
+// ***************************************************************************************************************************
+// * 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.params;
+
+import java.lang.reflect.*;
+
+import org.apache.juneau.http.annotation.*;
+import org.apache.juneau.httppart.*;
+import org.apache.juneau.reflect.*;
+import org.apache.juneau.rest.*;
+import org.apache.juneau.rest.annotation.*;
+
+/**
+ * Resolves method parameters and parameter types annotated with {@link Body} on {@link RestMethod}-annotated Java methods.
+ *
+ * <p>
+ * The parameter value is resolved using <c><jv>call</jv>.{@link RestCall#getRestRequest() getRestRequest}().{@link RestRequest#getBody() getBody}().{@link RequestBody#schema(HttpPartSchema) schema}(<jv>schema</jv>).{@link RequestBody#asType(Type,Type...) asType}(<jv>type</jv>)</c>.
+ * with a {@link HttpPartSchema schema} derived from the {@link Body} annotation.
+ */
+public class BodyParam implements RestParam {
+
+	private final HttpPartSchema schema;
+	private final Type type;
+
+	/**
+	 * Static creator.
+	 *
+	 * @param paramInfo The Java method parameter being resolved.
+	 * @return A new {@link BodyParam}, or <jk>null</jk> if the parameter is not annotated with {@link Body}.
+	 */
+	public static BodyParam create(ParamInfo paramInfo) {
+		if (paramInfo.hasAnnotation(Body.class) || paramInfo.getParameterType().hasAnnotation(Body.class))
+			return new BodyParam(paramInfo);
+		return null;
+	}
+
+	/**
+	 * Constructor.
+	 *
+	 * @param paramInfo The Java method parameter being resolved.
+	 */
+	protected BodyParam(ParamInfo paramInfo) {
+		this.type = paramInfo.getParameterType().innerType();
+		this.schema = HttpPartSchema.create(Body.class, paramInfo);
+	}
+
+	@Override /* RestMethodParam */
+	public Object resolve(RestCall call) throws Exception {
+		return call.getRestRequest().getBody().schema(schema).asType(type);
+	}
+}
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/params/ConfigParam.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/params/ConfigParam.java
new file mode 100644
index 0000000..fd68315
--- /dev/null
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/params/ConfigParam.java
@@ -0,0 +1,46 @@
+// ***************************************************************************************************************************
+// * 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.params;
+
+import org.apache.juneau.config.*;
+import org.apache.juneau.reflect.*;
+import org.apache.juneau.rest.*;
+import org.apache.juneau.rest.annotation.*;
+
+/**
+ * Resolves method parameters of type {@link Config} on {@link RestMethod}-annotated Java methods.
+ *
+ * <p>
+ * The parameter value is resolved using <c><jv>call</jv>.{@link RestCall#getContext() getContext}().{@link RestContext#getConfig() getConfig}()</c>.
+ */
+public class ConfigParam extends SimpleRestParam {
+
+	/**
+	 * Static creator.
+	 *
+	 * @param paramInfo The Java method parameter being resolved.
+	 * @return A new {@link ConfigParam}, or <jk>null</jk> if the parameter type is not {@link Config}.
+	 */
+	public static ConfigParam create(ParamInfo paramInfo) {
+		if (paramInfo.isType(Config.class))
+			return new ConfigParam();
+		return null;
+	}
+
+	/**
+	 * Constructor.
+	 */
+	protected ConfigParam() {
+		super((c)->c.getContext().getConfig());
+	}
+}
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/params/DefaultParam.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/params/DefaultParam.java
new file mode 100644
index 0000000..8dab057
--- /dev/null
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/params/DefaultParam.java
@@ -0,0 +1,59 @@
+// ***************************************************************************************************************************
+// * 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.params;
+
+import org.apache.juneau.cp.*;
+import org.apache.juneau.reflect.*;
+import org.apache.juneau.rest.*;
+import org.apache.juneau.rest.annotation.*;
+
+/**
+ * Resolves method parameters on {@link RestMethod}-annotated Java methods by retrieving them by type from the REST object bean factory.
+ *
+ * <p>
+ * The parameter value is resolved using <c><jv>call</jv>.{@link RestCall#getBeanFactory() getBeanFactory}().{@link BeanFactory#getBean(Class) getBean}(<jv>type</jv>)</c>
+ * which resolves the object from the registered bean factory (e.g. Spring-injected beans available in the application).
+ *
+ * <p>
+ * This is the default parameter resolver if no other applicable parameter resolvers could be found.
+ */
+public class DefaultParam implements RestParam {
+
+	private final Class<?> type;
+	private final ParamInfo paramInfo;
+
+	/**
+	 * Static creator.
+	 *
+	 * @param paramInfo The Java method parameter being resolved.
+	 * @return A new {@link DefaultParam}, never <jk>null</jk>.
+	 */
+	public static DefaultParam create(ParamInfo paramInfo) {
+		return new DefaultParam(paramInfo);
+	}
+
+	/**
+	 * Constructor.
+	 *
+	 * @param paramInfo The Java method parameter being resolved.
+	 */
+	protected DefaultParam(ParamInfo paramInfo) {
+		this.type = paramInfo.getParameterType().inner();
+		this.paramInfo = paramInfo;
+	}
+
+	@Override /* RestMethodParam */
+	public Object resolve(RestCall call) throws Exception {
+		return call.getBeanFactory().getBean(type).orElseThrow(()->new ParameterException(paramInfo, "Could not resolve bean type {0}", type.getName()));
+	}
+}
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/params/FormDataParam.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/params/FormDataParam.java
new file mode 100644
index 0000000..f052209
--- /dev/null
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/params/FormDataParam.java
@@ -0,0 +1,103 @@
+// ***************************************************************************************************************************
+// * 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.params;
+
+import static org.apache.juneau.internal.ClassUtils.*;
+import static org.apache.juneau.internal.StringUtils.*;
+
+import java.lang.reflect.*;
+import java.util.*;
+
+import org.apache.juneau.*;
+import org.apache.juneau.http.annotation.*;
+import org.apache.juneau.httppart.*;
+import org.apache.juneau.reflect.*;
+import org.apache.juneau.rest.*;
+import org.apache.juneau.rest.annotation.*;
+
+/**
+ * Resolves method parameters and parameter types annotated with {@link FormData} on {@link RestMethod}-annotated Java methods.
+ *
+ * <p>
+ * The parameter value is resolved using <c><jv>call</jv>.{@link RestCall#getRestRequest() getRestRequest}().{@link RestRequest#getFormData() getFormData}().{@link RequestFormData#get(HttpPartParserSession,HttpPartSchema,String,Type,Type...) get}(<jv>parserSession<jv>, <jv>schema</jv>, <jv>name</jv>, <jv>type</jv>)</c>
+ * with a {@link HttpPartSchema schema} derived from the {@link FormData} annotation.
+ *
+ * <p>
+ * If the {@link FormData#multi()} flag is set, then the data type can be a {@link Collection} or array.
+ */
+public class FormDataParam implements RestParam {
+	private final boolean multi;
+	private final HttpPartParser partParser;
+	private final HttpPartSchema schema;
+	private final String name;
+	private final ClassInfo type;
+
+	/**
+	 * Static creator.
+	 *
+	 * @param paramInfo The Java method parameter being resolved.
+	 * @param ps The configuration properties of the {@link RestContext}.
+	 * @return A new {@link FormDataParam}, or <jk>null</jk> if the parameter is not annotated with {@link FormData}.
+	 */
+	public static FormDataParam create(ParamInfo paramInfo, PropertyStore ps) {
+		if (paramInfo.hasAnnotation(FormData.class) || paramInfo.getParameterType().hasAnnotation(FormData.class))
+			return new FormDataParam(paramInfo, ps);
+		return null;
+	}
+
+	/**
+	 * Constructor.
+	 *
+	 * @param paramInfo The Java method parameter being resolved.
+	 * @param ps The configuration properties of the {@link RestContext}.
+	 */
+	protected FormDataParam(ParamInfo paramInfo, PropertyStore ps) {
+		this.name = getName(paramInfo);
+		this.type = paramInfo.getParameterType();
+		this.schema = HttpPartSchema.create(FormData.class, paramInfo);
+		this.partParser = castOrCreate(HttpPartParser.class, schema.getParser(), true, ps);
+		this.multi = getMulti(paramInfo) || schema.getCollectionFormat() == HttpPartCollectionFormat.MULTI;
+
+		if (multi && ! type.isCollectionOrArray())
+			throw new ParameterException(paramInfo, "Use of multipart flag on @FormData parameter that is not an array or Collection");
+	}
+
+	private String getName(ParamInfo paramInfo) {
+		String n = null;
+		for (FormData h : paramInfo.getAnnotations(FormData.class))
+			n = firstNonEmpty(h.name(), h.n(), h.value(), n);
+		for (FormData h : paramInfo.getParameterType().getAnnotations(FormData.class))
+			n = firstNonEmpty(h.name(), h.n(), h.value(), n);
+		if (n == null)
+			throw new ParameterException(paramInfo, "@FormData used without name or value");
+		return n;
+	}
+
+	private boolean getMulti(ParamInfo paramInfo) {
+		for (FormData f : paramInfo.getAnnotations(FormData.class))
+			if (f.multi())
+				return true;
+		for (FormData f : paramInfo.getParameterType().getAnnotations(FormData.class))
+			if (f.multi())
+				return true;
+		return false;
+	}
+
+	@Override /* RestMethodParam */
+	public Object resolve(RestCall call) throws Exception {
+		RestRequest req = call.getRestRequest();
+		HttpPartParserSession ps = partParser == null ? req.getPartParser() : partParser.createPartSession(req.getParserSessionArgs());
+		RequestFormData fd = req.getFormData();
+		return multi ? fd.getAll(ps, schema, name, type.innerType()) : fd.get(ps, schema, name, type.innerType());
+	}
+}
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/params/HasFormDataParam.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/params/HasFormDataParam.java
new file mode 100644
index 0000000..8828743
--- /dev/null
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/params/HasFormDataParam.java
@@ -0,0 +1,76 @@
+// ***************************************************************************************************************************
+// * 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.params;
+
+import static org.apache.juneau.internal.StringUtils.*;
+
+import java.lang.reflect.*;
+
+import org.apache.juneau.*;
+import org.apache.juneau.http.annotation.*;
+import org.apache.juneau.reflect.*;
+import org.apache.juneau.rest.*;
+import org.apache.juneau.rest.annotation.*;
+
+/**
+ * Resolves method parameters annotated with {@link HasFormData} on {@link RestMethod}-annotated Java methods.
+ *
+ * <p>
+ * The parameter value is resolved using <c><jv>call</jv>.{@link RestCall#getRestRequest() getRestRequest}().{@link RestRequest#getFormData() getFormData}().{@link RequestFormData#containsKey(Object) containsKey}(<jv>name</jv>)</c>
+ *
+ * <p>
+ * The parameter type can be a <jk>boolean</jk> or anything convertible from a <jk>boolean</jk>.
+ */
+public class HasFormDataParam implements RestParam {
+
+	private final String name;
+	private final Type type;
+
+	/**
+	 * Static creator.
+	 *
+	 * @param paramInfo The Java method parameter being resolved.
+	 * @return A new {@link HasFormDataParam}, or <jk>null</jk> if the parameter is not annotated with {@link HasFormData}.
+	 */
+	public static HasFormDataParam create(ParamInfo paramInfo) {
+		if (paramInfo.hasAnnotation(HasFormData.class))
+			return new HasFormDataParam(paramInfo);
+		return null;
+	}
+
+	/**
+	 * Constructor.
+	 *
+	 * @param paramInfo The Java method parameter being resolved.
+	 */
+	protected HasFormDataParam(ParamInfo paramInfo) {
+		this.name = getName(paramInfo);
+		this.type = paramInfo.getParameterType().innerType();
+	}
+
+	private String getName(ParamInfo paramInfo) {
+		String n = null;
+		for (HasFormData h : paramInfo.getAnnotations(HasFormData.class))
+			n = firstNonEmpty(h.name(), h.n(), h.value(), n);
+		if (n == null)
+			throw new ParameterException(paramInfo, "@HasFormData used without name or value");
+		return n;
+	}
+
+	@Override /* RestMethodParam */
+	public Object resolve(RestCall call) throws Exception {
+		RestRequest req = call.getRestRequest();
+		BeanSession bs = req.getBeanSession();
+		return bs.convertToType(req.getFormData().containsKey(name), bs.getClassMeta(type));
+	}
+}
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/params/HasQueryParam.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/params/HasQueryParam.java
new file mode 100644
index 0000000..109f878
--- /dev/null
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/params/HasQueryParam.java
@@ -0,0 +1,76 @@
+// ***************************************************************************************************************************
+// * 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.params;
+
+import static org.apache.juneau.internal.StringUtils.*;
+
+import java.lang.reflect.*;
+
+import org.apache.juneau.*;
+import org.apache.juneau.http.annotation.*;
+import org.apache.juneau.reflect.*;
+import org.apache.juneau.rest.*;
+import org.apache.juneau.rest.annotation.*;
+
+/**
+ * Resolves method parameters annotated with {@link HasQuery} on {@link RestMethod}-annotated Java methods.
+ *
+ * <p>
+ * The parameter value is resolved using <c><jv>call</jv>.{@link RestCall#getRestRequest() getRestRequest}().{@link RestRequest#getQuery() getQuery}().{@link RequestQuery#containsKey(Object) containsKey}(<jv>name</jv>)</c>
+ *
+ * <p>
+ * The parameter type can be a <jk>boolean</jk> or anything convertible from a <jk>boolean</jk>.
+ */
+public class HasQueryParam implements RestParam {
+
+	private final String name;
+	private final Type type;
+
+	/**
+	 * Static creator.
+	 *
+	 * @param paramInfo The Java method parameter being resolved.
+	 * @return A new {@link HasQueryParam}, or <jk>null</jk> if the parameter is not annotated with {@link HasQuery}.
+	 */
+	public static HasQueryParam create(ParamInfo paramInfo) {
+		if (paramInfo.hasAnnotation(HasQuery.class))
+			return new HasQueryParam(paramInfo);
+		return null;
+	}
+
+	/**
+	 * Constructor.
+	 *
+	 * @param paramInfo The Java method parameter being resolved.
+	 */
+	protected HasQueryParam(ParamInfo paramInfo) {
+		this.name = getName(paramInfo);
+		this.type = paramInfo.getParameterType().innerType();
+	}
+
+	private String getName(ParamInfo paramInfo) {
+		String n = null;
+		for (HasQuery h : paramInfo.getAnnotations(HasQuery.class))
+			n = firstNonEmpty(h.name(), h.n(), h.value(), n);
+		if (n == null)
+			throw new ParameterException(paramInfo, "@HasQuery used without name or value");
+		return n;
+	}
+
+	@Override /* RestMethodParam */
+	public Object resolve(RestCall call) throws Exception {
+		RestRequest req = call.getRestRequest();
+		BeanSession bs = req.getBeanSession();
+		return bs.convertToType(req.getQuery().containsKey(name), bs.getClassMeta(type));
+	}
+}
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/params/HeaderParam.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/params/HeaderParam.java
new file mode 100644
index 0000000..dccfe5d
--- /dev/null
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/params/HeaderParam.java
@@ -0,0 +1,103 @@
+// ***************************************************************************************************************************
+// * 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.params;
+
+import static org.apache.juneau.internal.ClassUtils.*;
+import static org.apache.juneau.internal.StringUtils.*;
+
+import java.lang.reflect.*;
+import java.util.*;
+
+import org.apache.juneau.*;
+import org.apache.juneau.http.annotation.*;
+import org.apache.juneau.httppart.*;
+import org.apache.juneau.reflect.*;
+import org.apache.juneau.rest.*;
+import org.apache.juneau.rest.annotation.*;
+
+/**
+ * Resolves method parameters and parameter types annotated with {@link Header} on {@link RestMethod}-annotated Java methods.
+ *
+ * <p>
+ * The parameter value is resolved using <c><jv>call</jv>.{@link RestCall#getRestRequest() getRestRequest}().{@link RestRequest#getHeaders() getHeaders}().{@link RequestHeaders#get(HttpPartParserSession,HttpPartSchema,String,Type,Type...) get}(<jv>parserSession<jv>, <jv>schema</jv>, <jv>name</jv>, <jv>type</jv>)</c>
+ * with a {@link HttpPartSchema schema} derived from the {@link Header} annotation.
+ *
+ * <p>
+ * If the {@link Header#multi()} flag is set, then the data type can be a {@link Collection} or array.
+ */
+public class HeaderParam implements RestParam {
+	private final HttpPartParser partParser;
+	private final HttpPartSchema schema;
+	private final boolean multi;
+	private final String name;
+	private final ClassInfo type;
+
+	/**
+	 * Static creator.
+	 *
+	 * @param paramInfo The Java method parameter being resolved.
+	 * @param ps The configuration properties of the {@link RestContext}.
+	 * @return A new {@link HeaderParam}, or <jk>null</jk> if the parameter is not annotated with {@link Header}.
+	 */
+	public static HeaderParam create(ParamInfo paramInfo, PropertyStore ps) {
+		if (paramInfo.hasAnnotation(Header.class) || paramInfo.getParameterType().hasAnnotation(Header.class))
+			return new HeaderParam(paramInfo, ps);
+		return null;
+	}
+
+	/**
+	 * Constructor.
+	 *
+	 * @param paramInfo The Java method parameter being resolved.
+	 * @param ps The configuration properties of the {@link RestContext}.
+	 */
+	protected HeaderParam(ParamInfo paramInfo, PropertyStore ps) {
+		this.name = getName(paramInfo);
+		this.type = paramInfo.getParameterType();
+		this.schema = HttpPartSchema.create(Header.class, paramInfo);
+		this.partParser = castOrCreate(HttpPartParser.class, schema.getParser(), true, ps);
+		this.multi = getMulti(paramInfo);
+
+		if (multi && ! type.isCollectionOrArray())
+			throw new ParameterException(paramInfo, "Use of multipart flag on @Header parameter that is not an array or Collection");
+	}
+
+	private String getName(ParamInfo paramInfo) {
+		String n = null;
+		for (Header h : paramInfo.getAnnotations(Header.class))
+			n = firstNonEmpty(h.name(), h.n(), h.value(), n);
+		for (Header h : paramInfo.getParameterType().getAnnotations(Header.class))
+			n = firstNonEmpty(h.name(), h.n(), h.value(), n);
+		if (n == null)
+			throw new ParameterException(paramInfo, "@Header used without name or value");
+		return n;
+	}
+
+	private boolean getMulti(ParamInfo paramInfo) {
+		for (Header h : paramInfo.getAnnotations(Header.class))
+			if (h.multi())
+				return true;
+		for (Header h : paramInfo.getParameterType().getAnnotations(Header.class))
+			if (h.multi())
+				return true;
+		return false;
+	}
+
+	@Override /* RestMethodParam */
+	public Object resolve(RestCall call) throws Exception {
+		RestRequest req = call.getRestRequest();
+		HttpPartParserSession ps = partParser == null ? req.getPartParser() : partParser.createPartSession(req.getParserSessionArgs());
+		RequestHeaders rh = call.getRestRequest().getHeaders();
+		return multi ? rh.getAll(ps, schema, name, type.innerType()) : rh.get(ps, schema, name, type.innerType());
+	}
+}
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/params/HttpServletRequestParam.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/params/HttpServletRequestParam.java
new file mode 100644
index 0000000..e68f5a3
--- /dev/null
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/params/HttpServletRequestParam.java
@@ -0,0 +1,48 @@
+// ***************************************************************************************************************************
+// * 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.params;
+
+
+import javax.servlet.http.*;
+
+import org.apache.juneau.reflect.*;
+import org.apache.juneau.rest.*;
+import org.apache.juneau.rest.annotation.*;
+
+/**
+ * Resolves method parameters of type {@link HttpServletRequest} on {@link RestMethod}-annotated Java methods.
+ *
+ * <p>
+ * The parameter value is resolved using <c><jv>call</jv>.{@link RestCall#getRequest() getRequest}()</c>.
+ */
+public class HttpServletRequestParam extends SimpleRestParam {
+
+	/**
+	 * Static creator.
+	 *
+	 * @param paramInfo The Java method parameter being resolved.
+	 * @return A new {@link HttpServletRequestParam}, or <jk>null</jk> if the parameter type is not {@link HttpServletRequest}.
+	 */
+	public static HttpServletRequestParam create(ParamInfo paramInfo) {
+		if (paramInfo.isType(HttpServletRequest.class))
+			return new HttpServletRequestParam();
+		return null;
+	}
+
+	/**
+	 * Constructor.
+	 */
+	protected HttpServletRequestParam() {
+		super((c)->c.getRequest());
+	}
+}
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/params/HttpServletResponseParam.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/params/HttpServletResponseParam.java
new file mode 100644
index 0000000..4628255
--- /dev/null
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/params/HttpServletResponseParam.java
@@ -0,0 +1,47 @@
+// ***************************************************************************************************************************
+// * 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.params;
+
+import javax.servlet.http.*;
+
+import org.apache.juneau.reflect.*;
+import org.apache.juneau.rest.*;
+import org.apache.juneau.rest.annotation.*;
+
+/**
+ * Resolves method parameters of type {@link HttpServletResponse} on {@link RestMethod}-annotated Java methods.
+ *
+ * <p>
+ * The parameter value is resolved using <c><jv>call</jv>.{@link RestCall#getResponse() getResponse}()</c>.
+ */
+public class HttpServletResponseParam extends SimpleRestParam {
+
+	/**
+	 * Static creator.
+	 *
+	 * @param paramInfo The Java method parameter being resolved.
+	 * @return A new {@link HttpServletResponse}, or <jk>null</jk> if the parameter type is not {@link HttpServletResponse}.
+	 */
+	public static HttpServletResponseParam create(ParamInfo paramInfo) {
+		if (paramInfo.isType(HttpServletResponse.class))
+			return new HttpServletResponseParam();
+		return null;
+	}
+
+	/**
+	 * Constructor.
+	 */
+	protected HttpServletResponseParam() {
+		super((c)->c.getResponse());
+	}
+}
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/params/InputStreamParam.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/params/InputStreamParam.java
new file mode 100644
index 0000000..666041e
--- /dev/null
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/params/InputStreamParam.java
@@ -0,0 +1,47 @@
+// ***************************************************************************************************************************
+// * 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.params;
+
+import java.io.*;
+
+import org.apache.juneau.reflect.*;
+import org.apache.juneau.rest.*;
+import org.apache.juneau.rest.annotation.*;
+
+/**
+ * Resolves method parameters of type {@link InputStream} on {@link RestMethod}-annotated Java methods.
+ *
+ * <p>
+ * The parameter value is resolved using <c><jv>call</jv>.{@link RestCall#getRestRequest() getRestRequest}().{@link RestRequest#getInputStream() getInputStream}()</c>.
+ */
+public class InputStreamParam extends SimpleRestParam {
+
+	/**
+	 * Static creator.
+	 *
+	 * @param paramInfo The Java method parameter being resolved.
+	 * @return A new {@link InputStreamParam}, or <jk>null</jk> if the parameter type is not {@link InputStream}.
+	 */
+	public static InputStreamParam create(ParamInfo paramInfo) {
+		if (paramInfo.isType(InputStream.class))
+			return new InputStreamParam();
+		return null;
+	}
+
+	/**
+	 * Constructor.
+	 */
+	protected InputStreamParam() {
+		super((c)->c.getRestRequest().getInputStream());
+	}
+}
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/params/InputStreamParserParam.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/params/InputStreamParserParam.java
new file mode 100644
index 0000000..6152790
--- /dev/null
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/params/InputStreamParserParam.java
@@ -0,0 +1,46 @@
+// ***************************************************************************************************************************
+// * 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.params;
+
+import org.apache.juneau.parser.*;
+import org.apache.juneau.reflect.*;
+import org.apache.juneau.rest.*;
+import org.apache.juneau.rest.annotation.*;
+
+/**
+ * Resolves method parameters of type {@link InputStreamParser} on {@link RestMethod}-annotated Java methods.
+ *
+ * <p>
+ * The parameter value is resolved using <c><jv>call</jv>.{@link RestCall#getRestRequest() getRestRequest}().{@link RestRequest#getBody() getBody}().{@link RequestBody#getInputStreamParser() getInputStreamParser}()</c>.
+ */
+public class InputStreamParserParam extends SimpleRestParam {
+
+	/**
+	 * Static creator.
+	 *
+	 * @param paramInfo The Java method parameter being resolved.
+	 * @return A new {@link InputStreamParserParam}, or <jk>null</jk> if the parameter type is not {@link InputStreamParser}.
+	 */
+	public static InputStreamParserParam create(ParamInfo paramInfo) {
+		if (paramInfo.isType(InputStreamParser.class))
+			return new InputStreamParserParam();
+		return null;
+	}
+
+	/**
+	 * Constructor.
+	 */
+	protected InputStreamParserParam() {
+		super((c)->c.getRestRequest().getBody().getInputStreamParser());
+	}
+}
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/params/LocaleParam.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/params/LocaleParam.java
new file mode 100644
index 0000000..569f218
--- /dev/null
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/params/LocaleParam.java
@@ -0,0 +1,47 @@
+// ***************************************************************************************************************************
+// * 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.params;
+
+import java.util.*;
+
+import org.apache.juneau.reflect.*;
+import org.apache.juneau.rest.*;
+import org.apache.juneau.rest.annotation.*;
+
+/**
+ * Resolves method parameters of type {@link Locale} on {@link RestMethod}-annotated Java methods.
+ *
+ * <p>
+ * The parameter value is resolved using <c><jv>call</jv>.{@link RestCall#getRestRequest() getRestRequest}().{@link RestRequest#getLocale() getLocale}()</c>.
+ */
+public class LocaleParam extends SimpleRestParam {
+
+	/**
+	 * Static creator.
+	 *
+	 * @param paramInfo The Java method parameter being resolved.
+	 * @return A new {@link LocaleParam}, or <jk>null</jk> if the parameter type is not {@link Locale}.
+	 */
+	public static LocaleParam create(ParamInfo paramInfo) {
+		if (paramInfo.isType(Locale.class))
+			return new LocaleParam();
+		return null;
+	}
+
+	/**
+	 * Constructor.
+	 */
+	protected LocaleParam() {
+		super((c)->c.getRestRequest().getLocale());
+	}
+}
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/params/MessagesParam.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/params/MessagesParam.java
new file mode 100644
index 0000000..daa6c0c
--- /dev/null
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/params/MessagesParam.java
@@ -0,0 +1,46 @@
+// ***************************************************************************************************************************
+// * 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.params;
+
+import org.apache.juneau.cp.*;
+import org.apache.juneau.reflect.*;
+import org.apache.juneau.rest.*;
+import org.apache.juneau.rest.annotation.*;
+
+/**
+ * Resolves method parameters of type {@link Messages} on {@link RestMethod}-annotated Java methods.
+ *
+ * <p>
+ * The parameter value is resolved using <c><jv>call</jv>.{@link RestCall#getRestRequest() getRestRequest}().{@link RestRequest#getMessages() getMessages}()</c>.
+ */
+public class MessagesParam extends SimpleRestParam {
+
+	/**
+	 * Static creator.
+	 *
+	 * @param paramInfo The Java method parameter being resolved.
+	 * @return A new {@link MessagesParam}, or <jk>null</jk> if the parameter type is not {@link Messages}.
+	 */
+	public static MessagesParam create(ParamInfo paramInfo) {
+		if (paramInfo.isType(Messages.class))
+			return new MessagesParam();
+		return null;
+	}
+
+	/**
+	 * Constructor.
+	 */
+	protected MessagesParam() {
+		super((c)->c.getRestRequest().getMessages());
+	}
+}
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/params/MethodParam.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/params/MethodParam.java
new file mode 100644
index 0000000..adf315c
--- /dev/null
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/params/MethodParam.java
@@ -0,0 +1,52 @@
+// ***************************************************************************************************************************
+// * 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.params;
+
+import org.apache.juneau.reflect.*;
+import org.apache.juneau.rest.*;
+import org.apache.juneau.rest.annotation.*;
+
+/**
+ * Resolves method parameters annotated with {@link Method} on {@link RestMethod}-annotated Java methods.
+ *
+ * <p>
+ * The parameter value is resolved using <c><jv>call</jv>.{@link RestCall#getRestRequest() getRestRequest}().{@link RestRequest#getMethod() getMethod}()</c>.
+ *
+ * <p>
+ * The parameter type must be {@link String}.
+ */
+public class MethodParam implements RestParam {
+
+	/**
+	 * Static creator.
+	 *
+	 * @param paramInfo The Java method parameter being resolved.
+	 * @return A new {@link MethodParam}, or <jk>null</jk> if the parameter isn't annotated with {@link Method}.
+	 */
+	public static MethodParam create(ParamInfo paramInfo) {
+		if (paramInfo.hasAnnotation(Method.class))
+			return new MethodParam();
+		return null;
+	}
+
+	/**
+	 * Constructor.
+	 */
+	protected MethodParam() {
+	}
+
+	@Override /* RestMethodParam */
+	public Object resolve(RestCall call) throws Exception {
+		return call.getRestRequest().getMethod();
+	}
+}
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/params/OutputStreamParam.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/params/OutputStreamParam.java
new file mode 100644
index 0000000..af4dcee
--- /dev/null
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/params/OutputStreamParam.java
@@ -0,0 +1,47 @@
+// ***************************************************************************************************************************
+// * 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.params;
+
+import java.io.*;
+
+import org.apache.juneau.reflect.*;
+import org.apache.juneau.rest.*;
+import org.apache.juneau.rest.annotation.*;
+
+/**
+ * Resolves method parameters of type {@link OutputStream} on {@link RestMethod}-annotated Java methods.
+ *
+ * <p>
+ * The parameter value is resolved using <c><jv>call</jv>.{@link RestCall#getRestResponse() getRestResponse}().{@link RestResponse#getOutputStream() getOutputStream}()</c>.
+ */
+public class OutputStreamParam extends SimpleRestParam {
+
+	/**
+	 * Static creator.
+	 *
+	 * @param paramInfo The Java method parameter being resolved.
+	 * @return A new {@link OutputStreamParam}, or <jk>null</jk> if the parameter type is not {@link OutputStream}.
+	 */
+	public static OutputStreamParam create(ParamInfo paramInfo) {
+		if (paramInfo.isType(OutputStream.class))
+			return new OutputStreamParam();
+		return null;
+	}
+
+	/**
+	 * Constructor.
+	 */
+	protected OutputStreamParam() {
+		super((c)->c.getRestResponse().getOutputStream());
+	}
+}
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/params/ParameterException.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/params/ParameterException.java
new file mode 100644
index 0000000..c812612
--- /dev/null
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/params/ParameterException.java
@@ -0,0 +1,37 @@
+// ***************************************************************************************************************************
+// * 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.params;
+
+import static org.apache.juneau.internal.StringUtils.*;
+
+import org.apache.juneau.http.exception.*;
+import org.apache.juneau.reflect.*;
+
+/**
+ * General exception due to a malformed Java parameter.
+ */
+public class ParameterException extends InternalServerError {
+	private static final long serialVersionUID = 1L;
+
+	/**
+	 * Constructor.
+	 *
+	 * @param pi The parameter with the issue.
+	 * @param msg The message.
+	 * @param args The message args.
+	 */
+	public ParameterException(ParamInfo pi, String msg, Object...args) {
+		super(format(msg, args) + " on parameter "+pi.getIndex()+" of method "+pi.getMethod().getFullName()+".");
+	}
+
+}
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/params/ParserParam.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/params/ParserParam.java
new file mode 100644
index 0000000..01e4ce5
--- /dev/null
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/params/ParserParam.java
@@ -0,0 +1,46 @@
+// ***************************************************************************************************************************
+// * 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.params;
+
+import org.apache.juneau.parser.*;
+import org.apache.juneau.reflect.*;
+import org.apache.juneau.rest.*;
+import org.apache.juneau.rest.annotation.*;
+
+/**
+ * Resolves method parameters of type {@link Parser} on {@link RestMethod}-annotated Java methods.
+ *
+ * <p>
+ * The parameter value is resolved using <c><jv>call</jv>.{@link RestCall#getRestRequest() getRestRequest}().{@link RestRequest#getBody() getBody}().{@link RequestBody#getParser() getParser}()</c>.
+ */
+public class ParserParam extends SimpleRestParam {
+
+	/**
+	 * Static creator.
+	 *
+	 * @param paramInfo The Java method parameter being resolved.
+	 * @return A new {@link ParserParam}, or <jk>null</jk> if the parameter type is not {@link Parser}.
+	 */
+	public static ParserParam create(ParamInfo paramInfo) {
+		if (paramInfo.isType(Parser.class))
+			return new ParserParam();
+		return null;
+	}
+
+	/**
+	 * Constructor.
+	 */
+	protected ParserParam() {
+		super((c)->c.getRestRequest().getBody().getParser());
+	}
+}
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/params/PathParam.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/params/PathParam.java
new file mode 100644
index 0000000..14f6a8f
--- /dev/null
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/params/PathParam.java
@@ -0,0 +1,108 @@
+// ***************************************************************************************************************************
+// * 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.params;
+
+import static org.apache.juneau.internal.ClassUtils.*;
+import static org.apache.juneau.internal.StringUtils.*;
+
+import java.lang.reflect.*;
+
+import org.apache.juneau.*;
+import org.apache.juneau.http.annotation.*;
+import org.apache.juneau.httppart.*;
+import org.apache.juneau.internal.*;
+import org.apache.juneau.reflect.*;
+import org.apache.juneau.rest.*;
+import org.apache.juneau.rest.annotation.*;
+import org.apache.juneau.rest.util.*;
+
+/**
+ * Resolves method parameters and parameter types annotated with {@link Path} on {@link RestMethod}-annotated Java methods.
+ *
+ * <p>
+ * The parameter value is resolved using <c><jv>call</jv>.{@link RestCall#getRestRequest() getRestRequest}().{@link RestRequest#getPathMatch() getPathMatch}().{@link RequestPath#get(HttpPartParserSession,HttpPartSchema,String,Type,Type...) get}(<jv>parserSession<jv>, <jv>schema</jv>, <jv>name</jv>, <jv>type</jv>)</c>
+ * with a {@link HttpPartSchema schema} derived from the {@link Path} annotation.
+ */
+public class PathParam implements RestParam {
+	private final HttpPartParser partParser;
+	private final HttpPartSchema schema;
+	private final String name;
+	private final Type type;
+
+	/**
+	 * Static creator.
+	 *
+	 * @param paramInfo The Java method parameter being resolved.
+	 * @param ps The configuration properties of the {@link RestContext}.
+	 * @param pathMatcher Path matcher for the specified method.
+	 * @return A new {@link PathParam}, or <jk>null</jk> if the parameter is not annotated with {@link Path}.
+	 */
+	public static PathParam create(ParamInfo paramInfo, PropertyStore ps, UrlPathMatcher pathMatcher) {
+		if (paramInfo.hasAnnotation(Path.class) || paramInfo.getParameterType().hasAnnotation(Path.class))
+			return new PathParam(paramInfo, ps, pathMatcher);
+		return null;
+	}
+
+	/**
+	 * Constructor.
+	 *
+	 * @param paramInfo The Java method parameter being resolved.
+	 * @param ps The configuration properties of the {@link RestContext}.
+	 * @param pathMatcher Path matcher for the specified method.
+	 */
+	protected PathParam(ParamInfo paramInfo, PropertyStore ps, UrlPathMatcher pathMatcher) {
+		this.name = getName(paramInfo, pathMatcher);
+		this.type = paramInfo.getParameterType().innerType();
+		this.schema = HttpPartSchema.create(Path.class, paramInfo);
+		this.partParser = castOrCreate(HttpPartParser.class, schema.getParser(), true, ps);
+	}
+
+	private String getName(ParamInfo paramInfo, UrlPathMatcher pathMatcher) {
+		String p = null;
+		for (Path h : paramInfo.getAnnotations(Path.class))
+			p = firstNonEmpty(h.name(), h.n(), h.value(), p);
+		for (Path h : paramInfo.getParameterType().getAnnotations(Path.class))
+			p = firstNonEmpty(h.name(), h.n(), h.value(), p);
+		if (p != null)
+			return p;
+		if (pathMatcher != null) {
+			int idx = 0;
+			int i = paramInfo.getIndex();
+			MethodInfo mi = paramInfo.getMethod();
+
+			for (int j = 0; j < i; j++)
+				if (mi.getParam(i).getLastAnnotation(Path.class) != null)
+					idx++;
+
+			String[] vars = pathMatcher.getVars();
+			if (vars.length <= idx)
+				throw new ParameterException(paramInfo, "Number of attribute parameters exceeds the number of URL pattern variables");
+
+			// Check for {#} variables.
+			String idxs = String.valueOf(idx);
+			for (int j = 0; j < vars.length; j++)
+				if (StringUtils.isNumeric(vars[j]) && vars[j].equals(idxs))
+					return vars[j];
+
+			return pathMatcher.getVars()[idx];
+		}
+		throw new ParameterException(paramInfo, "@Path used without name or value");
+	}
+
+	@Override /* RestMethodParam */
+	public Object resolve(RestCall call) throws Exception {
+		RestRequest req = call.getRestRequest();
+		HttpPartParserSession ps = partParser == null ? req.getPartParser() : partParser.createPartSession(req.getParserSessionArgs());
+		return call.getRestRequest().getPathMatch().get(ps, schema, name, type);
+	}
+}
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/params/QueryParam.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/params/QueryParam.java
new file mode 100644
index 0000000..230f529
--- /dev/null
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/params/QueryParam.java
@@ -0,0 +1,99 @@
+// ***************************************************************************************************************************
+// * 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.params;
+
+import static org.apache.juneau.internal.ClassUtils.*;
+import static org.apache.juneau.internal.StringUtils.*;
+
+import java.lang.reflect.*;
+
+import org.apache.juneau.*;
+import org.apache.juneau.http.annotation.*;
+import org.apache.juneau.httppart.*;
+import org.apache.juneau.reflect.*;
+import org.apache.juneau.rest.*;
+import org.apache.juneau.rest.annotation.*;
+
+/**
+ * Resolves method parameters and parameter types annotated with {@link Query} on {@link RestMethod}-annotated Java methods.
+ *
+ * <p>
+ * The parameter value is resolved using <c><jv>call</jv>.{@link RestCall#getRestRequest() getRestRequest}().{@link RestRequest#getQuery() getQuery}().{@link RequestQuery#get(HttpPartParserSession,HttpPartSchema,String,Type,Type...) get}(<jv>parserSession<jv>, <jv>schema</jv>, <jv>name</jv>, <jv>type</jv>)</c>
+ * with a {@link HttpPartSchema schema} derived from the {@link Query} annotation.
+ */
+public class QueryParam implements RestParam {
+	private final boolean multi;
+	private final HttpPartParser partParser;
+	private final HttpPartSchema schema;
+	private final String name;
+	private final ClassInfo type;
+
+	/**
+	 * Static creator.
+	 *
+	 * @param paramInfo The Java method parameter being resolved.
+	 * @param ps The configuration properties of the {@link RestContext}.
+	 * @return A new {@link QueryParam}, or <jk>null</jk> if the parameter is not annotated with {@link Query}.
+	 */
+	public static QueryParam create(ParamInfo paramInfo, PropertyStore ps) {
+		if (paramInfo.hasAnnotation(Query.class) || paramInfo.getParameterType().hasAnnotation(Query.class))
+			return new QueryParam(paramInfo, ps);
+		return null;
+	}
+
+	/**
+	 * Constructor.
+	 *
+	 * @param paramInfo The Java method parameter being resolved.
+	 * @param ps The configuration properties of the {@link RestContext}.
+	 */
+	protected QueryParam(ParamInfo paramInfo, PropertyStore ps) {
+		this.name = getName(paramInfo);
+		this.type = paramInfo.getParameterType();
+		this.schema = HttpPartSchema.create(Query.class, paramInfo);
+		this.partParser = castOrCreate(HttpPartParser.class, schema.getParser(), true, ps);
+		this.multi = getMulti(paramInfo) || schema.getCollectionFormat() == HttpPartCollectionFormat.MULTI;
+
+		if (multi && ! type.isCollectionOrArray())
+			throw new ParameterException(paramInfo, "Use of multipart flag on @Query parameter that is not an array or Collection");
+	}
+
+	private String getName(ParamInfo paramInfo) {
+		String n = null;
+		for (Query h : paramInfo.getAnnotations(Query.class))
+			n = firstNonEmpty(h.name(), h.n(), h.value(), n);
+		for (Query h : paramInfo.getParameterType().getAnnotations(Query.class))
+			n = firstNonEmpty(h.name(), h.n(), h.value(), n);
+		if (n == null)
+			throw new ParameterException(paramInfo, "@Query used without name or value");
+		return n;
+	}
+
+	private boolean getMulti(ParamInfo paramInfo) {
+		for (Query q : paramInfo.getAnnotations(Query.class))
+			if (q.multi())
+				return true;
+		for (Query q : paramInfo.getParameterType().getAnnotations(Query.class))
+			if (q.multi())
+				return true;
+		return false;
+	}
+
+	@Override /* RestMethodParam */
+	public Object resolve(RestCall call) throws Exception {
+		RestRequest req = call.getRestRequest();
+		HttpPartParserSession ps = partParser == null ? req.getPartParser() : partParser.createPartSession(req.getParserSessionArgs());
+		RequestQuery rq = req.getQuery();
+		return multi ? rq.getAll(ps, schema, name, type.innerType()) : rq.get(ps, schema, name, type.innerType());
+	}
+}
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/params/ReaderParam.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/params/ReaderParam.java
new file mode 100644
index 0000000..d2782ca
--- /dev/null
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/params/ReaderParam.java
@@ -0,0 +1,47 @@
+// ***************************************************************************************************************************
+// * 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.params;
+
+import java.io.*;
+
+import org.apache.juneau.reflect.*;
+import org.apache.juneau.rest.*;
+import org.apache.juneau.rest.annotation.*;
+
+/**
+ * Resolves method parameters of type {@link Reader} on {@link RestMethod}-annotated Java methods.
+ *
+ * <p>
+ * The parameter value is resolved using <c><jv>call</jv>.{@link RestCall#getRestRequest() getRestRequest}().{@link RestRequest#getReader() getReader}()</c>.
+ */
+public class ReaderParam extends SimpleRestParam {
+
+	/**
+	 * Static creator.
+	 *
+	 * @param paramInfo The Java method parameter being resolved.
+	 * @return A new {@link ReaderParam}, or <jk>null</jk> if the parameter type is not {@link Reader}.
+	 */
+	public static ReaderParam create(ParamInfo paramInfo) {
+		if (paramInfo.isType(Reader.class))
+			return new ReaderParam();
+		return null;
+	}
+
+	/**
+	 * Constructor.
+	 */
+	protected ReaderParam() {
+		super((c)->c.getRestRequest().getReader());
+	}
+}
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/params/ReaderParserParam.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/params/ReaderParserParam.java
new file mode 100644
index 0000000..8c35d39
--- /dev/null
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/params/ReaderParserParam.java
@@ -0,0 +1,46 @@
+// ***************************************************************************************************************************
+// * 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.params;
+
+import org.apache.juneau.parser.*;
+import org.apache.juneau.reflect.*;
+import org.apache.juneau.rest.*;
+import org.apache.juneau.rest.annotation.*;
+
+/**
+ * Resolves method parameters of type {@link ReaderParser} on {@link RestMethod}-annotated Java methods.
+ *
+ * <p>
+ * The parameter value is resolved using <c><jv>call</jv>.{@link RestCall#getRestRequest() getRestRequest}().{@link RestRequest#getBody() getBody}().{@link RequestBody#getReaderParser() getReaderParser}()</c>.
+ */
+public class ReaderParserParam extends SimpleRestParam {
+
+	/**
+	 * Static creator.
+	 *
+	 * @param paramInfo The Java method parameter being resolved.
+	 * @return A new {@link ReaderParserParam}, or <jk>null</jk> if the parameter type is not {@link ReaderParser}.
+	 */
+	public static ReaderParserParam create(ParamInfo paramInfo) {
+		if (paramInfo.isType(ReaderParser.class))
+			return new ReaderParserParam();
+		return null;
+	}
+
+	/**
+	 * Constructor.
+	 */
+	protected ReaderParserParam() {
+		super((c)->c.getRestRequest().getBody().getReaderParser());
+	}
+}
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/params/RequestAttributesParam.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/params/RequestAttributesParam.java
new file mode 100644
index 0000000..0f61d75
--- /dev/null
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/params/RequestAttributesParam.java
@@ -0,0 +1,45 @@
+// ***************************************************************************************************************************
+// * 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.params;
+
+import org.apache.juneau.reflect.*;
+import org.apache.juneau.rest.*;
+import org.apache.juneau.rest.annotation.*;
+
+/**
+ * Resolves method parameters of type {@link RequestAttributes} on {@link RestMethod}-annotated Java methods.
+ *
+ * <p>
+ * The parameter value is resolved using <c><jv>call</jv>.{@link RestCall#getRestRequest() getRestRequest}().{@link RestRequest#getAttributes() getAttributes}()</c>.
+ */
+public class RequestAttributesParam extends SimpleRestParam {
+
+	/**
+	 * Static creator.
+	 *
+	 * @param paramInfo The Java method parameter being resolved.
+	 * @return A new {@link RequestAttributesParam}, or <jk>null</jk> if the parameter type is not {@link RequestAttributes}.
+	 */
+	public static RequestAttributesParam create(ParamInfo paramInfo) {
+		if (paramInfo.isType(RequestAttributes.class))
+			return new RequestAttributesParam();
+		return null;
+	}
+
+	/**
+	 * Constructor.
+	 */
+	protected RequestAttributesParam() {
+		super((c)->c.getRestRequest().getAttributes());
+	}
+}
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/params/RequestBeanParam.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/params/RequestBeanParam.java
new file mode 100644
index 0000000..9e7c734
--- /dev/null
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/params/RequestBeanParam.java
@@ -0,0 +1,59 @@
+// ***************************************************************************************************************************
+// * 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.params;
+
+import org.apache.juneau.*;
+import org.apache.juneau.http.annotation.*;
+import org.apache.juneau.httppart.bean.*;
+import org.apache.juneau.reflect.*;
+import org.apache.juneau.rest.*;
+import org.apache.juneau.rest.annotation.*;
+
+/**
+ * Resolves method parameters annotated with {@link Request} on {@link RestMethod}-annotated Java methods.
+ *
+ * <p>
+ * The parameter value is resolved using <c><jv>call</jv>.{@link RestCall#getRestRequest() getRestRequest}().{@link RestRequest#getRequest(RequestBeanMeta) getRequest}(<jv>requestBeanMeta</jv>)</c>
+ * with a {@link RequestBeanMeta meta} derived from the {@link Request} annotation and context configuration.
+ */
+public class RequestBeanParam implements RestParam {
+	private final RequestBeanMeta meta;
+
+	/**
+	 * Static creator.
+	 *
+	 * @param paramInfo The Java method parameter being resolved.
+	 * @param ps The configuration properties of the {@link RestContext}.
+	 * @return A new {@link RequestBeanParam}, or <jk>null</jk> if the parameter is not annotated with {@link Request}.
+	 */
+	public static RequestBeanParam create(ParamInfo paramInfo, PropertyStore ps) {
+		if (paramInfo.hasAnnotation(Request.class))
+			return new RequestBeanParam(paramInfo, ps);
+		return null;
+	}
+
+	/**
+	 * Constructor.
+	 *
+	 * @param paramInfo The Java method parameter being resolved.
+	 * @param ps The configuration properties of the {@link RestContext}.
+	 */
+	protected RequestBeanParam(ParamInfo paramInfo, PropertyStore ps) {
+		this.meta = RequestBeanMeta.create(paramInfo, ps);
+	}
+
+	@Override /* RestMethodParam */
+	public Object resolve(RestCall call) throws Exception {
+		return call.getRestRequest().getRequest(meta);
+	}
+}
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/params/RequestBodyParam.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/params/RequestBodyParam.java
new file mode 100644
index 0000000..09f44ab
--- /dev/null
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/params/RequestBodyParam.java
@@ -0,0 +1,45 @@
+// ***************************************************************************************************************************
+// * 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.params;
+
+import org.apache.juneau.reflect.*;
+import org.apache.juneau.rest.*;
+import org.apache.juneau.rest.annotation.*;
+
+/**
+ * Resolves method parameters of type {@link RequestBody} on {@link RestMethod}-annotated Java methods.
+ *
+ * <p>
+ * The parameter value is resolved using <c><jv>call</jv>.{@link RestCall#getRestRequest() getRestRequest}().{@link RestRequest#getBody() getBody}()</c>.
+ */
+public class RequestBodyParam extends SimpleRestParam {
+
+	/**
+	 * Static creator.
+	 *
+	 * @param paramInfo The Java method parameter being resolved.
+	 * @return A new {@link RequestBodyParam}, or <jk>null</jk> if the parameter type is not {@link RequestBody}.
+	 */
+	public static RequestBodyParam create(ParamInfo paramInfo) {
+		if (paramInfo.isType(RequestBody.class))
+			return new RequestBodyParam();
+		return null;
+	}
+
+	/**
+	 * Constructor.
+	 */
+	protected RequestBodyParam() {
+		super((c)->c.getRestRequest().getBody());
+	}
+}
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/params/RequestFormDataParam.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/params/RequestFormDataParam.java
new file mode 100644
index 0000000..841132f
--- /dev/null
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/params/RequestFormDataParam.java
@@ -0,0 +1,45 @@
+// ***************************************************************************************************************************
+// * 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.params;
+
+import org.apache.juneau.reflect.*;
+import org.apache.juneau.rest.*;
+import org.apache.juneau.rest.annotation.*;
+
+/**
+ * Resolves method parameters of type {@link RequestFormData} on {@link RestMethod}-annotated Java methods.
+ *
+ * <p>
+ * The parameter value is resolved using <c><jv>call</jv>.{@link RestCall#getRestRequest() getRestRequest}().{@link RestRequest#getFormData() getFormData}()</c>.
+ */
+public class RequestFormDataParam extends SimpleRestParam {
+
+	/**
+	 * Static creator.
+	 *
+	 * @param paramInfo The Java method parameter being resolved.
+	 * @return A new {@link RequestFormDataParam}, or <jk>null</jk> if the parameter type is not {@link RequestFormData}.
+	 */
+	public static RequestFormDataParam create(ParamInfo paramInfo) {
+		if (paramInfo.isType(RequestFormData.class))
+			return new RequestFormDataParam();
+		return null;
+	}
+
+	/**
+	 * Constructor.
+	 */
+	protected RequestFormDataParam() {
+		super((c)->c.getRestRequest().getFormData());
+	}
+}
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/params/RequestHeadersParam.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/params/RequestHeadersParam.java
new file mode 100644
index 0000000..6056655
--- /dev/null
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/params/RequestHeadersParam.java
@@ -0,0 +1,45 @@
+// ***************************************************************************************************************************
+// * 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.params;
+
+import org.apache.juneau.reflect.*;
+import org.apache.juneau.rest.*;
+import org.apache.juneau.rest.annotation.*;
+
+/**
+ * Resolves method parameters of type {@link RequestHeaders} on {@link RestMethod}-annotated Java methods.
+ *
+ * <p>
+ * The parameter value is resolved using <c><jv>call</jv>.{@link RestCall#getRestRequest() getRestRequest}().{@link RestRequest#getHeaders() getHeaders}()</c>.
+ */
+public class RequestHeadersParam extends SimpleRestParam {
+
+	/**
+	 * Static creator.
+	 *
+	 * @param paramInfo The Java method parameter being resolved.
+	 * @return A new {@link RequestHeadersParam}, or <jk>null</jk> if the parameter type is not {@link RequestHeaders}.
+	 */
+	public static RequestHeadersParam create(ParamInfo paramInfo) {
+		if (paramInfo.isType(RequestHeaders.class))
+			return new RequestHeadersParam();
+		return null;
+	}
+
+	/**
+	 * Constructor.
+	 */
+	protected RequestHeadersParam() {
+		super((c)->c.getRestRequest().getHeaders());
+	}
+}
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/params/RequestPathParam.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/params/RequestPathParam.java
new file mode 100644
index 0000000..17b95f9
--- /dev/null
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/params/RequestPathParam.java
@@ -0,0 +1,45 @@
+// ***************************************************************************************************************************
+// * 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.params;
+
+import org.apache.juneau.reflect.*;
+import org.apache.juneau.rest.*;
+import org.apache.juneau.rest.annotation.*;
+
+/**
+ * Resolves method of type with {@link RequestPath} on {@link RestMethod}-annotated Java methods.
+ *
+ * <p>
+ * The parameter value is resolved using <c><jv>call</jv>.{@link RestCall#getRestRequest() getRestRequest}().{@link RestRequest#getPathMatch() getPathMatch}()</c>.
+ */
+public class RequestPathParam extends SimpleRestParam {
+
+	/**
+	 * Static creator.
+	 *
+	 * @param paramInfo The Java method parameter being resolved.
+	 * @return A new {@link RequestPathParam}, or <jk>null</jk> if the parameter type is not {@link RequestPath}.
+	 */
+	public static RequestPathParam create(ParamInfo paramInfo) {
+		if (paramInfo.isType(RequestPath.class))
+			return new RequestPathParam();
+		return null;
+	}
+
+	/**
+	 * Constructor.
+	 */
+	protected RequestPathParam() {
+		super((c)->c.getRestRequest().getPathMatch());
+	}
+}
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/params/RequestQueryParam.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/params/RequestQueryParam.java
new file mode 100644
index 0000000..68d949c
--- /dev/null
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/params/RequestQueryParam.java
@@ -0,0 +1,45 @@
+// ***************************************************************************************************************************
+// * 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.params;
+
+import org.apache.juneau.reflect.*;
+import org.apache.juneau.rest.*;
+import org.apache.juneau.rest.annotation.*;
+
+/**
+ * Resolves method parameters of type {@link RequestQuery} on {@link RestMethod}-annotated Java methods.
+ *
+ * <p>
+ * The parameter value is resolved using <c><jv>call</jv>.{@link RestCall#getRestRequest() getRestRequest}().{@link RestRequest#getQuery() getQuery}()</c>.
+ */
+public class RequestQueryParam extends SimpleRestParam {
+
+	/**
+	 * Static creator.
+	 *
+	 * @param paramInfo The Java method parameter being resolved.
+	 * @return A new {@link RequestQueryParam}, or <jk>null</jk> if the parameter type is not {@link RequestQuery}.
+	 */
+	public static RequestQueryParam create(ParamInfo paramInfo) {
+		if (paramInfo.isType(RequestQuery.class))
+			return new RequestQueryParam();
+		return null;
+	}
+
+	/**
+	 * Constructor.
+	 */
+	protected RequestQueryParam() {
+		super((c)->c.getRestRequest().getQuery());
+	}
+}
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/params/ResourceBundleParam.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/params/ResourceBundleParam.java
new file mode 100644
index 0000000..5ddd42b
--- /dev/null
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/params/ResourceBundleParam.java
@@ -0,0 +1,47 @@
+// ***************************************************************************************************************************
+// * 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.params;
+
+import java.util.*;
+
+import org.apache.juneau.reflect.*;
+import org.apache.juneau.rest.*;
+import org.apache.juneau.rest.annotation.*;
+
+/**
+ * Resolves method parameters of type {@link ResourceBundle} on {@link RestMethod}-annotated Java methods.
+ *
+ * <p>
+ * The parameter value is resolved using <c><jv>call</jv>.{@link RestCall#getRestRequest() getRestRequest}().{@link RestRequest#getMessages() getMessages}()</c>.
+ */
+public class ResourceBundleParam extends SimpleRestParam {
+
+	/**
+	 * Static creator.
+	 *
+	 * @param paramInfo The Java method parameter being resolved.
+	 * @return A new {@link ResourceBundleParam}, or <jk>null</jk> if the parameter type is not {@link ResourceBundle}.
+	 */
+	public static ResourceBundleParam create(ParamInfo paramInfo) {
+		if (paramInfo.isType(ResourceBundle.class))
+			return new ResourceBundleParam();
+		return null;
+	}
+
+	/**
+	 * Constructor.
+	 */
+	protected ResourceBundleParam() {
+		super((c)->c.getRestRequest().getMessages());
+	}
+}
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/params/ResponseBeanParam.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/params/ResponseBeanParam.java
new file mode 100644
index 0000000..e05ca32
--- /dev/null
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/params/ResponseBeanParam.java
@@ -0,0 +1,80 @@
+// ***************************************************************************************************************************
+// * 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.params;
+
+import java.lang.reflect.*;
+
+import org.apache.juneau.*;
+import org.apache.juneau.http.annotation.*;
+import org.apache.juneau.httppart.bean.*;
+import org.apache.juneau.reflect.*;
+import org.apache.juneau.rest.*;
+import org.apache.juneau.rest.annotation.*;
+
+/**
+ * Resolves method parameters and parameter types annotated with {@link Response} on {@link RestMethod}-annotated Java methods.
+ *
+ * <p>
+ * The parameter value must be of type {@link Value} that accepts a value that is then set via
+ * <c><jv>call</jv>.{@link RestCall#getRestResponse() getRestResponse}().{@link RestResponse#setOutput(Object) setOutput}(<jv>value</jv>)</c>.
+ */
+public class ResponseBeanParam implements RestParam {
+	final ResponseBeanMeta meta;
+	private final Type type;
+
+	/**
+	 * Static creator.
+	 *
+	 * @param paramInfo The Java method parameter being resolved.
+	 * @param ps The configuration properties of the {@link RestContext}.
+	 * @return A new {@link ResponseBeanParam}, or <jk>null</jk> if the parameter is not annotated with {@link Response}.
+	 */
+	public static ResponseBeanParam create(ParamInfo paramInfo, PropertyStore ps) {
+		if (paramInfo.hasAnnotation(Response.class) || paramInfo.getParameterType().hasAnnotation(Response.class))
+			return new ResponseBeanParam(paramInfo, ps);
+		return null;
+	}
+
+	/**
+	 * Constructor.
+	 *
+	 * @param paramInfo The Java method parameter being resolved.
+	 * @param ps The configuration properties of the {@link RestContext}.
+	 */
+	protected ResponseBeanParam(ParamInfo paramInfo, PropertyStore ps) {
+		this.type = paramInfo.getParameterType().innerType();
+		this.meta = ResponseBeanMeta.create(paramInfo, ps);
+		Class<?> c = type instanceof Class ? (Class<?>)type : type instanceof ParameterizedType ? (Class<?>)((ParameterizedType)type).getRawType() : null;
+		if (c != Value.class)
+			throw new ParameterException(paramInfo, "Type must be Value<?> on parameter annotated with @Response annotation");
+	}
+
+	@SuppressWarnings({ "unchecked", "rawtypes" })
+	@Override /* RestMethodParam */
+	public Object resolve(final RestCall call) throws Exception {
+		Value<Object> v = new Value();
+		v.listener(new ValueListener() {
+			@Override
+			public void onSet(Object o) {
+				RestRequest req = call.getRestRequest();
+				RestResponse res = call.getRestResponse();
+				ResponseBeanMeta meta = req.getResponseBeanMeta(o);
+				if (meta == null)
+					meta = ResponseBeanParam.this.meta;
+				res.setResponseMeta(meta);
+				res.setOutput(o);
+			}
+		});
+		return v;
+	}
+}
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/params/ResponseHeaderParam.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/params/ResponseHeaderParam.java
new file mode 100644
index 0000000..95d11bd
--- /dev/null
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/params/ResponseHeaderParam.java
@@ -0,0 +1,103 @@
+// ***************************************************************************************************************************
+// * 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.params;
+
+import static org.apache.juneau.internal.ClassUtils.*;
+import static org.apache.juneau.internal.StringUtils.*;
+
+import java.lang.reflect.*;
+
+import org.apache.juneau.*;
+import org.apache.juneau.http.annotation.*;
+import org.apache.juneau.httppart.*;
+import org.apache.juneau.reflect.*;
+import org.apache.juneau.rest.*;
+import org.apache.juneau.rest.annotation.*;
+import org.apache.juneau.serializer.*;
+
+/**
+ * Resolves method parameters annotated with {@link ResponseHeader} on {@link RestMethod}-annotated Java methods.
+ *
+ * <p>
+ * The parameter value must be of type {@link Value} that accepts a value that is then set via
+ * <c><jv>call</jv>.{@link RestCall#getRestResponse() getRestResponse}().{@link RestResponse#setHeader(String,String) setOutput}(<jv>name</jv>,<jv>value</jv>)</c>.
+ */
+public class ResponseHeaderParam implements RestParam {
+	final ResponsePartMeta meta;
+	final String name;
+	private final Type type;
+
+	/**
+	 * Static creator.
+	 *
+	 * @param paramInfo The Java method parameter being resolved.
+	 * @param ps The configuration properties of the {@link RestContext}.
+	 * @return A new {@link ResponseHeaderParam}, or <jk>null</jk> if the parameter is not annotated with {@link ResponseHeader}.
+	 */
+	public static ResponseHeaderParam create(ParamInfo paramInfo, PropertyStore ps) {
+		if (paramInfo.hasAnnotation(ResponseHeader.class) || paramInfo.getParameterType().hasAnnotation(ResponseHeader.class))
+			return new ResponseHeaderParam(paramInfo, ps);
+		return null;
+	}
+
+	/**
+	 * Constructor.
+	 *
+	 * @param paramInfo The Java method parameter being resolved.
+	 * @param ps The configuration properties of the {@link RestContext}.
+	 */
+	protected ResponseHeaderParam(ParamInfo paramInfo, PropertyStore ps) {
+		this.name = getName(paramInfo);
+		this.type = paramInfo.getParameterType().innerType();
+		HttpPartSchema schema = HttpPartSchema.create(ResponseHeader.class, paramInfo);
+		this.meta = new ResponsePartMeta(HttpPartType.HEADER, schema, castOrCreate(HttpPartSerializer.class, schema.getSerializer(), true, ps));
+
+		Class<?> c = type instanceof Class ? (Class<?>)type : type instanceof ParameterizedType ? (Class<?>)((ParameterizedType)type).getRawType() : null;
+		if (c != Value.class)
+			throw new ParameterException(paramInfo, "Type must be Value<?> on parameter annotated with @ResponseHeader annotation");
+	}
+
+	private static String getName(ParamInfo paramInfo) {
+		String n = null;
+		for (ResponseHeader h : paramInfo.getAnnotations(ResponseHeader.class))
+			n = firstNonEmpty(h.name(), h.n(), h.value(), n);
+		for (ResponseHeader h : paramInfo.getParameterType().getAnnotations(ResponseHeader.class))
+			n = firstNonEmpty(h.name(), h.n(), h.value(), n);
+		if (n == null)
+			throw new ParameterException(paramInfo, "@ResponseHeader used without name or value");
+		return n;
+	}
+
+	@SuppressWarnings({ "unchecked", "rawtypes" })
+	@Override /* RestMethodParam */
+	public Object resolve(final RestCall call) throws Exception {
+		Value<Object> v = new Value();
+		v.listener(new ValueListener() {
+			@Override
+			public void onSet(Object o) {
+				try {
+					RestRequest req = call.getRestRequest();
+					RestResponse res = call.getRestResponse();
+					ResponsePartMeta rpm = req.getResponseHeaderMeta(o);
+					if (rpm == null)
+						rpm = ResponseHeaderParam.this.meta;
+					HttpPartSerializerSession pss = rpm.getSerializer() == null ? req.getPartSerializer() : rpm.getSerializer().createPartSession(req.getSerializerSessionArgs());
+					res.setHeader(new HttpPart(name, HttpPartType.HEADER, rpm.getSchema(), pss, o));
+				} catch (SerializeException | SchemaValidationException e) {
+					throw new RuntimeException(e);
+				}
+			}
+		});
+		return v;
+	}
+}
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/params/ResponseStatusParam.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/params/ResponseStatusParam.java
new file mode 100644
index 0000000..59d8a10
--- /dev/null
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/params/ResponseStatusParam.java
@@ -0,0 +1,66 @@
+// ***************************************************************************************************************************
+// * 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.params;
+
+import java.lang.reflect.*;
+
+import org.apache.juneau.*;
+import org.apache.juneau.http.annotation.*;
+import org.apache.juneau.reflect.*;
+import org.apache.juneau.rest.*;
+import org.apache.juneau.rest.annotation.*;
+
+/**
+ * Resolves method parameters annotated with {@link ResponseStatus} on {@link RestMethod}-annotated Java methods.
+ */
+public class ResponseStatusParam implements RestParam {
+
+	private final Type type;
+
+	/**
+	 * Static creator.
+	 *
+	 * @param paramInfo The Java method parameter being resolved.
+	 * @return A new {@link ResponseStatusParam}, or <jk>null</jk> if the parameter is not annotated with {@link ResponseStatus}.
+	 */
+	public static ResponseStatusParam create(ParamInfo paramInfo) {
+		if (paramInfo.hasAnnotation(ResponseStatus.class) || paramInfo.getParameterType().hasAnnotation(ResponseStatus.class))
+			return new ResponseStatusParam(paramInfo);
+		return null;
+	}
+
+	/**
+	 * Constructor.
+	 *
+	 * @param paramInfo The Java method parameter being resolved.
+	 */
+	protected ResponseStatusParam(ParamInfo paramInfo) {
+		this.type = paramInfo.getParameterType().innerType();
+		Class<?> c = type instanceof Class ? (Class<?>)type : type instanceof ParameterizedType ? (Class<?>)((ParameterizedType)type).getRawType() : null;
+		if (c != Value.class || Value.getParameterType(type) != Integer.class)
+			throw new ParameterException(paramInfo, "Type must be Value<Integer> on parameter annotated with @ResponseStatus annotation");
+	}
+
+	@SuppressWarnings({ "unchecked", "rawtypes" })
+	@Override /* RestMethodParam */
+	public Object resolve(final RestCall call) throws Exception {
+		Value<Object> v = new Value();
+		v.listener(new ValueListener() {
+			@Override
+			public void onSet(Object o) {
+				call.getRestResponse().setStatus(Integer.parseInt(o.toString()));
+			}
+		});
+		return v;
+	}
+}
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/params/RestContextParam.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/params/RestContextParam.java
new file mode 100644
index 0000000..5829883
--- /dev/null
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/params/RestContextParam.java
@@ -0,0 +1,45 @@
+// ***************************************************************************************************************************
+// * 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.params;
+
+import org.apache.juneau.reflect.*;
+import org.apache.juneau.rest.*;
+import org.apache.juneau.rest.annotation.*;
+
+/**
+ * Resolves method parameters of type {@link RestContext} on {@link RestMethod}-annotated Java methods.
+ *
+ * <p>
+ * The parameter value is resolved using <c><jv>call</jv>.{@link RestCall#getContext() getContext}()</c>.
+ */
+public class RestContextParam extends SimpleRestParam {
+
+	/**
+	 * Static creator.
+	 *
+	 * @param paramInfo The Java method parameter being resolved.
+	 * @return A new {@link RestContextParam}, or <jk>null</jk> if the parameter type is not {@link RestContext}.
+	 */
+	public static RestContextParam create(ParamInfo paramInfo) {
+		if (paramInfo.isType(RestContext.class))
+			return new RestContextParam();
+		return null;
+	}
+
+	/**
+	 * Constructor.
+	 */
+	protected RestContextParam() {
+		super((c)->c.getContext());
+	}
+}
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/params/RestRequestParam.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/params/RestRequestParam.java
new file mode 100644
index 0000000..3b5752c
--- /dev/null
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/params/RestRequestParam.java
@@ -0,0 +1,45 @@
+// ***************************************************************************************************************************
+// * 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.params;
+
+import org.apache.juneau.reflect.*;
+import org.apache.juneau.rest.*;
+import org.apache.juneau.rest.annotation.*;
+
+/**
+ * Resolves method parameters of type {@link RestRequest} on {@link RestMethod}-annotated Java methods.
+ *
+ * <p>
+ * The parameter value is resolved using <c><jv>call</jv>.{@link RestCall#getRestRequest() getRestRequest}()</c>.
+ */
+public class RestRequestParam extends SimpleRestParam {
+
+	/**
+	 * Static creator.
+	 *
+	 * @param paramInfo The Java method parameter being resolved.
+	 * @return A new {@link RestRequestParam}, or <jk>null</jk> if the parameter type is not {@link RestRequest}.
+	 */
+	public static RestRequestParam create(ParamInfo paramInfo) {
+		if (paramInfo.isType(RestRequest.class))
+			return new RestRequestParam();
+		return null;
+	}
+
+	/**
+	 * Constructor.
+	 */
+	protected RestRequestParam() {
+		super((c)->c.getRestRequest());
+	}
+}
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/params/ServetInputStreamParam.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/params/ServetInputStreamParam.java
new file mode 100644
index 0000000..cadcad6
--- /dev/null
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/params/ServetInputStreamParam.java
@@ -0,0 +1,47 @@
+// ***************************************************************************************************************************
+// * 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.params;
+
+import javax.servlet.*;
+
+import org.apache.juneau.reflect.*;
+import org.apache.juneau.rest.*;
+import org.apache.juneau.rest.annotation.*;
+
+/**
+ * Resolves method parameters of type {@link ServletInputStream} on {@link RestMethod}-annotated Java methods.
+ *
+ * <p>
+ * The parameter value is resolved using <c><jv>call</jv>.{@link RestCall#getRestRequest() getRestRequest}().{@link RestRequest#getInputStream() getInputStream}()</c>.
+ */
+public class ServetInputStreamParam extends SimpleRestParam {
+
+	/**
+	 * Static creator.
+	 *
+	 * @param paramInfo The Java method parameter being resolved.
+	 * @return A new {@link ServetInputStreamParam}, or <jk>null</jk> if the parameter type is not {@link ServletInputStream}.
+	 */
+	public static ServetInputStreamParam create(ParamInfo paramInfo) {
+		if (paramInfo.isType(ServletInputStream.class))
+			return new ServetInputStreamParam();
+		return null;
+	}
+
+	/**
+	 * Constructor.
+	 */
+	protected ServetInputStreamParam() {
+		super((c)->c.getRestRequest().getInputStream());
+	}
+}
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/params/ServletOutputStreamParam.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/params/ServletOutputStreamParam.java
new file mode 100644
index 0000000..677a1b7
--- /dev/null
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/params/ServletOutputStreamParam.java
@@ -0,0 +1,47 @@
+// ***************************************************************************************************************************
+// * 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.params;
+
+import javax.servlet.*;
+
+import org.apache.juneau.reflect.*;
+import org.apache.juneau.rest.*;
+import org.apache.juneau.rest.annotation.*;
+
+/**
+ * Resolves method parameters of type {@link ServletOutputStream} on {@link RestMethod}-annotated Java methods.
+ *
+ * <p>
+ * The parameter value is resolved using <c><jv>call</jv>.{@link RestCall#getRestResponse() getRestResponse}().{@link RestResponse#getOutputStream() getOutputStream}()</c>.
+ */
+public class ServletOutputStreamParam extends SimpleRestParam {
+
+	/**
+	 * Static creator.
+	 *
+	 * @param paramInfo The Java method parameter being resolved.
+	 * @return A new {@link ServletOutputStreamParam}, or <jk>null</jk> if the parameter type is not {@link ServletOutputStream}.
+	 */
+	public static ServletOutputStreamParam create(ParamInfo paramInfo) {
+		if (paramInfo.isType(ServletOutputStream.class))
+			return new ServletOutputStreamParam();
+		return null;
+	}
+
+	/**
+	 * Constructor.
+	 */
+	protected ServletOutputStreamParam() {
+		super((c)->c.getRestResponse().getOutputStream());
+	}
+}
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/params/SimpleRestParam.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/params/SimpleRestParam.java
new file mode 100644
index 0000000..4cdac27
--- /dev/null
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/params/SimpleRestParam.java
@@ -0,0 +1,41 @@
+// ***************************************************************************************************************************
+// * 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.params;
+
+import java.util.function.*;
+
+import org.apache.juneau.rest.*;
+import org.apache.juneau.utils.*;
+
+/**
+ * An implementation of a {@link RestParam} that takes in a {@link ThrowingFunction} for resolving a parameter value.
+ */
+public class SimpleRestParam implements RestParam {
+
+	private final Function<RestCall,Object> function;
+
+	/**
+	 * Constructor.
+	 *
+	 * @param function The function to use to retrieve the parameter value from the {@link RestCall}.
+	 */
+	@SuppressWarnings("unchecked")
+	protected <T> SimpleRestParam(ThrowingFunction<RestCall,T> function) {
+		this.function = (Function<RestCall,Object>)function;
+	}
+
+	@Override /* RestMethodParam */
+	public Object resolve(RestCall call) throws Exception {
+		return function.apply(call);
+	}
+}
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/params/SwaggerParam.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/params/SwaggerParam.java
new file mode 100644
index 0000000..f263cd4
--- /dev/null
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/params/SwaggerParam.java
@@ -0,0 +1,46 @@
+// ***************************************************************************************************************************
+// * 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.params;
+
+import org.apache.juneau.dto.swagger.*;
+import org.apache.juneau.reflect.*;
+import org.apache.juneau.rest.*;
+import org.apache.juneau.rest.annotation.*;
+
+/**
+ * Resolves method parameters of type {@link Swagger} on {@link RestMethod}-annotated Java methods.
+ *
+ * <p>
+ * The parameter value is resolved using <c><jv>call</jv>.{@link RestCall#getRestRequest() getRestRequest}().{@link RestRequest#getSwagger() getSwagger}()</c>.
+ */
+public class SwaggerParam extends SimpleRestParam {
+
+	/**
+	 * Static creator.
+	 *
+	 * @param paramInfo The Java method parameter being resolved.
+	 * @return A new {@link SwaggerParam}, or <jk>null</jk> if the parameter type is not {@link Swagger}.
+	 */
+	public static SwaggerParam create(ParamInfo paramInfo) {
+		if (paramInfo.isType(Swagger.class))
+			return new SwaggerParam();
+		return null;
+	}
+
+	/**
+	 * Constructor.
+	 */
+	protected SwaggerParam() {
+		super((c)->c.getRestRequest().getSwagger());
+	}
+}
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/params/TimeZoneParam.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/params/TimeZoneParam.java
new file mode 100644
index 0000000..1924f16
--- /dev/null
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/params/TimeZoneParam.java
@@ -0,0 +1,47 @@
+// ***************************************************************************************************************************
+// * 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.params;
+
+import java.util.*;
+
+import org.apache.juneau.reflect.*;
+import org.apache.juneau.rest.*;
+import org.apache.juneau.rest.annotation.*;
+
+/**
+ * Resolves method parameters of type {@link TimeZone} on {@link RestMethod}-annotated Java methods.
+ *
+ * <p>
+ * The parameter value is resolved using <c><jv>call</jv>.{@link RestCall#getRestRequest() getRestRequest}().{@link RestRequest#getHeaders() getHeaders}().{@link RequestHeaders#getTimeZone() getTimeZone}()</c>.
+ */
+public class TimeZoneParam extends SimpleRestParam {
+
+	/**
+	 * Static creator.
+	 *
+	 * @param paramInfo The Java method parameter being resolved.
+	 * @return A new {@link TimeZoneParam}, or <jk>null</jk> if the parameter type is not {@link TimeZone}.
+	 */
+	public static TimeZoneParam create(ParamInfo paramInfo) {
+		if (paramInfo.isType(TimeZone.class))
+			return new TimeZoneParam();
+		return null;
+	}
+
+	/**
+	 * Constructor.
+	 */
+	protected TimeZoneParam() {
+		super((c)->c.getRestRequest().getHeaders().getTimeZone());
+	}
+}
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/params/UriContextParam.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/params/UriContextParam.java
new file mode 100644
index 0000000..d1215f7
--- /dev/null
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/params/UriContextParam.java
@@ -0,0 +1,46 @@
+// ***************************************************************************************************************************
+// * 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.params;
+
+import org.apache.juneau.*;
+import org.apache.juneau.reflect.*;
+import org.apache.juneau.rest.*;
+import org.apache.juneau.rest.annotation.*;
+
+/**
+ * Resolves method parameters of type {@link UriContext} on {@link RestMethod}-annotated Java methods.
+ *
+ * <p>
+ * The parameter value is resolved using <c><jv>call</jv>.{@link RestCall#getRestRequest() getRestRequest}().{@link RestRequest#getUriContext() getUriContext}()</c>.
+ */
+public class UriContextParam extends SimpleRestParam {
+
+	/**
+	 * Static creator.
+	 *
+	 * @param paramInfo The Java method parameter being resolved.
+	 * @return A new {@link UriContextParam}, or <jk>null</jk> if the parameter type is not {@link UriContext}.
+	 */
+	public static UriContextParam create(ParamInfo paramInfo) {
+		if (paramInfo.isType(UriContext.class))
+			return new UriContextParam();
+		return null;
+	}
+
+	/**
+	 * Constructor.
+	 */
+	protected UriContextParam() {
+		super((c)->c.getRestRequest().getUriContext());
+	}
+}
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/params/UriResolverParam.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/params/UriResolverParam.java
new file mode 100644
index 0000000..1ea4b1e
--- /dev/null
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/params/UriResolverParam.java
@@ -0,0 +1,46 @@
+// ***************************************************************************************************************************
+// * 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.params;
+
+import org.apache.juneau.*;
+import org.apache.juneau.reflect.*;
+import org.apache.juneau.rest.*;
+import org.apache.juneau.rest.annotation.*;
+
+/**
+ * Resolves method parameters of type {@link UriResolver} on {@link RestMethod}-annotated Java methods.
+ *
+ * <p>
+ * The parameter value is resolved using <c><jv>call</jv>.{@link RestCall#getRestRequest() getRestRequest}().{@link RestRequest#getUriResolver() getUriResolver}()</c>.
+ */
+public class UriResolverParam extends SimpleRestParam {
+
+	/**
+	 * Static creator.
+	 *
+	 * @param paramInfo The Java method parameter being resolved.
+	 * @return A new {@link UriResolverParam}, or <jk>null</jk> if the parameter type is not {@link UriResolver}.
+	 */
+	public static UriResolverParam create(ParamInfo paramInfo) {
+		if (paramInfo.isType(UriResolver.class))
+			return new UriResolverParam();
+		return null;
+	}
+
+	/**
+	 * Constructor.
+	 */
+	protected UriResolverParam() {
+		super((c)->c.getRestRequest().getUriResolver());
+	}
+}
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/params/WriterParam.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/params/WriterParam.java
new file mode 100644
index 0000000..37d95cf
--- /dev/null
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/params/WriterParam.java
@@ -0,0 +1,47 @@
+// ***************************************************************************************************************************
+// * 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.params;
+
+import java.io.*;
+
+import org.apache.juneau.reflect.*;
+import org.apache.juneau.rest.*;
+import org.apache.juneau.rest.annotation.*;
+
+/**
+ * Resolves method parameters of type {@link Writer} on {@link RestMethod}-annotated Java methods.
+ *
+ * <p>
+ * The parameter value is resolved using <c><jv>call</jv>.{@link RestCall#getRestResponse() getRestResponse}().{@link RestResponse#getWriter() getWriter}()</c>.
+ */
+public class WriterParam extends SimpleRestParam {
+
+	/**
+	 * Static creator.
+	 *
+	 * @param paramInfo The Java method parameter being resolved.
+	 * @return A new {@link WriterParam}, or <jk>null</jk> if the parameter type is not {@link Writer}.
+	 */
+	public static WriterParam create(ParamInfo paramInfo) {
+		if (paramInfo.isType(Writer.class))
+			return new WriterParam();
+		return null;
+	}
+
+	/**
+	 * Constructor.
+	 */
+	protected WriterParam() {
+		super((c)->c.getRestResponse().getWriter());
+	}
+}