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

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


The following commit(s) were added to refs/heads/master by this push:
     new 602d6f2  RestRequest API cleanup.
602d6f2 is described below

commit 602d6f2a39700e1e7c70b577871358da0af91353
Author: JamesBognar <[email protected]>
AuthorDate: Sun Nov 7 11:53:11 2021 -0500

    RestRequest API cleanup.
---
 .../src/main/java/org/apache/juneau/ClassMeta.java |  41 +-
 .../java/org/apache/juneau/http/HttpParts.java     | 101 ++++
 .../java/org/apache/juneau/http/header/Accept.java |   3 +-
 .../org/apache/juneau/http/header/ContentType.java |   3 +-
 .../java/org/apache/juneau/rest/RequestBody.java   |   8 +-
 .../org/apache/juneau/rest/RequestFormParam.java   |  25 -
 .../org/apache/juneau/rest/RequestFormParams.java  |  23 +-
 .../java/org/apache/juneau/rest/RequestHeader.java |  27 -
 .../org/apache/juneau/rest/RequestHeaders.java     |  21 +
 .../org/apache/juneau/rest/RequestHttpPart.java    |  36 ++
 .../org/apache/juneau/rest/RequestPathParam.java   |  26 -
 .../org/apache/juneau/rest/RequestPathParams.java  |  21 +
 .../org/apache/juneau/rest/RequestQueryParam.java  |  26 -
 .../org/apache/juneau/rest/RequestQueryParams.java |  21 +
 .../java/org/apache/juneau/rest/RestRequest.java   | 560 ++++-----------------
 .../annotation/Rest_AllowedHeaderParams_Test.java  |   4 +-
 16 files changed, 358 insertions(+), 588 deletions(-)

diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/ClassMeta.java 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/ClassMeta.java
index 1199bad..a760fdc 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/ClassMeta.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/ClassMeta.java
@@ -29,6 +29,7 @@ import java.util.*;
 import java.util.Date;
 import java.util.concurrent.*;
 import java.util.concurrent.locks.*;
+import java.util.function.*;
 
 import org.apache.juneau.annotation.*;
 import org.apache.juneau.collections.*;
@@ -113,6 +114,9 @@ public final class ClassMeta<T> implements Type {
        private final Map<Class<?>,Mutater<?,T>> fromMutaters = new 
ConcurrentHashMap<>();
        private final Map<Class<?>,Mutater<T,?>> toMutaters = new 
ConcurrentHashMap<>();
        private final Mutater<String,T> stringMutater;
+       private final Map<Class<?>,List<?>> annotationListMap = new 
ConcurrentHashMap<>();
+       private final Map<Class<?>,Optional<?>> annotationLastMap = new 
ConcurrentHashMap<>();
+       private final Map<String,Optional<?>> properties = new 
ConcurrentHashMap<>();
 
        private final ReadWriteLock lock = new ReentrantReadWriteLock(false);
        private final Lock rLock = lock.readLock(), wLock = lock.writeLock();
@@ -2076,8 +2080,16 @@ public final class ClassMeta<T> implements Type {
         * @param a The annotation to retrieve.
         * @return The specified annotation, or <jk>null</jk> if the class does 
not have the specified annotation.
         */
+       @SuppressWarnings("unchecked")
        public <A extends Annotation> A getLastAnnotation(Class<A> a) {
-               return info.getLastAnnotation(a, beanContext == null ? 
BeanContext.DEFAULT : beanContext);
+               Optional<A> o = (Optional<A>)annotationLastMap.get(a);
+               if (o == null) {
+                       if (beanContext == null)
+                               return info.getLastAnnotation(a, 
BeanContext.DEFAULT);
+                       o = Optional.ofNullable(info.getLastAnnotation(a, 
beanContext));
+                       annotationLastMap.put(a, o);
+               }
+               return o.orElse(null);
        }
 
        /**
@@ -2088,8 +2100,33 @@ public final class ClassMeta<T> implements Type {
         * @return
         *      A list of all matching annotations found or an empty list if 
none found.
         */
+       @SuppressWarnings("unchecked")
        public <A extends Annotation> List<A> getAnnotations(Class<A> a) {
-               return info.getAnnotations(a, beanContext == null ? 
BeanContext.DEFAULT : beanContext);
+               List<A> l = (List<A>)annotationListMap.get(a);
+               if (l == null) {
+                       if (beanContext == null)
+                               return info.getAnnotations(a, 
BeanContext.DEFAULT);
+                       l = Collections.unmodifiableList(info.getAnnotations(a, 
beanContext));
+                       annotationListMap.put(a, l);
+               }
+               return l;
+       }
+
+       /**
+        * Returns a calculated property on this context.
+        *
+        * @param name The name of the property.
+        * @param function The function used to create this property.
+        * @return The property value.  Never <jk>null</jk>.
+        */
+       @SuppressWarnings("unchecked")
+       public <T2> Optional<T2> getProperty(String name, 
Function<ClassMeta<?>,T2> function) {
+               Optional<T2> t = (Optional<T2>) properties.get(name);
+               if (t == null) {
+                       t = Optional.ofNullable(function.apply(this));
+                       properties.put(name, t);
+               }
+               return t;
        }
 
        @Override /* Object */
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/HttpParts.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/HttpParts.java
index 95238f0..5e1e261 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/HttpParts.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/HttpParts.java
@@ -20,8 +20,10 @@ import java.util.*;
 import java.util.function.*;
 
 import org.apache.http.*;
+import org.apache.juneau.*;
 import org.apache.juneau.http.header.*;
 import org.apache.juneau.http.part.*;
+import org.apache.juneau.httppart.*;
 import org.apache.juneau.reflect.*;
 
 /**
@@ -411,6 +413,105 @@ public class HttpParts {
        // Utility methods
        
//-----------------------------------------------------------------------------------------------------------------
 
+       private static final Function<ClassMeta<?>,String> HEADER_NAME_FUNCTION 
= x -> {
+               for (org.apache.juneau.http.annotation.Header a : 
x.getAnnotations(org.apache.juneau.http.annotation.Header.class)) {
+                       if (! a.value().isEmpty())
+                               return a.value();
+                       if (! a.n().isEmpty())
+                               return a.n();
+                       if (! a.name().isEmpty())
+                               return a.name();
+               }
+               return null;
+       };
+
+       private static final Function<ClassMeta<?>,String> QUERY_NAME_FUNCTION 
= x -> {
+               for (org.apache.juneau.http.annotation.Query a : 
x.getAnnotations(org.apache.juneau.http.annotation.Query.class)) {
+                       if (! a.value().isEmpty())
+                               return a.value();
+                       if (! a.n().isEmpty())
+                               return a.n();
+                       if (! a.name().isEmpty())
+                               return a.name();
+               }
+               return null;
+       };
+
+       private static final Function<ClassMeta<?>,String> 
FORMDATA_NAME_FUNCTION = x -> {
+               for (org.apache.juneau.http.annotation.FormData a : 
x.getAnnotations(org.apache.juneau.http.annotation.FormData.class)) {
+                       if (! a.value().isEmpty())
+                               return a.value();
+                       if (! a.n().isEmpty())
+                               return a.n();
+                       if (! a.name().isEmpty())
+                               return a.name();
+               }
+               return null;
+       };
+
+       private static final Function<ClassMeta<?>,String> PATH_NAME_FUNCTION = 
x -> {
+               for (org.apache.juneau.http.annotation.Path a : 
x.getAnnotations(org.apache.juneau.http.annotation.Path.class)) {
+                       if (! a.value().isEmpty())
+                               return a.value();
+                       if (! a.n().isEmpty())
+                               return a.n();
+                       if (! a.name().isEmpty())
+                               return a.name();
+               }
+               return null;
+       };
+
+       private static final Function<ClassMeta<?>,ConstructorInfo> 
CONSTRUCTOR_FUNCTION = x -> {
+               ClassInfo ci = x.getInfo();
+               ConstructorInfo cc = ci.getConstructor(Visibility.PUBLIC, 
String.class);
+               if (cc == null)
+                       cc = ci.getConstructor(Visibility.PUBLIC, String.class, 
String.class);
+               return cc;
+       };
+
+       /**
+        * Returns the name of the specified part type.
+        *
+        * <p>
+        * Gets the name from one of the following annotations:
+        * <ul class='javatreec'>
+        *      <li class='ja'>{@link org.apache.juneau.http.annotation.Header}
+        *      <li class='ja'>{@link org.apache.juneau.http.annotation.Query}
+        *      <li class='ja'>{@link 
org.apache.juneau.http.annotation.FormData}
+        *      <li class='ja'>{@link org.apache.juneau.http.annotation.Path}
+        * </ul>
+        *
+        * @param partType The part type.
+        * @param type The type to check.
+        * @return The part name.  Never <jk>null</jk>.
+        */
+       public static Optional<String> getName(HttpPartType partType, 
ClassMeta<?> type) {
+               switch(partType) {
+                       case FORMDATA: return 
type.getProperty("HttpPartName.FormData", FORMDATA_NAME_FUNCTION);
+                       case HEADER: return 
type.getProperty("HttpPartName.Header", HEADER_NAME_FUNCTION);
+                       case PATH: return type.getProperty("HttpPartName.Path", 
PATH_NAME_FUNCTION);
+                       case QUERY: return 
type.getProperty("HttpPartName.Query", QUERY_NAME_FUNCTION);
+                       default: return Optional.empty();
+               }
+       }
+
+       /**
+        * Returns the constructor for the specified type.
+        *
+        * <p>
+        * Looks for one of the following constructors:
+        * <ul class='javatree'>
+        *      <li class='jm><c><jk>public</jv> T(String <jv>value</jv>);</c>
+        *      <li class='jm><c><jk>public</jv> T(String <jv>name</jv>, String 
<jv>value</jv>);</c>
+        * </ul>
+        *
+        * @param type The header type to find the constructor on.
+        * @return The constructor.  Never <jk>null</jk>.
+        */
+       public static Optional<ConstructorInfo> getConstructor(ClassMeta<?> 
type) {
+               return type.getProperty("HttpPart.Constructor", 
CONSTRUCTOR_FUNCTION);
+       }
+
        /**
         * Utility method for converting an arbitrary object to a {@link 
NameValuePair}.
         *
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/Accept.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/Accept.java
index 7dee5b2..1e958bf 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/Accept.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/Accept.java
@@ -173,7 +173,8 @@ public class Accept extends BasicMediaRangeArrayHeader {
                TEXT_HTML = of("text/html"),
                TEXT_PLAIN = of("text/plain"),
                TEXT_XML = of("text/xml"),
-               WILDCARD = of("*/*");
+               WILDCARD = of("*/*"),
+               NULL = new Accept((String)null);
 
        /**
         * Static creator.
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/ContentType.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/ContentType.java
index c02b819..0fa704d 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/ContentType.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/ContentType.java
@@ -82,7 +82,8 @@ public class ContentType extends BasicMediaTypeHeader {
                TEXT_OPENAPI = of("text/openapi"),
                TEXT_PLAIN = of("text/plain"),
                TEXT_XML = of("text/xml"),
-               WILDCARD = of("*/*");
+               WILDCARD = of("*/*"),
+               NULL = new ContentType((String)null);
 
        /**
         * Static creator.
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 434c5d8..a9dffd2 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
@@ -363,10 +363,10 @@ public class RequestBody {
        private MediaType getMediaType() {
                if (mediaType != null)
                        return mediaType;
-               ContentType ct = req.getContentType();
+               Optional<ContentType> ct = req.getHeader(ContentType.class);
                if (!ct.isPresent() && body != null)
                        return MediaType.UON;
-               return ct.isNotEmpty() ? ct.asMediaType().orElse(null) : null;
+               return ct.isPresent() ? ct.get().asMediaType().orElse(null) : 
null;
        }
 
        /**
@@ -476,10 +476,10 @@ public class RequestBody {
                if ((isEmpty(mt) || mt.toString().startsWith("text/plain")) && 
cm.hasStringMutater())
                        return cm.getStringMutater().mutate(asString());
 
-               ContentType ct = req.getContentType();
+               Optional<ContentType> ct = req.getHeader(ContentType.class);
                throw new UnsupportedMediaType(
                        "Unsupported media-type in request header 
''Content-Type'': ''{0}''\n\tSupported media-types: {1}",
-                       ct.isPresent() ? ct.asMediaType().orElse(null) : 
"not-specified", json(req.getOpContext().getParsers().getSupportedMediaTypes())
+                       ct.isPresent() ? ct.get().asMediaType().orElse(null) : 
"not-specified", json(req.getOpContext().getParsers().getSupportedMediaTypes())
                );
        }
 
diff --git 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RequestFormParam.java
 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RequestFormParam.java
index a40f52d..2a0cbf4 100644
--- 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RequestFormParam.java
+++ 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RequestFormParam.java
@@ -13,7 +13,6 @@
 package org.apache.juneau.rest;
 
 import static org.apache.juneau.httppart.HttpPartType.*;
-import static org.apache.juneau.internal.ClassUtils.*;
 import static org.apache.juneau.internal.ThrowableUtils.*;
 
 import java.io.*;
@@ -21,12 +20,10 @@ import java.time.*;
 import java.util.*;
 
 import org.apache.http.*;
-import org.apache.juneau.*;
 import org.apache.juneau.assertions.*;
 import org.apache.juneau.http.part.*;
 import org.apache.juneau.httppart.*;
 import org.apache.juneau.internal.*;
-import org.apache.juneau.reflect.*;
 
 /**
  * Represents a single form-data parameter on an HTTP request.
@@ -121,28 +118,6 @@ public class RequestFormParam extends RequestHttpPart 
implements NameValuePair {
        }
 
        /**
-        * Returns the value of this parameter as a {@link BasicPart}.
-        *
-        * @param c The subclass of {@link BasicPart} to instantiate.
-        * @param <T> The subclass of {@link BasicPart} to instantiate.
-        * @return The value of this parameter as a string, never <jk>null</jk>.
-        */
-       public <T extends BasicPart> T asPart(Class<T> c) {
-               try {
-                       ClassInfo ci = ClassInfo.of(c);
-                       ConstructorInfo cc = 
ci.getConstructor(Visibility.PUBLIC, String.class);
-                       if (cc != null)
-                               return cc.invoke(orElse(null));
-                       cc = ci.getConstructor(Visibility.PUBLIC, String.class, 
String.class);
-                       if (cc != null)
-                               return cc.invoke(getName(), orElse(null));
-               } catch (Exception e) {
-                       throw runtimeException(e);
-               }
-               throw runtimeException("Could not determine a method to 
construct type {0}", className(c));
-       }
-
-       /**
         * Returns the value of this parameter as a {@link BasicCsvArrayPart}.
         *
         * @return The value of this parameter as a {@link BasicCsvArrayPart}, 
never <jk>null</jk>.
diff --git 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RequestFormParams.java
 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RequestFormParams.java
index 5b01ffc..e44c5c8 100644
--- 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RequestFormParams.java
+++ 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RequestFormParams.java
@@ -14,7 +14,10 @@ package org.apache.juneau.rest;
 
 import static java.util.Collections.*;
 import static org.apache.juneau.assertions.Assertions.*;
+import static org.apache.juneau.httppart.HttpPartType.*;
+import static org.apache.juneau.internal.ClassUtils.*;
 import static org.apache.juneau.internal.StringUtils.*;
+import static org.apache.juneau.internal.ThrowableUtils.*;
 
 import java.time.*;
 import java.util.*;
@@ -22,7 +25,10 @@ import java.util.*;
 import javax.servlet.http.*;
 
 import org.apache.http.*;
+import org.apache.juneau.*;
 import org.apache.juneau.collections.*;
+import org.apache.juneau.http.*;
+import org.apache.juneau.http.header.*;
 import org.apache.juneau.httppart.*;
 import org.apache.juneau.internal.*;
 import org.apache.juneau.rest.util.*;
@@ -51,7 +57,7 @@ public class RequestFormParams {
                Collection<Part> c = null;
 
                RequestBody body = req.getBody();
-               if (body.isLoaded() || ! 
req.getContentType().equalsIgnoreCase("multipart/form-data"))
+               if (body.isLoaded() || ! 
req.getHeader(ContentType.class).orElse(ContentType.NULL).equalsIgnoreCase("multipart/form-data"))
                        m = RestUtils.parseQuery(body.getReader());
                else {
                        c = req.getHttpServletRequest().getParts();
@@ -399,6 +405,21 @@ public class RequestFormParams {
        }
 
        /**
+        * Returns the form data parameter as the specified bean type.
+        *
+        * <p>
+        * Type must have a name specified via the {@link 
org.apache.juneau.http.annotation.FormData} annotation
+        * and a public constructor that takes in either <c>value</c> or 
<c>name,value</c> as strings.
+        *
+        * @param type The bean type to create.
+        * @return The bean, never <jk>null</jk>.
+        */
+       public <T> Optional<T> get(Class<T> type) {
+               ClassMeta<T> cm = req.getBeanSession().getClassMeta(type);
+               String name = HttpParts.getName(FORMDATA, 
cm).orElseThrow(()->runtimeException("@FormData(name) not found on class {0}", 
className(type)));
+               return get(name).asPart(type);
+       }
+       /**
         * Returns the last parameter with the specified name as a string.
         *
         * @param name The parameter name.
diff --git 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RequestHeader.java
 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RequestHeader.java
index 59f106d..56f1f20 100644
--- 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RequestHeader.java
+++ 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RequestHeader.java
@@ -13,18 +13,13 @@
 package org.apache.juneau.rest;
 
 import static org.apache.juneau.httppart.HttpPartType.*;
-import static org.apache.juneau.internal.ClassUtils.*;
-import static org.apache.juneau.internal.ThrowableUtils.*;
-
 import java.time.*;
 import java.util.*;
 
 import org.apache.http.*;
-import org.apache.juneau.*;
 import org.apache.juneau.http.header.*;
 import org.apache.juneau.http.response.BasicHttpException;
 import org.apache.juneau.httppart.*;
-import org.apache.juneau.reflect.*;
 import org.apache.juneau.rest.assertions.*;
 
 /**
@@ -100,28 +95,6 @@ public class RequestHeader extends RequestHttpPart 
implements Header {
        }
 
        /**
-        * Returns the value of this header as a {@link BasicHeader}.
-        *
-        * @param c The subclass of {@link BasicHeader} to instantiate.
-        * @param <T> The subclass of {@link BasicHeader} to instantiate.
-        * @return The value of this header as a string, never <jk>null</jk>.
-        */
-       public <T extends BasicHeader> T asHeader(Class<T> c) {
-               try {
-                       ClassInfo ci = ClassInfo.of(c);
-                       ConstructorInfo cc = 
ci.getConstructor(Visibility.PUBLIC, String.class);
-                       if (cc != null)
-                               return cc.invoke(orElse(null));
-                       cc = ci.getConstructor(Visibility.PUBLIC, String.class, 
String.class);
-                       if (cc != null)
-                               return cc.invoke(getName(), orElse(null));
-               } catch (Exception e) {
-                       throw runtimeException(e);
-               }
-               throw runtimeException("Could not determine a method to 
construct type {0}", className(c));
-       }
-
-       /**
         * Returns the value of this header as a {@link BasicCsvArrayHeader}.
         *
         * @return The value of this header as a  {@link BasicCsvArrayHeader}, 
never <jk>null</jk>.
diff --git 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RequestHeaders.java
 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RequestHeaders.java
index 36e7a46..6683106 100644
--- 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RequestHeaders.java
+++ 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RequestHeaders.java
@@ -12,10 +12,13 @@
 // 
***************************************************************************************************************************
 package org.apache.juneau.rest;
 
+import static org.apache.juneau.internal.ClassUtils.*;
 import static org.apache.juneau.internal.StringUtils.*;
+import static org.apache.juneau.internal.ThrowableUtils.*;
 import static java.util.Collections.*;
 import static java.util.stream.Collectors.*;
 import static org.apache.juneau.assertions.Assertions.*;
+import static org.apache.juneau.httppart.HttpPartType.*;
 
 import java.time.*;
 import java.util.*;
@@ -25,7 +28,9 @@ import org.apache.http.*;
 import org.apache.juneau.httppart.*;
 import org.apache.juneau.internal.*;
 import org.apache.juneau.svl.*;
+import org.apache.juneau.*;
 import org.apache.juneau.collections.*;
+import org.apache.juneau.http.*;
 
 /**
  * Represents the headers in an HTTP request.
@@ -398,6 +403,22 @@ public class RequestHeaders {
        }
 
        /**
+        * Returns the header as the specified bean type.
+        *
+        * <p>
+        * Type must have a name specified via the {@link 
org.apache.juneau.http.annotation.Header} annotation
+        * and a public constructor that takes in either <c>value</c> or 
<c>name,value</c> as strings.
+        *
+        * @param type The bean type to create.
+        * @return The bean, never <jk>null</jk>.
+        */
+       public <T> Optional<T> get(Class<T> type) {
+               ClassMeta<T> cm = req.getBeanSession().getClassMeta(type);
+               String name = HttpParts.getName(HEADER, 
cm).orElseThrow(()->runtimeException("@Header(name) not found on class {0}", 
className(type)));
+               return get(name).asPart(type);
+       }
+
+       /**
         * Returns the last header with the specified name as a string.
         *
         * @param name The header name.
diff --git 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RequestHttpPart.java
 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RequestHttpPart.java
index 7fd1abd..0d471ff 100644
--- 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RequestHttpPart.java
+++ 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RequestHttpPart.java
@@ -13,16 +13,21 @@
 package org.apache.juneau.rest;
 
 import static org.apache.juneau.httppart.HttpPartType.*;
+import static org.apache.juneau.internal.ClassUtils.*;
+import static org.apache.juneau.internal.ThrowableUtils.*;
+
 import java.lang.reflect.*;
 import java.util.*;
 import java.util.regex.*;
 
 import org.apache.juneau.*;
+import org.apache.juneau.http.*;
 import org.apache.juneau.http.response.*;
 import org.apache.juneau.httppart.*;
 import org.apache.juneau.internal.*;
 import org.apache.juneau.oapi.*;
 import org.apache.juneau.parser.ParseException;
+import org.apache.juneau.reflect.*;
 
 /**
  * Represents a single HTTP part on an HTTP request.
@@ -129,6 +134,28 @@ public abstract class RequestHttpPart {
        }
 
        /**
+        * Returns the value of this part as the specified type.
+        *
+        * <p>
+        * Looks for one of the following constructors:
+        * <ul class='javatree'>
+        *      <li class='jm><c><jk>public</jv> T(String <jv>value</jv>);</c>
+        *      <li class='jm><c><jk>public</jv> T(String <jv>name</jv>, String 
<jv>value</jv>);</c>
+        * </ul>
+        *
+        * @param c The part type.
+        * @return The value of this part as the specified type, never 
<jk>null</jk>.
+        */
+       public <T> Optional<T> asPart(Class<T> c) {
+               if (! isPresent())
+                       return Optional.empty();
+               ConstructorInfo cc = 
HttpParts.getConstructor(getRequest().getBeanSession().getClassMeta(c)).orElseThrow(()->runtimeException("Could
 not determine a method to construct type {0}", className(c)));
+               if (cc.getParamCount() == 1)
+                       return Optional.of(cc.invoke(get()));
+               return Optional.of(cc.invoke(getName(), get()));
+       }
+
+       /**
         * Returns the value of this part as a string.
         *
         * @return The value of this part as a string, or {@link 
Optional#empty()} if the part was not present.
@@ -249,6 +276,15 @@ public abstract class RequestHttpPart {
        }
 
        /**
+        * Returns the request that created this part.
+        *
+        * @return The request that created this part.
+        */
+       protected RestRequest getRequest() {
+               return request;
+       }
+
+       /**
         * Gets the name of this part.
         *
         * @return The name of this part, never <jk>null</jk>.
diff --git 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RequestPathParam.java
 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RequestPathParam.java
index 89a9115..a192709 100644
--- 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RequestPathParam.java
+++ 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RequestPathParam.java
@@ -13,18 +13,14 @@
 package org.apache.juneau.rest;
 
 import static org.apache.juneau.httppart.HttpPartType.*;
-import static org.apache.juneau.internal.ClassUtils.*;
-import static org.apache.juneau.internal.ThrowableUtils.*;
 
 import java.time.*;
 import java.util.*;
 
 import org.apache.http.*;
-import org.apache.juneau.*;
 import org.apache.juneau.assertions.*;
 import org.apache.juneau.http.part.*;
 import org.apache.juneau.httppart.*;
-import org.apache.juneau.reflect.*;
 
 /**
  * Represents a single path parameter on an HTTP request.
@@ -100,28 +96,6 @@ public class RequestPathParam extends RequestHttpPart 
implements NameValuePair {
        }
 
        /**
-        * Returns the value of this parameter as a {@link BasicPart}.
-        *
-        * @param c The subclass of {@link BasicPart} to instantiate.
-        * @param <T> The subclass of {@link BasicPart} to instantiate.
-        * @return The value of this parameter as a string, never <jk>null</jk>.
-        */
-       public <T extends BasicPart> T asPart(Class<T> c) {
-               try {
-                       ClassInfo ci = ClassInfo.of(c);
-                       ConstructorInfo cc = 
ci.getConstructor(Visibility.PUBLIC, String.class);
-                       if (cc != null)
-                               return cc.invoke(orElse(null));
-                       cc = ci.getConstructor(Visibility.PUBLIC, String.class, 
String.class);
-                       if (cc != null)
-                               return cc.invoke(getName(), orElse(null));
-               } catch (Exception e) {
-                       throw runtimeException(e);
-               }
-               throw runtimeException("Could not determine a method to 
construct type {0}", className(c));
-       }
-
-       /**
         * Returns the value of this parameter as a {@link BasicCsvArrayPart}.
         *
         * @return The value of this parameter as a {@link BasicCsvArrayPart}, 
never <jk>null</jk>.
diff --git 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RequestPathParams.java
 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RequestPathParams.java
index efdb6ac..6acc5de 100644
--- 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RequestPathParams.java
+++ 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RequestPathParams.java
@@ -12,9 +12,12 @@
 // 
***************************************************************************************************************************
 package org.apache.juneau.rest;
 
+import static org.apache.juneau.internal.ClassUtils.*;
 import static org.apache.juneau.internal.StringUtils.*;
+import static org.apache.juneau.internal.ThrowableUtils.*;
 import static java.util.Collections.*;
 import static org.apache.juneau.assertions.Assertions.*;
+import static org.apache.juneau.httppart.HttpPartType.*;
 
 import java.time.*;
 import java.util.*;
@@ -24,7 +27,9 @@ import org.apache.juneau.httppart.*;
 import org.apache.juneau.internal.*;
 import org.apache.juneau.rest.util.*;
 import org.apache.juneau.svl.*;
+import org.apache.juneau.*;
 import org.apache.juneau.collections.*;
+import org.apache.juneau.http.*;
 
 /**
  * Represents the path parameters in an HTTP request.
@@ -355,6 +360,22 @@ public class RequestPathParams {
        }
 
        /**
+        * Returns the path parameter as the specified bean type.
+        *
+        * <p>
+        * Type must have a name specified via the {@link 
org.apache.juneau.http.annotation.Path} annotation
+        * and a public constructor that takes in either <c>value</c> or 
<c>name,value</c> as strings.
+        *
+        * @param type The bean type to create.
+        * @return The bean, never <jk>null</jk>.
+        */
+       public <T> Optional<T> get(Class<T> type) {
+               ClassMeta<T> cm = req.getBeanSession().getClassMeta(type);
+               String name = HttpParts.getName(PATH, 
cm).orElseThrow(()->runtimeException("@Path(name) not found on class {0}", 
className(type)));
+               return get(name).asPart(type);
+       }
+
+       /**
         * Returns the last parameter with the specified name as a string.
         *
         * @param name The parameter name.
diff --git 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RequestQueryParam.java
 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RequestQueryParam.java
index 2d5c90b..a6017fb 100644
--- 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RequestQueryParam.java
+++ 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RequestQueryParam.java
@@ -13,18 +13,14 @@
 package org.apache.juneau.rest;
 
 import static org.apache.juneau.httppart.HttpPartType.*;
-import static org.apache.juneau.internal.ClassUtils.*;
-import static org.apache.juneau.internal.ThrowableUtils.*;
 
 import java.time.*;
 import java.util.*;
 
 import org.apache.http.*;
-import org.apache.juneau.*;
 import org.apache.juneau.assertions.*;
 import org.apache.juneau.http.part.*;
 import org.apache.juneau.httppart.*;
-import org.apache.juneau.reflect.*;
 
 /**
  * Represents a single query parameter on an HTTP request.
@@ -100,28 +96,6 @@ public class RequestQueryParam extends RequestHttpPart 
implements NameValuePair
        }
 
        /**
-        * Returns the value of this parameter as a {@link BasicPart}.
-        *
-        * @param c The subclass of {@link BasicPart} to instantiate.
-        * @param <T> The subclass of {@link BasicPart} to instantiate.
-        * @return The value of this parameter as a string, never <jk>null</jk>.
-        */
-       public <T extends BasicPart> T asPart(Class<T> c) {
-               try {
-                       ClassInfo ci = ClassInfo.of(c);
-                       ConstructorInfo cc = 
ci.getConstructor(Visibility.PUBLIC, String.class);
-                       if (cc != null)
-                               return cc.invoke(orElse(null));
-                       cc = ci.getConstructor(Visibility.PUBLIC, String.class, 
String.class);
-                       if (cc != null)
-                               return cc.invoke(getName(), orElse(null));
-               } catch (Exception e) {
-                       throw runtimeException(e);
-               }
-               throw runtimeException("Could not determine a method to 
construct type {0}", className(c));
-       }
-
-       /**
         * Returns the value of this parameter as a {@link BasicCsvArrayPart}.
         *
         * @return The value of this parameter as a {@link BasicCsvArrayPart}, 
never <jk>null</jk>.
diff --git 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RequestQueryParams.java
 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RequestQueryParams.java
index f0f341c..61e09f5 100644
--- 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RequestQueryParams.java
+++ 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RequestQueryParams.java
@@ -12,9 +12,12 @@
 // 
***************************************************************************************************************************
 package org.apache.juneau.rest;
 
+import static org.apache.juneau.internal.ClassUtils.*;
 import static org.apache.juneau.internal.StringUtils.*;
+import static org.apache.juneau.internal.ThrowableUtils.*;
 import static java.util.Collections.*;
 import static org.apache.juneau.assertions.Assertions.*;
+import static org.apache.juneau.httppart.HttpPartType.*;
 
 import java.time.*;
 import java.util.*;
@@ -24,7 +27,9 @@ import org.apache.juneau.httppart.*;
 import org.apache.juneau.internal.*;
 import org.apache.juneau.svl.*;
 import org.apache.juneau.utils.*;
+import org.apache.juneau.*;
 import org.apache.juneau.collections.*;
+import org.apache.juneau.http.*;
 
 /**
  * Represents the query parameters in an HTTP request.
@@ -365,6 +370,22 @@ public class RequestQueryParams {
        }
 
        /**
+        * Returns the query parameter as the specified bean type.
+        *
+        * <p>
+        * Type must have a name specified via the {@link 
org.apache.juneau.http.annotation.Query} annotation
+        * and a public constructor that takes in either <c>value</c> or 
<c>name,value</c> as strings.
+        *
+        * @param type The bean type to create.
+        * @return The bean, never <jk>null</jk>.
+        */
+       public <T> Optional<T> get(Class<T> type) {
+               ClassMeta<T> cm = req.getBeanSession().getClassMeta(type);
+               String name = HttpParts.getName(QUERY, 
cm).orElseThrow(()->runtimeException("@Query(name) not found on class {0}", 
className(type)));
+               return get(name).asPart(type);
+       }
+
+       /**
         * Returns the last parameter with the specified name as a string.
         *
         * @param name The parameter name.
diff --git 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestRequest.java
 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestRequest.java
index 8200b75..ef6c074 100644
--- 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestRequest.java
+++ 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestRequest.java
@@ -466,418 +466,58 @@ public final class RestRequest {
        
//-----------------------------------------------------------------------------------------------------------------
 
        /**
-        * Returns the <c>Accept</c> header on the request.
+        * Returns the request header of the specified type.
         *
         * <p>
-        * Content-Types that are acceptable for the response.
-        *
-        * <h5 class='figure'>Example:</h5>
-        * <p class='bcode w800'>
-        *      Accept: text/plain
-        * </p>
-        *
-        * @return The parsed header on the request, never <jk>null</jk>.
-        */
-       public Accept getAccept() {
-               return headers.get("Accept").asHeader(Accept.class);
-       }
-
-       /**
-        * Returns the <c>Accept-Charset</c> header on the request.
-        *
-        * <p>
-        * Character sets that are acceptable.
-        *
-        * <h5 class='figure'>Example:</h5>
-        * <p class='bcode w800'>
-        *      Accept-Charset: utf-8
-        * </p>
-        *
-        * @return The parsed header on the request, never <jk>null</jk>.
-        */
-       public AcceptCharset getAcceptCharset() {
-               return 
headers.get("Accept-Charset").asHeader(AcceptCharset.class);
-       }
-
-       /**
-        * Returns the <c>Accept-Encoding</c> header on the request.
-        *
-        * <p>
-        * List of acceptable encodings.
-        *
-        * <h5 class='figure'>Example:</h5>
-        * <p class='bcode w800'>
-        *      Accept-Encoding: gzip, deflate
-        * </p>
-        *
-        * @return The parsed header on the request, never <jk>null</jk>.
-        */
-       public AcceptEncoding getAcceptEncoding() {
-               return 
headers.get("Accept-Encoding").asHeader(AcceptEncoding.class);
-       }
-
-       /**
-        * Returns the <c>Accept-Language</c> header on the request.
-        *
-        * <p>
-        * List of acceptable human languages for response.
-        *
-        * <h5 class='figure'>Example:</h5>
-        * <p class='bcode w800'>
-        *      Accept-Language: en-US
-        * </p>
-        *
-        * @return The parsed header on the request, never <jk>null</jk>.
-        */
-       public AcceptLanguage getAcceptLanguage() {
-               return 
headers.get("Accept-Language").asHeader(AcceptLanguage.class);
-       }
-
-       /**
-        * Returns the <c>Authorization</c> header on the request.
-        *
-        * <p>
-        * Authentication credentials for HTTP authentication.
-        *
-        * <h5 class='figure'>Example:</h5>
-        * <p class='bcode w800'>
-        *      Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==
-        * </p>
-        *
-        * @return The parsed header on the request, never <jk>null</jk>.
-        */
-       public Authorization getAuthorization() {
-               return 
headers.get("Authorization").asHeader(Authorization.class);
-       }
-
-       /**
-        * Returns the <c>Cache-Control</c> header on the request.
-        *
-        * <p>
-        * Used to specify directives that must be obeyed by all caching 
mechanisms along the request-response chain.
-        *
-        * <h5 class='figure'>Example:</h5>
-        * <p class='bcode w800'>
-        *      Cache-Control: no-cache
-        * </p>
-        *
-        * @return The parsed header on the request, never <jk>null</jk>.
-        */
-       public CacheControl getCacheControl() {
-               return 
headers.get("Cache-Control").asHeader(CacheControl.class);
-       }
-
-       /**
-        * Returns the <c>Connection</c> header on the request.
-        *
-        * <p>
-        * Control options for the current connection and list of hop-by-hop 
request fields.
-        *
-        * <h5 class='figure'>Example:</h5>
-        * <p class='bcode w800'>
-        *      Connection: keep-alive
-        *      Connection: Upgrade
-        * </p>
-        *
-        * @return The parsed header on the request, never <jk>null</jk>.
-        */
-       public Connection getConnection() {
-               return headers.get("Connection").asHeader(Connection.class);
-       }
-
-       /**
-        * Returns the <c>Content-Length</c> header on the request.
-        *
-        * <p>
-        * The length of the request body in octets (8-bit bytes).
-        *
-        * <h5 class='figure'>Example:</h5>
-        * <p class='bcode w800'>
-        *      Content-Length: 348
-        * </p>
-        *
-        * @return The parsed header on the request, never <jk>null</jk>.
-        */
-       public ContentLength getContentLength() {
-               return 
headers.get("Content-Length").asHeader(ContentLength.class);
-       }
-
-       /**
-        * Returns the <c>Content-Type</c> header on the request.
-        *
-        * <p>
-        * The MIME type of the body of the request (used with POST and PUT 
requests).
-        *
-        * <h5 class='figure'>Example:</h5>
-        * <p class='bcode w800'>
-        *      Content-Type: application/x-www-form-urlencoded
-        * </p>
-        *
-        * @return The parsed header on the request, never <jk>null</jk>.
-        */
-       public ContentType getContentType() {
-               return headers.get("Content-Type").asHeader(ContentType.class);
-       }
-
-       /**
-        * Returns the <c>Date</c> header on the request.
-        *
-        * <p>
-        * The date and time that the message was originated (in "HTTP-date" 
format as defined by RFC 7231 Date/Time Formats).
-        *
-        * <h5 class='figure'>Example:</h5>
-        * <p class='bcode w800'>
-        *      Date: Tue, 15 Nov 1994 08:12:31 GMT
-        * </p>
-        *
-        * @return The parsed header on the request, never <jk>null</jk>.
-        */
-       public Date getDate() {
-               return headers.get("Date").asHeader(Date.class);
-       }
-
-       /**
-        * Returns the <c>Expect</c> header on the request.
-        *
-        * <p>
-        * Indicates that particular server behaviors are required by the 
client.
-        *
-        * <h5 class='figure'>Example:</h5>
-        * <p class='bcode w800'>
-        *      Expect: 100-continue
-        * </p>
-        *
-        * @return The parsed header on the request, never <jk>null</jk>.
-        */
-       public Expect getExpect() {
-               return headers.get("Expect").asHeader(Expect.class);
-       }
-
-       /**
-        * Returns the <c>From</c> header on the request.
-        *
-        * <p>
-        * The email address of the user making the request.
-        *
-        * <h5 class='figure'>Example:</h5>
-        * <p class='bcode w800'>
-        *      From: [email protected]
-        * </p>
-        *
-        * @return The parsed header on the request, never <jk>null</jk>.
-        */
-       public From getFrom() {
-               return headers.get("From").asHeader(From.class);
-       }
-
-       /**
-        * Returns the <c>Host</c> header on the request.
-        *
-        * <p>
-        * The domain name of the server (for virtual hosting), and the TCP 
port number on which the server is listening.
-        * The port number may be omitted if the port is the standard port for 
the service requested.
-        *
-        * <h5 class='figure'>Example:</h5>
-        * <p class='bcode w800'>
-        *      Host: en.wikipedia.org:8080
-        *      Host: en.wikipedia.org
-        * </p>
-        *
-        * @return The parsed header on the request, never <jk>null</jk>.
-        */
-       public Host getHost() {
-               return headers.get("Host").asHeader(Host.class);
-       }
-
-       /**
-        * Returns the <c>If-Match</c> header on the request.
-        *
-        * <p>
-        * Only perform the action if the client supplied entity matches the 
same entity on the server.
-        * This is mainly for methods like PUT to only update a resource if it 
has not been modified since the user last
-        * updated it.
-        *
-        * <h5 class='figure'>Example:</h5>
-        * <p class='bcode w800'>
-        *      If-Match: "737060cd8c284d8af7ad3082f209582d"
-        * </p>
-        *
-        * @return The parsed header on the request, never <jk>null</jk>.
-        */
-       public IfMatch getIfMatch() {
-               return headers.get("If-Match").asHeader(IfMatch.class);
-       }
-
-       /**
-        * Returns the <c>If-Modified-Since</c> header on the request.
-        *
-        * <p>
-        * Allows a 304 Not Modified to be returned if content is unchanged.
-        *
-        * <h5 class='figure'>Example:</h5>
-        * <p class='bcode w800'>
-        *      If-Modified-Since: Sat, 29 Oct 1994 19:43:31 GMT
-        * </p>
-        *
-        * @return The parsed header on the request, never <jk>null</jk>.
-        */
-       public IfModifiedSince getIfModifiedSince() {
-               return 
headers.get("If-Modified-Since").asHeader(IfModifiedSince.class);
-       }
-
-       /**
-        * Returns the <c>If-None-Match</c> header on the request.
-        *
-        * <p>
-        * Allows a 304 Not Modified to be returned if content is unchanged, 
see HTTP ETag.
-        *
-        * <h5 class='figure'>Example:</h5>
-        * <p class='bcode w800'>
-        *      If-None-Match: "737060cd8c284d8af7ad3082f209582d"
-        * </p>
-        *
-        * @return The parsed header on the request, never <jk>null</jk>.
-        */
-       public IfNoneMatch getIfNoneMatch() {
-               return headers.get("If-None-Match").asHeader(IfNoneMatch.class);
-       }
-
-       /**
-        * Returns the <c>If-Range</c> header on the request.
-        *
-        * <p>
-        * If the entity is unchanged, send me the part(s) that I am missing; 
otherwise, send me the entire ofNullable(entity.
-        *
-        * <h5 class='figure'>Example:</h5>
-        * <p class='bcode w800'>
-        *      If-Range: "737060cd8c284d8af7ad3082f209582d"
-        * </p>
-        *
-        * @return The parsed header on the request, never <jk>null</jk>.
-        */
-       public IfRange getIfRange() {
-               return headers.get("If-Range").asHeader(IfRange.class);
-       }
-
-       /**
-        * Returns the <c>If-Unmodified-Since</c> header on the request.
-        *
-        * <p>
-        * Only send the response if the entity has not been modified since a 
specific time.
-        *
-        * <h5 class='figure'>Example:</h5>
-        * <p class='bcode w800'>
-        *      If-Unmodified-Since: Sat, 29 Oct 1994 19:43:31 GMT
-        * </p>
-        *
-        * @return The parsed header on the request, never <jk>null</jk>.
-        */
-       public IfUnmodifiedSince getIfUnmodifiedSince() {
-               return 
headers.get("If-Unmodified-Since").asHeader(IfUnmodifiedSince.class);
-       }
-
-       /**
-        * Returns the <c>Max-Forwards</c> header on the request.
-        *
-        * <p>
-        * Limit the number of times the message can be forwarded through 
proxies or gateways.
-        *
-        * <h5 class='figure'>Example:</h5>
-        * <p class='bcode w800'>
-        *      Max-Forwards: 10
-        * </p>
-        *
-        * @return The parsed header on the request, never <jk>null</jk>.
-        */
-       public MaxForwards getMaxForwards() {
-               return headers.get("Max-Forwards").asHeader(MaxForwards.class);
-       }
-
-       /**
-        * Returns the <c>Pragma</c> header on the request.
-        *
-        * <p>
-        * Implementation-specific fields that may have various effects 
anywhere along the request-response chain.
-        *
-        * <h5 class='figure'>Example:</h5>
-        * <p class='bcode w800'>
-        *      Pragma: no-cache
-        * </p>
-        *
-        * @return The parsed header on the request, never <jk>null</jk>.
-        */
-       public Pragma getPragma() {
-               return headers.get("Pragma").asHeader(Pragma.class);
-       }
-
-       /**
-        * Returns the <c>Proxy-Authorization</c> header on the request.
-        *
-        * <p>
-        * Authorization credentials for connecting to a proxy.
-        *
-        * <h5 class='figure'>Example:</h5>
-        * <p class='bcode w800'>
-        *      Proxy-Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==
-        * </p>
-        *
-        * @return The parsed header on the request, never <jk>null</jk>.
-        */
-       public ProxyAuthorization getProxyAuthorization() {
-               return 
headers.get("Proxy-Authorization").asHeader(ProxyAuthorization.class);
-       }
-
-       /**
-        * Returns the <c>Range</c> header on the request.
-        *
-        * <p>
-        * Request only part of an entity. Bytes are numbered from 0.
-        *
-        * <h5 class='figure'>Example:</h5>
-        * <p class='bcode w800'>
-        *      Range: bytes=500-999
-        * </p>
-        *
-        * @return The parsed header on the request, never <jk>null</jk>.
-        */
-       public Range getRange() {
-               return headers.get("Range").asHeader(Range.class);
-       }
-
-       /**
-        * Returns the <c>Referer</c> header on the request.
+        * Type must have a name specified via the {@link 
org.apache.juneau.http.annotation.Header} annotation
+        * and a public constructor that takes in either <c>value</c> or 
<c>name,value</c> as strings.
         *
         * <p>
-        * This is the address of the previous web page from which a link to 
the currently requested page was followed.
-        *
-        * <h5 class='figure'>Example:</h5>
-        * <p class='bcode w800'>
-        *      Referer: http://en.wikipedia.org/wiki/Main_Page
-        * </p>
-        *
-        * @return The parsed header on the request, never <jk>null</jk>.
-        */
-       public Referer getReferer() {
-               return headers.get("Referer").asHeader(Referer.class);
-       }
-
-       /**
-        * Returns the <c>TE</c> header on the request.
-        *
-        * <p>
-        * The transfer encodings the user agent is willing to accept: the same 
values as for the response header field
-        * Transfer-Encoding can be used, plus the "trailers" value (related to 
the "chunked" transfer method) to notify the
-        * server it expects to receive additional fields in the trailer after 
the last, zero-sized, chunk.
-        *
-        * <h5 class='figure'>Example:</h5>
-        * <p class='bcode w800'>
-        *      TE: trailers, deflate
-        * </p>
+        * Typically any of the following:
+        * <ul class='javatreec'>
+        *      <li class='jc'>{@link Accept}
+        *      <li class='jc'>{@link AcceptCharset}
+        *      <li class='jc'>{@link AcceptEncoding}
+        *      <li class='jc'>{@link AcceptLanguage}
+        *      <li class='jc'>{@link AcceptRanges}
+        *      <li class='jc'>{@link Authorization}
+        *      <li class='jc'>{@link CacheControl}
+        *      <li class='jc'>{@link ClientVersion}
+        *      <li class='jc'>{@link Connection}
+        *      <li class='jc'>{@link ContentDisposition}
+        *      <li class='jc'>{@link ContentEncoding}
+        *      <li class='jc'>{@link ContentLength}
+        *      <li class='jc'>{@link ContentType}
+        *      <li class='jc'>{@link Date}
+        *      <li class='jc'>{@link Debug}
+        *      <li class='jc'>{@link Expect}
+        *      <li class='jc'>{@link Forwarded}
+        *      <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 NoTrace}
+        *      <li class='jc'>{@link Origin}
+        *      <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 Thrown}
+        *      <li class='jc'>{@link Upgrade}
+        *      <li class='jc'>{@link UserAgent}
+        *      <li class='jc'>{@link Warning}
+        * </ul>
         *
+        * @param type The bean type to create.
         * @return The parsed header on the request, never <jk>null</jk>.
         */
-       public TE getTE() {
-               return headers.get("TE").asHeader(TE.class);
+       public <T> Optional<T> getHeader(Class<T> type) {
+               return headers.get(type);
        }
 
        /**
@@ -895,74 +535,6 @@ public final class RestRequest {
                return empty();
        }
 
-       /**
-        * Returns the <c>User-Agent</c> header on the request.
-        *
-        * <p>
-        * The user agent string of the user agent.
-        *
-        * <h5 class='figure'>Example:</h5>
-        * <p class='bcode w800'>
-        *      User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:12.0) 
Gecko/20100101 Firefox/21.0
-        * </p>
-        *
-        * @return The parsed header on the request, never <jk>null</jk>.
-        */
-       public UserAgent getUserAgent() {
-               return headers.get("Upgrade").asHeader(UserAgent.class);
-       }
-
-       /**
-        * Returns the <c>Upgrade</c> header on the request.
-        *
-        * <p>
-        * Ask the server to upgrade to another protocol.
-        *
-        * <h5 class='figure'>Example:</h5>
-        * <p class='bcode w800'>
-        *      Upgrade: HTTP/2.0, HTTPS/1.3, IRC/6.9, RTA/x11, websocket
-        * </p>
-        *
-        * @return The parsed header on the request, never <jk>null</jk>.
-        */
-       public Upgrade getUpgrade() {
-               return headers.get("Upgrade").asHeader(Upgrade.class);
-       }
-
-       /**
-        * Returns the <c>Via</c> header on the request.
-        *
-        * <p>
-        * Informs the server of proxies through which the request was sent.
-        *
-        * <h5 class='figure'>Example:</h5>
-        * <p class='bcode w800'>
-        *      Via: 1.0 fred, 1.1 example.com (Apache/1.1)
-        * </p>
-        *
-        * @return The parsed header on the request, never <jk>null</jk>.
-        */
-       public Via getVia() {
-               return headers.get("Via").asHeader(Via.class);
-       }
-
-       /**
-        * Returns the <c>Warning</c> header on the request.
-        *
-        * <p>
-        * A general warning about possible problems with the entity body.
-        *
-        * <h5 class='figure'>Example:</h5>
-        * <p class='bcode w800'>
-        *      Warning: 199 Miscellaneous warning
-        * </p>
-        *
-        * @return The parsed header on the request, never <jk>null</jk>.
-        */
-       public Warning getWarning() {
-               return headers.get("Warning").asHeader(Warning.class);
-       }
-
        
//-----------------------------------------------------------------------------------------------------------------
        // Attributes
        
//-----------------------------------------------------------------------------------------------------------------
@@ -1085,6 +657,20 @@ public final class RestRequest {
        }
 
        /**
+        * Returns the request query parameter of the specified type.
+        *
+        * <p>
+        * Type must have a name specified via the {@link 
org.apache.juneau.http.annotation.Query} annotation
+        * and a public constructor that takes in either <c>value</c> or 
<c>name,value</c> as strings.
+        *
+        * @param type The bean type to create.
+        * @return The parsed query parameter on the request, never 
<jk>null</jk>.
+        */
+       public <T> Optional<T> getQueryParam(Class<T> type) {
+               return queryParams.get(type);
+       }
+
+       /**
         * Returns <jk>true</jk> if this request contains the specified header.
         *
         * @param name The header name.
@@ -1166,6 +752,20 @@ public final class RestRequest {
        }
 
        /**
+        * Returns the request form-data parameter of the specified type.
+        *
+        * <p>
+        * Type must have a name specified via the {@link 
org.apache.juneau.http.annotation.FormData} annotation
+        * and a public constructor that takes in either <c>value</c> or 
<c>name,value</c> as strings.
+        *
+        * @param type The bean type to create.
+        * @return The parsed form-data parameter on the request, never 
<jk>null</jk>.
+        */
+       public <T> Optional<T> getFormParam(Class<T> type) {
+               return getFormParams().get(type);
+       }
+
+       /**
         * Returns <jk>true</jk> if this request contains the specified header.
         *
         * @param name The header name.
@@ -1226,6 +826,20 @@ public final class RestRequest {
        }
 
        /**
+        * Returns the request path parameter of the specified type.
+        *
+        * <p>
+        * Type must have a name specified via the {@link 
org.apache.juneau.http.annotation.Path} annotation
+        * and a public constructor that takes in either <c>value</c> or 
<c>name,value</c> as strings.
+        *
+        * @param type The bean type to create.
+        * @return The parsed form-data parameter on the request, never 
<jk>null</jk>.
+        */
+       public <T> Optional<T> getPathParam(Class<T> type) {
+               return pathParams.get(type);
+       }
+
+       /**
         * Shortcut for calling <c>getPathParams().getRemainder()</c>.
         *
         * @return The path remainder value, never <jk>null</jk>.
diff --git 
a/juneau-utest/src/test/java/org/apache/juneau/rest/annotation/Rest_AllowedHeaderParams_Test.java
 
b/juneau-utest/src/test/java/org/apache/juneau/rest/annotation/Rest_AllowedHeaderParams_Test.java
index 39ddba9..d081b8f 100644
--- 
a/juneau-utest/src/test/java/org/apache/juneau/rest/annotation/Rest_AllowedHeaderParams_Test.java
+++ 
b/juneau-utest/src/test/java/org/apache/juneau/rest/annotation/Rest_AllowedHeaderParams_Test.java
@@ -30,8 +30,8 @@ public class Rest_AllowedHeaderParams_Test {
        public static class A {
                @RestOp
                public String put(RequestHeaders h) {
-                       Accept accept = h.get("Accept").asHeader(Accept.class);
-                       ContentType contentType = 
h.get("Content-Type").asHeader(ContentType.class);
+                       Accept accept = 
h.get("Accept").asPart(Accept.class).orElse(Accept.NULL);
+                       ContentType contentType = 
h.get("Content-Type").asPart(ContentType.class).orElse(ContentType.NULL);
                        return "Accept="+(accept.isPresent() ? accept.get() : 
null)+",Content-Type=" + (contentType.isPresent() ? contentType.get() : null) + 
",Custom=" + h.getString("Custom").orElse(null);
                }
        }

Reply via email to