Code cleanup.

Project: http://git-wip-us.apache.org/repos/asf/incubator-juneau/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-juneau/commit/98a53eb3
Tree: http://git-wip-us.apache.org/repos/asf/incubator-juneau/tree/98a53eb3
Diff: http://git-wip-us.apache.org/repos/asf/incubator-juneau/diff/98a53eb3

Branch: refs/heads/master
Commit: 98a53eb3143d1420464b25a5f8289f4dc1a0c495
Parents: 80e8061
Author: JamesBognar <[email protected]>
Authored: Thu May 11 17:17:01 2017 -0400
Committer: JamesBognar <[email protected]>
Committed: Thu May 11 17:17:01 2017 -0400

----------------------------------------------------------------------
 juneau-core/src/main/javadoc/overview.html      | 229 ++++++++++---------
 .../src/main/javadoc/resources/juneau-doc.css   |   1 +
 .../examples/rest/MethodExampleResource.java    | 122 +++++++---
 .../rest/addressbook/AddressBookResource.java   |  16 +-
 .../org/apache/juneau/microservice/package.html |   8 +-
 .../juneau/rest/test/OnPostCallResource.java    |   4 +-
 .../juneau/rest/test/OnPreCallResource.java     |   2 +-
 .../rest/test/OverlappingMethodsResource.java   |   8 +-
 .../apache/juneau/rest/test/ParamsResource.java |  24 +-
 .../apache/juneau/rest/test/PathsResource.java  |   4 +-
 .../apache/juneau/rest/test/UrisResource.java   |   2 +-
 .../java/org/apache/juneau/rest/CallMethod.java |  15 +-
 .../org/apache/juneau/rest/RequestBody.java     |  34 +--
 .../apache/juneau/rest/RequestPathMatch.java    | 213 +++++++++++++++++
 .../apache/juneau/rest/RequestPathParams.java   | 137 -----------
 .../apache/juneau/rest/RestParamDefaults.java   |  12 +-
 .../org/apache/juneau/rest/RestRequest.java     | 185 ++-------------
 .../org/apache/juneau/rest/annotation/Body.java |   2 +-
 .../juneau/rest/converters/Introspectable.java  |   4 +-
 .../juneau/rest/converters/Traversable.java     |   4 +-
 .../java/org/apache/juneau/rest/package.html    |  26 +--
 .../juneau/rest/response/DefaultHandler.java    |   4 +-
 .../org/apache/juneau/rest/vars/RequestVar.java |   8 +-
 23 files changed, 525 insertions(+), 539 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/98a53eb3/juneau-core/src/main/javadoc/overview.html
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/javadoc/overview.html 
b/juneau-core/src/main/javadoc/overview.html
index 3f5683f..f0bd247 100644
--- a/juneau-core/src/main/javadoc/overview.html
+++ b/juneau-core/src/main/javadoc/overview.html
@@ -3026,106 +3026,123 @@
                
                <jd>/** Example GET request that redirects to our example 
method */</jd> 
                <ja>@RestMethod</ja>(name=<js>"GET"</js>, path=<js>"/"</js>) 
-               <jk>public</jk> Redirect doGetExample() <jk>throws</jk> 
Exception { 
-                       <jk>return new</jk> 
Redirect(<js>"example1/xxx/123/{0}/xRemainder?p1=123&amp;p2=yyy"</js>, 
UUID.<jsm>randomUUID</jsm>()); 
+               <jk>public</jk> Redirect doExample() <jk>throws</jk> Exception 
{ 
+                       <jk>return new</jk> 
Redirect(<js>"example1/xxx/123/{0}/xRemainder?q1=123&amp;q2=yyy"</js>, 
UUID.<jsm>randomUUID</jsm>()); 
                } 
                
-               <jd>/** Example GET request using annotated attributes */</jd> 
-               <ja>@RestMethod</ja>(name=<js>"GET"</js>, 
path=<js>"/example1/{a1}/{a2}/{a3}/*"</js>, rc={200}) 
-               <jk>public</jk> String doGetExample1( 
-                       <ja>@Method</ja> String method, 
-                       <ja>@Path</ja> String a1, 
-                       <ja>@Path</ja> <jk>int</jk> a2, 
-                       <ja>@Path</ja> UUID a3, 
-                       <ja>@Query</ja>(<js>"p1"</js>) <jk>int</jk> p1, 
-                       <ja>@Query</ja>(<js>"p2"</js>) String p2, 
-                       <ja>@Query</ja>(<js>"p3"</js>) UUID p3, 
-                       <ja>@PathRemainder</ja> String remainder, 
-                       <ja>@Header</ja>(<js>"Accept-Language"</js>) String 
lang, 
-                       <ja>@Header</ja>(<js>"Accept"</js>) String accept, 
-                       <ja>@Header</ja>(<js>"DNT"</js>) <jk>int</jk> 
doNotTrack 
-               ) { 
-                       String output = String.format( 
-                               <js>"method=%s, a1=%s, a2=%d, a3=%s, 
remainder=%s, p1=%d, p2=%s, p3=%s, lang=%s, accept=%s, dnt=%d"</js>, 
-                               method, a1, a2, a3, remainder, p1, p2, p3, 
lang, accept, doNotTrack); 
-                       <jk>return</jk> output; 
-               } 
-               
-               <jd>/** Example GET request using methods on RestRequest and 
RestResponse */</jd> 
-               <ja>@RestMethod</ja>(name=<js>"GET"</js>, 
path=<js>"/example2/{a1}/{a2}/{a3}/*"</js>, rc={200}) 
-               <jk>public void</jk> doGetExample2(RestRequest req, 
RestResponse res) <jk>throws</jk> Exception { 
-                       String method = req.getMethod(); 
-                       
-                       <jc>// Attributes (from URL pattern variables)</jc> 
-                       RequestPathParams path = req.getPathParams();
-                       String a1 = path.get(<js>"a1"</js>, 
String.<jk>class</jk>); 
-                       <jk>int</jk> a2 = path.get(<js>"a2"</js>, 
<jk>int</jk>.<jk>class</jk>); 
-                       UUID a3 = path.get(<js>"a3"</js>, UUID.<jk>class</jk>); 
+               <jd>/** 
+                * Methodology #1 - GET request using annotated attributes.
+                * This approach uses annotated parameters for retrieving input.
+                */</jd>
+               <ja>@RestMethod</ja>(name=<js>"GET"</js>, 
path=<js>"/example1/{p1}/{p2}/{p3}/*"</js>)
+               <jk>public</jk> String example1(
+                               <ja>@Method</ja> String method,                 
 <jc>// HTTP method.</jc>
+                               <ja>@Path</ja> String p1,                       
 <jc>// Path variables.</jc>
+                               <ja>@Path</ja> <jk>int</jk> p2,
+                               <ja>@Path</ja> UUID p3,
+                               <ja>@Query</ja>(<js>"q1"</js>) <jk>int</jk> q1, 
                   <jc>// Query parameters.</jc>
+                               <ja>@Query</ja>(<js>"q2"</js>) String q2,
+                               <ja>@Query</ja>(<js>"q3"</js>) UUID q3,
+                               <ja>@PathRemainder</ja> String remainder,       
 <jc>// Path remainder after pattern match.</jc>
+                               <ja>@Header</ja>(<js>"Accept-Language"</js>) 
String lang, <jc>// Headers.</jc>
+                               <ja>@Header</ja>(<js>"Accept"</js>) String 
accept,
+                               <ja>@Header</ja>(<js>"DNT"</js>) <jk>int</jk> 
doNotTrack
+                       ) {
+       
+                       <jc>// Send back a simple String response</jc>
+                       String output = String.<jsm>format</jsm>(
+                                       <js>"method=%s, p1=%s, p2=%d, p3=%s, 
remainder=%s, q1=%d, q2=%s, q3=%s, lang=%s, accept=%s, dnt=%d"</js>,
+                                       method, p1, p2, p3, remainder, q1, q2, 
q3, lang, accept, doNotTrack);
+                       <jk>return</jk> output;
+               }
+
+               <jd>/** 
+                * Methodology #2 - GET request using methods on RestRequest 
and RestResponse.
+                * This approach uses low-level request/response objects to 
perform the same as above.
+                */</jd>
+               <ja>@RestMethod</ja>(name=<js>"GET"</js>, 
path=<js>"/example2/{p1}/{p2}/{p3}/*"</js>)
+               <jk>public</jk> String example2(
+                               RestRequest req,          <jc>// A direct 
subclass of HttpServletRequest.</jc>
+                               RestResponse res          <jc>// A direct 
subclass of HttpServletResponse.</jc>
+                       ) {
                        
-                       <jc>// Optional GET parameters</jc> 
+                       <jc>// HTTP method.</jc>
+                       String method = req.getMethod();
+       
+                       <jc>// Path variables.</jc>
+                       RequestPathMatch path = req.getPathMatch();
+                       String p1 = path.get(<js>"p1"</js>, 
String.<jk>class</jk>);
+                       <jk>int</jk> p2 = path.get(<js>"p2"</js>, 
<jk>int</jk>.<jk>class</jk>);
+                       UUID p3 = path.get(<js>"p3"</js>, UUID.<jk>class</jk>);
+       
+                       <jc>// Query parameters.</jc>
                        RequestQuery query = req.getQuery();
-                       <jk>int</jk> p1 = query.get(<js>"p1"</js>, 
<jk>int</jk>.<jk>class</jk>, 0); 
-                       String p2 = query.get(<js>"p2"</js>, 
String.<jk>class</jk>); 
-                       UUID p3 = query.get(<js>"p3"</js>, 
UUID.<jk>class</jk>); 
-                       
-                       <jc>// URL pattern post-match</jc> 
-                       String remainder = req.getPathRemainder(); 
-                       
-                       <jc>// Headers</jc> 
-                       String lang = 
req.getHeader(<js>"Accept-Language"</js>); 
-                       <jk>int</jk> doNotTrack = req.getHeader(<js>"DNT"</js>, 
<jk>int</jk>.<jk>class</jk>); 
-                       
-                       <jc>// Send back a simple String response</jc> 
-                       String output = String.format( 
-                               <js>"method=%s, a1=%s, a2=%d, a3=%s, 
remainder=%s, p1=%d, p2=%s, p3=%s, lang=%s, dnt=%d"</js>, 
-                               method, a1, a2, a3, remainder, p1, p2, p3, 
lang, doNotTrack); 
-                       res.setOutput(output); 
-               } 
+                       <jk>int</jk> q1 = query.get(<js>"q1"</js>, 0, 
<jk>int</jk>.<jk>class</jk>);
+                       String q2 = query.get(<js>"q2"</js>, 
String.<jk>class</jk>);
+                       UUID q3 = query.get(<js>"q3"</js>, UUID.<jk>class</jk>);
+       
+                       <jc>// Path remainder after pattern match.</jc>
+                       String remainder = req.getPathMatch().getRemainder();
+       
+                       <jc>// Headers.</jc>
+                       String lang = req.getHeader(<js>"Accept-Language"</js>);
+                       String accept = req.getHeader(<js>"Accept"</js>);
+                       <jk>int</jk> doNotTrack = 
req.getHeaders().get(<js>"DNT"</js>, <jk>int</jk>.<jk>class</jk>);
+       
+                       <jc>// Send back a simple String response</jc>
+                       String output = String.format(
+                                       <js>"method=%s, p1=%s, p2=%d, p3=%s, 
remainder=%s, q1=%d, q2=%s, q3=%s, lang=%s, accept=%s, dnt=%d"</js>,
+                                       method, p1, p2, p3, remainder, q1, q2, 
q3, lang, accept, doNotTrack);
+                       res.setOutput(output);  <jc>// Or use getWriter().</jc>
+               }
 
-               <jd>/** Example GET request using resolved parameter objects 
*/</jd> 
-               <ja>@RestMethod</ja>(name=<js>"GET"</js>, 
path=<js>"/example3/{a1}/{a2}/{a3}/*"</js>, rc={200}) 
-               <jk>public void</jk> doGetExample3(
-                               HttpMethod httpMethod, 
-                               RequestPathParams path, 
-                               RequestQuery query,
-                               <ja>@PathRemainder</ja> String remainder,
-                               AcceptLanguage acceptLanguage,
-                               Accept accept,
-                               DNT dnt
-                       ) <jk>throws</jk> Exception { 
-                       
-                       String method = httpMethod.toString(); 
-                       
-                       <jc>// Attributes (from URL pattern variables)</jc> 
-                       String a1 = path.get(<js>"a1"</js>, 
String.<jk>class</jk>); 
-                       <jk>int</jk> a2 = path.get(<js>"a2"</js>, 
<jk>int</jk>.<jk>class</jk>); 
-                       UUID a3 = path.get(<js>"a3"</js>, UUID.<jk>class</jk>); 
-                       
-                       <jc>// Optional GET parameters</jc> 
-                       <jk>int</jk> p1 = query.get(<js>"p1"</js>, 
<jk>int</jk>.<jk>class</jk>, 0); 
-                       String p2 = query.get(<js>"p2"</js>, 
String.<jk>class</jk>); 
-                       UUID p3 = query.get(<js>"p3"</js>, 
UUID.<jk>class</jk>); 
-                       
-                       <jc>// Headers</jc> 
-                       String lang = acceptLanguage.toString(); 
-                       <jk>int</jk> doNotTrack = 
dnt.asType(<jk>int</jk>.<jk>class</jk>); 
+               <jd>/** 
+                * Methodology #3 - GET request using special objects.
+                * This approach uses intermediate-level APIs.
+                * The framework recognizes the parameter types and knows how 
to resolve them.
+                */</jd>
+               <ja>@RestMethod</ja>(name=<js>"GET"</js>, 
path=<js>"/example3/{p1}/{p2}/{p3}/*"</js>)
+               <jk>public</jk> String example3(
+                               HttpMethod method,           <jc>// HTTP 
method.</jc>
+                               RequestPathMatch path,       <jc>// Path 
variables.</jc>
+                               RequestQuery query,          <jc>// Query 
parameters.</jc>
+                               RequestHeaders headers,      <jc>// 
Headers.</jc>
+                               AcceptLanguage lang,         <jc>// Specific 
header classes.</jc>
+                               Accept accept
+                       ) {
                        
-                       <jc>// Send back a simple String response</jc> 
-                       String output = String.format( 
-                               <js>"method=%s, a1=%s, a2=%d, a3=%s, 
remainder=%s, p1=%d, p2=%s, p3=%s, lang=%s, dnt=%d"</js>, 
-                               method, a1, a2, a3, remainder, p1, p2, p3, 
lang, doNotTrack); 
-                       res.setOutput(output); 
-               } 
-       } 
+                       <jc>// Path variables.</jc>
+                       String p1 = path.get(<js>"p1"</js>, 
String.<jk>class</jk>);
+                       <jk>int</jk> p2 = path.get(<js>"p2"</js>, 
<jk>int</jk>.<jk>class</jk>);
+                       UUID p3 = path.get(<js>"p3"</js>, UUID.<jk>class</jk>);
+       
+                       <jc>// Query parameters.</jc>
+                       <jk>int</jk> q1 = query.get(<js>"q1"</js>, 0, 
<jk>int</jk>.<jk>class</jk>);
+                       String q2 = query.get(<js>"q2"</js>, 
String.<jk>class</jk>);
+                       UUID q3 = query.get(<js>"q3"</js>, UUID.<jk>class</jk>);
+       
+                       <jc>// Path remainder after pattern match.</jc>
+                       String remainder = path.getRemainder();
+       
+                       <jc>// Headers.</jc>
+                       int doNotTrack = headers.get(<js>"DNT"</js>, 
<jk>int</jk>.<jk>class</jk>);
+       
+                       <jc>// Send back a simple String response</jc>
+                       String output = String.format(
+                                       <js>"method=%s, p1=%s, p2=%d, p3=%s, 
remainder=%s, q1=%d, q2=%s, q3=%s, lang=%s, accept=%s, dnt=%d"</js>,
+                                       method, p1, p2, p3, remainder, q1, q2, 
q3, lang, accept, doNotTrack);
+                       res.setOutput(output);
+               }
+       }
                </p>
                <p>
                        The class consists of 4 methods:
                </p>    
                <ul class='javahierarchy'>
-                       <li class='m'><l>doGetExample()</l>
+                       <li class='m'><l>doExample()</l>
                                <br>The root page. 
                                <br>Performs a simple redirection to the 
<l>doGetExample1()</l> method using a {@link org.apache.juneau.rest.Redirect} 
object.
-                       <li class='m'><l>doGetExample1()</l>
+                       <li class='m'><l>example1()</l>
                                <br>Shows how to use the following annotations:
                                <ul>
                                        <li class='n'>{@link 
org.apache.juneau.rest.annotation.Path @Path}
@@ -3135,18 +3152,18 @@
                                        <li class='n'>{@link 
org.apache.juneau.rest.annotation.PathRemainder @PathRemainder}
                                </ul>
                                Method returns a POJO to be serialized as the 
output.
-                       <li class='m'><l>doGetExample2()</l>
+                       <li class='m'><l>example2()</l>
                                <br>Identical to <l>doGetExample1()</l> but 
shows how to use the {@link org.apache.juneau.rest.RestRequest} and {@link 
org.apache.juneau.rest.RestResponse} objects:
                                <ul>
-                                       <li class='m'>{@link 
org.apache.juneau.rest.RestRequest#getPathParams()}
+                                       <li class='m'>{@link 
org.apache.juneau.rest.RestRequest#getPathMatch()}
                                        <li class='m'>{@link 
org.apache.juneau.rest.RestRequest#getQuery()}
                                        <li class='m'>{@link 
org.apache.juneau.rest.RestRequest#getFormData()}
                                        <li class='m'>{@link 
org.apache.juneau.rest.RestRequest#getHeaders()}
                                        <li class='m'>{@link 
org.apache.juneau.rest.RestRequest#getMethod()}
-                                       <li class='m'>{@link 
org.apache.juneau.rest.RestRequest#getPathRemainder()}
+                                       <li class='m'>{@link 
org.apache.juneau.rest.RequestPathMatch#getRemainder()}
                                </ul>
                                Method sets the POJO to be serialized using the 
{@link org.apache.juneau.rest.RestResponse#setOutput(Object)} method.
-                       <li class='m'><l>doGetExample2()</l>
+                       <li class='m'><l>example3()</l>
                                <br>Identical to <l>doGetExample1()</l> but 
uses automatically resolved parameters based on class type.
                                <br>Juneau automatically recognizes specific 
class types such as common header types and automatically
                                        resolves them to objects for you.  
@@ -4103,14 +4120,13 @@
                <ja>@RestMethod</ja>(name=<js>"PUT"</js>, 
path=<js>"/people/{id}/*"</js>, 
                        guards=AdminGuard.<jk>class</jk> 
                ) 
-               <jk>public</jk> String updatePerson(RestRequest req, 
<ja>@Path</ja> <jk>int</jk> id) <jk>throws</jk> Exception { 
+               <jk>public</jk> String updatePerson(RestRequest req, 
<ja>@Path</ja> <jk>int</jk> id, <ja>@PathRemainder</ja> String remainder) 
<jk>throws</jk> Exception { 
                        <jk>try</jk> { 
                                Person p = findPerson(id); 
-                               String pathRemainder = req.getPathRemainder(); 
                                PojoRest r = <jk>new</jk> PojoRest(p); 
-                               ClassMeta&lt;?&gt; cm = 
r.getClassMeta(pathRemainder); 
-                               Object in = req.getBody(cm); 
-                               r.put(pathRemainder, in); 
+                               ClassMeta&lt;?&gt; cm = 
r.getClassMeta(remainder); 
+                               Object in = req.getBody().asType(cm); 
+                               r.put(remainder, in); 
                                <jk>return</jk> <js>"PUT successful"</js>; 
                        } <jk>catch</jk> (Exception e) { 
                                <jk>throw new</jk> 
RestException(<jsf>SC_BAD_REQUEST</jsf>, <js>"PUT 
unsuccessful"</js>).initCause(e); 
@@ -4124,14 +4140,13 @@
                <ja>@RestMethod</ja>(name=<js>"PUT"</js>, 
path=<js>"/addresses/{id}/*"</js>, 
                        guards=AdminGuard.<jk>class</jk> 
                ) 
-               <jk>public</jk> String updateAddress(RestRequest req, 
<ja>@Path</ja> <jk>int</jk> id) <jk>throws</jk> Exception { 
+               <jk>public</jk> String updateAddress(RestRequest req, 
<ja>@Path</ja> <jk>int</jk> id, <ja>@PathRemainder</ja> String remainder) 
<jk>throws</jk> Exception { 
                        <jk>try</jk> { 
                                Address a = findAddress(id); 
-                               String pathInfo = req.getPathInfo(); 
                                PojoRest r = <jk>new</jk> PojoRest(a); 
-                               ClassMeta&lt;?&gt; cm = 
r.getClassMeta(pathInfo); 
-                               Object in = req.getBody(cm); 
-                               r.put(pathInfo, in); 
+                               ClassMeta&lt;?&gt; cm = 
r.getClassMeta(remainder); 
+                               Object in = req.getBody().asType(cm); 
+                               r.put(remainder, in); 
                                <jk>return</jk> <js>"PUT successful"</js>; 
                        } <jk>catch</jk> (Exception e) { 
                                <jk>throw new</jk> 
RestException(<jsf>SC_BAD_REQUEST</jsf>, <js>"PUT 
unsuccessful"</js>).initCause(e); 
@@ -5969,7 +5984,7 @@
                                        <li>{@link 
org.apache.juneau.rest.RestRequest#getHeaders()} - The request headers.
                                        <li>{@link 
org.apache.juneau.rest.RestRequest#getQuery()} - The request query parameters.
                                        <li>{@link 
org.apache.juneau.rest.RestRequest#getFormData()} - The request form data 
parameters.
-                                       <li>{@link 
org.apache.juneau.rest.RestRequest#getPathParams()} - The path variables.
+                                       <li>{@link 
org.apache.juneau.rest.RestRequest#getPathMatch()} - The path variables and 
remainder.
                                </ul>   
                                The following classes have been introduced:
                                <ul>
@@ -5977,7 +5992,7 @@
                                        <li>{@link 
org.apache.juneau.rest.RequestHeaders}
                                        <li>{@link 
org.apache.juneau.rest.RequestQuery}
                                        <li>{@link 
org.apache.juneau.rest.RequestFormData}
-                                       <li>{@link 
org.apache.juneau.rest.RequestPathParams}
+                                       <li>{@link 
org.apache.juneau.rest.RequestPathMatch}
                                </ul>                                           
                        <li>The unannotated parameter types that can be passed 
in through REST Java methods has been significantly expanded.
                                <br>For reference, the previous supported types 
were:
@@ -6030,7 +6045,7 @@
                                        <li>{@link 
org.apache.juneau.rest.RequestHeaders} - API for accessing request headers.
                                        <li>{@link 
org.apache.juneau.rest.RequestQuery} - API for accessing request query 
parameters.
                                        <li>{@link 
org.apache.juneau.rest.RequestFormData} - API for accessing request form data.
-                                       <li>{@link 
org.apache.juneau.rest.RequestPathParams} - API for accessing path variables.
+                                       <li>{@link 
org.apache.juneau.rest.RequestPathMatch} - API for accessing path variables.
                                        <li>{@link 
org.apache.juneau.rest.RequestBody} - API for accessing request body.
                                        <li>{@link 
org.apache.juneau.http.HttpMethod} - The method name matched (when using 
<code><ja>@RestMethod</ja>(name=<js>"*"</js>)</code>)
                                        <li>{@link java.util.logging.Logger} - 
The logger to use for logging.
@@ -7502,7 +7517,7 @@
                                                        
<li><code><del>RestRequest.getQueryParameterMap()</del></code>
                                                        
<li><code><del>RestRequest.getQueryParameterNames()</del></code>
                                                        <li>{@link 
org.apache.juneau.rest.RestRequest#getPathInfoUndecoded()}
-                                                       <li>{@link 
org.apache.juneau.rest.RestRequest#getPathRemainderUndecoded()}
+                                                       
<li><code><del>RestRequest.getPathRemainderUndecoded()</del></code>
                                                        <li>{@link 
org.apache.juneau.rest.RestRequest#getTrimmedRequestURI()}
                                                        <li>{@link 
org.apache.juneau.rest.RestRequest#getTrimmedRequestURL()}
                                                        <li>{@link 
org.apache.juneau.rest.RestRequest#getServletTitle()}
@@ -7511,8 +7526,8 @@
                                                </ul>
                                        <li>Behavior changes to {@link 
org.apache.juneau.rest.RestRequest#getPathInfo()} to follow Servlet specs.
                                                Returns <jk>null</jk> instead 
of blank for no path info.
-                                       <li>{@link 
org.apache.juneau.rest.RestRequest#getPathRemainder()} now automatically 
decodes the path remainder. 
-                                               Use {@link 
org.apache.juneau.rest.RestRequest#getPathRemainderUndecoded()} to get the 
unencoded path remainder.
+                                       
<li><code><del>RestRequest.getPathRemainder()</del></code> now automatically 
decodes the path remainder. 
+                                               Use 
<code><del>RestRequest.getPathRemainderUndecoded()</del></code> to get the 
unencoded path remainder.
                                        <li>Bug fixes in {@link 
org.apache.juneau.rest.RestRequest#getRequestParentURI()} when servlet is 
mapped to <js>"/*"</js>.
                                        <li>Bug fixes in {@link 
org.apache.juneau.rest.RestRequest#getServletURI()} when servlet is mapped to 
<js>"/*"</js>.
                                </ul>

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/98a53eb3/juneau-core/src/main/javadoc/resources/juneau-doc.css
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/javadoc/resources/juneau-doc.css 
b/juneau-core/src/main/javadoc/resources/juneau-doc.css
index 572b253..1bc7c23 100755
--- a/juneau-core/src/main/javadoc/resources/juneau-doc.css
+++ b/juneau-core/src/main/javadoc/resources/juneau-doc.css
@@ -343,6 +343,7 @@ l {
 p.severe, p.warn, p.info {
        background-repeat: no-repeat;
        background-position: left center;
+       background-size: 16px;
        padding-left: 30px;
     min-height: 24px;
 }

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/98a53eb3/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/MethodExampleResource.java
----------------------------------------------------------------------
diff --git 
a/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/MethodExampleResource.java
 
b/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/MethodExampleResource.java
index ba6ce35..4aad593 100644
--- 
a/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/MethodExampleResource.java
+++ 
b/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/MethodExampleResource.java
@@ -14,12 +14,14 @@ package org.apache.juneau.examples.rest;
 
 import java.util.*;
 
+import org.apache.juneau.http.*;
 import org.apache.juneau.microservice.*;
 import org.apache.juneau.rest.*;
 import org.apache.juneau.rest.annotation.*;
+import org.apache.juneau.rest.annotation.Method;
 
 /**
- * Sample REST resource that shows how to define REST methods and OPTIONS pages
+ * Sample REST resource that shows how to define REST methods.
  */
 @RestResource(
        path="/methodExample",
@@ -31,59 +33,111 @@ public class MethodExampleResource extends Resource {
 
        /** Example GET request that redirects to our example method */
        @RestMethod(name="GET", path="/")
-       public Redirect doGetExample() throws Exception {
-               return new 
Redirect("example1/xxx/123/{0}/xRemainder?p1=123&p2=yyy", UUID.randomUUID());
+       public Redirect doExample() throws Exception {
+               return new 
Redirect("example1/xxx/123/{0}/xRemainder?q1=123&q2=yyy", UUID.randomUUID());
        }
 
-       /** Example GET request using annotated attributes */
-       @RestMethod(name="GET", path="/example1/{a1}/{a2}/{a3}/*", 
responses={@Response(200)})
-       public String doGetExample1(
-                       @Method String method,
-                       @Path String a1,
-                       @Path int a2,
-                       @Path UUID a3,
-                       @Query("p1") int p1,
-                       @Query("p2") String p2,
-                       @Query("p3") UUID p3,
-                       @PathRemainder String remainder,
-                       @Header("Accept-Language") String lang,
+       /** 
+        * Methodology #1 - GET request using annotated attributes.
+        * This approach uses annotated parameters for retrieving input.
+        */
+       @RestMethod(name="GET", path="/example1/{p1}/{p2}/{p3}/*")
+       public String example1(
+                       @Method String method,                  // HTTP method.
+                       @Path String p1,                        // Path 
variables.
+                       @Path int p2,
+                       @Path UUID p3,
+                       @Query("q1") int q1,                    // Query 
parameters.
+                       @Query("q2") String q2,
+                       @Query("q3") UUID q3,
+                       @PathRemainder String remainder,        // Path 
remainder after pattern match.
+                       @Header("Accept-Language") String lang, // Headers.
                        @Header("Accept") String accept,
                        @Header("DNT") int doNotTrack
                ) {
+
+               // Send back a simple String response
                String output = String.format(
-                               "method=%s, a1=%s, a2=%d, a3=%s, remainder=%s, 
p1=%d, p2=%s, p3=%s, lang=%s, accept=%s, dnt=%d",
-                               method, a1, a2, a3, remainder, p1, p2, p3, 
lang, accept, doNotTrack);
+                               "method=%s, p1=%s, p2=%d, p3=%s, remainder=%s, 
q1=%d, q2=%s, q3=%s, lang=%s, accept=%s, dnt=%d",
+                               method, p1, p2, p3, remainder, q1, q2, q3, 
lang, accept, doNotTrack);
                return output;
        }
 
-       /** Example GET request using methods on RestRequest and RestResponse */
-       @RestMethod(name="GET", path="/example2/{a1}/{a2}/{a3}/*", 
responses={@Response(200)})
-       public void doGetExample2(RestRequest req, RestResponse res) throws 
Exception {
+       /** 
+        * Methodology #2 - GET request using methods on RestRequest and 
RestResponse.
+        * This approach uses low-level request/response objects to perform the 
same as above.
+        */
+       @RestMethod(name="GET", path="/example2/{p1}/{p2}/{p3}/*")
+       public void example2(
+                       RestRequest req,          // A direct subclass of 
HttpServletRequest.
+                       RestResponse res          // A direct subclass of 
HttpServletResponse.
+               ) throws Exception {
+               
+               // HTTP method.
                String method = req.getMethod();
 
-               // Attributes (from URL pattern variables)
-               RequestPathParams path = req.getPathParams();
-               String a1 = path.get("a1", String.class);
-               int a2 = path.get("a2", int.class);
-               UUID a3 = path.get("a3", UUID.class);
+               // Path variables.
+               RequestPathMatch path = req.getPathMatch();
+               String p1 = path.get("p1", String.class);
+               int p2 = path.get("p2", int.class);
+               UUID p3 = path.get("p3", UUID.class);
 
-               // Optional GET parameters
+               // Query parameters.
                RequestQuery query = req.getQuery();
-               int p1 = query.get("p1", 0, int.class);
-               String p2 = query.get("p2", String.class);
-               UUID p3 = query.get("p3", UUID.class);
+               int q1 = query.get("q1", 0, int.class);
+               String q2 = query.get("q2", String.class);
+               UUID q3 = query.get("q3", UUID.class);
 
-               // URL pattern post-match
-               String remainder = req.getPathRemainder();
+               // Path remainder after pattern match.
+               String remainder = req.getPathMatch().getRemainder();
 
-               // Headers
+               // Headers.
                String lang = req.getHeader("Accept-Language");
+               String accept = req.getHeader("Accept");
                int doNotTrack = req.getHeaders().get("DNT", int.class);
 
                // Send back a simple String response
                String output = String.format(
-                               "method=%s, a1=%s, a2=%d, a3=%s, remainder=%s, 
p1=%d, p2=%s, p3=%s, lang=%s, dnt=%d",
-                               method, a1, a2, a3, remainder, p1, p2, p3, 
lang, doNotTrack);
+                               "method=%s, p1=%s, p2=%d, p3=%s, remainder=%s, 
q1=%d, q2=%s, q3=%s, lang=%s, accept=%s, dnt=%d",
+                               method, p1, p2, p3, remainder, q1, q2, q3, 
lang, accept, doNotTrack);
                res.setOutput(output);
        }
+
+       /** 
+        * Methodology #3 - GET request using special objects.
+        * This approach uses intermediate-level APIs.
+        * The framework recognizes the parameter types and knows how to 
resolve them.
+        */
+       @RestMethod(name="GET", path="/example3/{p1}/{p2}/{p3}/*")
+       public String example3(
+               HttpMethod method,           // HTTP method.
+               RequestPathMatch path,       // Path variables.
+               RequestQuery query,          // Query parameters.
+               RequestHeaders headers,      // Headers.
+               AcceptLanguage lang,         // Specific header classes.
+               Accept accept
+       ) throws Exception {
+
+               // Path variables.
+               String p1 = path.get("p1", String.class);
+               int p2 = path.get("p2", int.class);
+               UUID p3 = path.get("p3", UUID.class);
+
+               // Query parameters.
+               int q1 = query.get("q1", 0, int.class);
+               String q2 = query.get("q2", String.class);
+               UUID q3 = query.get("q3", UUID.class);
+
+               // Path remainder after pattern match.
+               String remainder = path.getRemainder();
+
+               // Headers.
+               int doNotTrack = headers.get("DNT", int.class);
+
+               // Send back a simple String response
+               String output = String.format(
+                               "method=%s, p1=%s, p2=%d, p3=%s, remainder=%s, 
q1=%d, q2=%s, q3=%s, lang=%s, accept=%s, dnt=%d",
+                               method, p1, p2, p3, remainder, q1, q2, q3, 
lang, accept, doNotTrack);
+               return output;
+       }       
 }

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/98a53eb3/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/addressbook/AddressBookResource.java
----------------------------------------------------------------------
diff --git 
a/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/addressbook/AddressBookResource.java
 
b/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/addressbook/AddressBookResource.java
index 122d949..5fed44f 100644
--- 
a/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/addressbook/AddressBookResource.java
+++ 
b/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/addressbook/AddressBookResource.java
@@ -203,14 +203,13 @@ public class AddressBookResource extends ResourceJena {
        @RestMethod(name="PUT", path="/people/{id}/*",
                guards=AdminGuard.class
        )
-       public String updatePerson(RestRequest req, @Path int id) throws 
Exception {
+       public String updatePerson(RequestBody body, @Path int id, 
@PathRemainder String remainder) throws Exception {
                try {
                        Person p = findPerson(id);
-                       String pathRemainder = req.getPathRemainder();
                        PojoRest r = new PojoRest(p);
-                       ClassMeta<?> cm = r.getClassMeta(pathRemainder);
-                       Object in = req.getBody().asType(cm);
-                       r.put(pathRemainder, in);
+                       ClassMeta<?> cm = r.getClassMeta(remainder);
+                       Object in = body.asType(cm);
+                       r.put(remainder, in);
                        return "PUT successful";
                } catch (Exception e) {
                        throw new RestException(SC_BAD_REQUEST, "PUT 
unsuccessful").initCause(e);
@@ -224,14 +223,13 @@ public class AddressBookResource extends ResourceJena {
        @RestMethod(name="PUT", path="/addresses/{id}/*",
                guards=AdminGuard.class
        )
-       public String updateAddress(RestRequest req, @Path int id) throws 
Exception {
+       public String updateAddress(RestRequest req, @Path int id, 
@PathRemainder String remainder) throws Exception {
                try {
                        Address a = findAddress(id);
-                       String pathInfo = req.getPathInfo();
                        PojoRest r = new PojoRest(a);
-                       ClassMeta<?> cm = r.getClassMeta(pathInfo);
+                       ClassMeta<?> cm = r.getClassMeta(remainder);
                        Object in = req.getBody().asType(cm);
-                       r.put(pathInfo, in);
+                       r.put(remainder, in);
                        return "PUT successful";
                } catch (Exception e) {
                        throw new RestException(SC_BAD_REQUEST, "PUT 
unsuccessful").initCause(e);

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/98a53eb3/juneau-microservice/src/main/java/org/apache/juneau/microservice/package.html
----------------------------------------------------------------------
diff --git 
a/juneau-microservice/src/main/java/org/apache/juneau/microservice/package.html 
b/juneau-microservice/src/main/java/org/apache/juneau/microservice/package.html
index 2595771..a643da5 100755
--- 
a/juneau-microservice/src/main/java/org/apache/juneau/microservice/package.html
+++ 
b/juneau-microservice/src/main/java/org/apache/juneau/microservice/package.html
@@ -652,14 +652,14 @@
                                        <ul>
                                                <li><l>$R{attribute.X}</l> - 
Value returned by {@link 
org.apache.juneau.rest.RestRequest#getAttribute(String)} converted to a string.
                                                <li><l>$R{contextPath}</l> - 
Value returned by {@link org.apache.juneau.rest.RestRequest#getContextPath()}.
-                                               <li><l>$R{formData.X}</l> - 
Value returned by {@link 
org.apache.juneau.rest.RestRequest#getFormData(String)}.
-                                               <li><l>$R{header.X}</l> - Value 
returned by {@link org.apache.juneau.rest.RestRequest#getHeader(String)}.
+                                               <li><l>$R{formData.X}</l> - 
Value returned by {@link 
org.apache.juneau.rest.RequestFormData#getFirst(String)}.
+                                               <li><l>$R{header.X}</l> - Value 
returned by {@link org.apache.juneau.rest.RequestHeaders#getFirst(String)}.
                                                <li><l>$R{method}</l> - Value 
returned by {@link org.apache.juneau.rest.RestRequest#getMethod()}.
                                                <li><l>$R{methodSummary}</l> - 
Value returned by {@link org.apache.juneau.rest.RestRequest#getMethodSummary()}.
                                                
<li><l>$R{methodDescription}</l> - Value returned by {@link 
org.apache.juneau.rest.RestRequest#getMethodDescription()}.
-                                               <li><l>$R{path.X}</l> - Value 
returned by {@link org.apache.juneau.rest.RestRequest#getPathParameter(String)}.
+                                               <li><l>$R{path.X}</l> - Value 
returned by {@link org.apache.juneau.rest.RequestPathMatch#get(Object)}.
                                                <li><l>$R{pathInfo}</l> - Value 
returned by {@link org.apache.juneau.rest.RestRequest#getPathInfo()}.
-                                               <li><l>$R{query.X}</l> - Value 
returned by {@link org.apache.juneau.rest.RestRequest#getQuery(String)}.
+                                               <li><l>$R{query.X}</l> - Value 
returned by {@link org.apache.juneau.rest.RequestQuery#getFirst(String)}.
                                                <li><l>$R{requestParentURI}</l> 
- Value returned by {@link 
org.apache.juneau.rest.RestRequest#getRequestParentURI()}.
                                                <li><l>$R{requestURI}</l> - 
Value returned by {@link org.apache.juneau.rest.RestRequest#getRequestURI()}.
                                                
<li><l>$R{servletDescription}</l> - Value returned by {@link 
org.apache.juneau.rest.RestRequest#getServletDescription()}.

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/98a53eb3/juneau-rest-test/src/main/java/org/apache/juneau/rest/test/OnPostCallResource.java
----------------------------------------------------------------------
diff --git 
a/juneau-rest-test/src/main/java/org/apache/juneau/rest/test/OnPostCallResource.java
 
b/juneau-rest-test/src/main/java/org/apache/juneau/rest/test/OnPostCallResource.java
index c18b5e3..e046779 100644
--- 
a/juneau-rest-test/src/main/java/org/apache/juneau/rest/test/OnPostCallResource.java
+++ 
b/juneau-rest-test/src/main/java/org/apache/juneau/rest/test/OnPostCallResource.java
@@ -63,7 +63,7 @@ public class OnPostCallResource extends RestServlet {
                properties.put("p5", "xp5"); // New property
                String overrideAccept = req.getHeader("Override-Accept");
                if (overrideAccept != null)
-                       req.setHeader("Accept", overrideAccept);
+                       req.getHeaders().put("Accept", overrideAccept);
                String overrideContentType = 
req.getHeader("Override-Content-Type");
                if (overrideContentType != null)
                        properties.put("Override-Content-Type", 
overrideContentType);
@@ -93,7 +93,7 @@ public class OnPostCallResource extends RestServlet {
                properties.put("p4", "pp4");
                String accept = req.getHeader("Accept");
                if (accept == null || accept.isEmpty())
-                       req.setHeader("Accept", "text/s2");
+                       req.getHeaders().put("Accept", "text/s2");
                return "";
        }
 }

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/98a53eb3/juneau-rest-test/src/main/java/org/apache/juneau/rest/test/OnPreCallResource.java
----------------------------------------------------------------------
diff --git 
a/juneau-rest-test/src/main/java/org/apache/juneau/rest/test/OnPreCallResource.java
 
b/juneau-rest-test/src/main/java/org/apache/juneau/rest/test/OnPreCallResource.java
index 9479ab4..feefe2f 100644
--- 
a/juneau-rest-test/src/main/java/org/apache/juneau/rest/test/OnPreCallResource.java
+++ 
b/juneau-rest-test/src/main/java/org/apache/juneau/rest/test/OnPreCallResource.java
@@ -61,7 +61,7 @@ public class OnPreCallResource extends RestServlet {
                properties.put("p5", "xp5"); // New property
                String overrideContentType = 
req.getHeader("Override-Content-Type");
                if (overrideContentType != null)
-                       req.setHeader("Content-Type", overrideContentType);
+                       req.getHeaders().put("Content-Type", 
overrideContentType);
        }
 
 

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/98a53eb3/juneau-rest-test/src/main/java/org/apache/juneau/rest/test/OverlappingMethodsResource.java
----------------------------------------------------------------------
diff --git 
a/juneau-rest-test/src/main/java/org/apache/juneau/rest/test/OverlappingMethodsResource.java
 
b/juneau-rest-test/src/main/java/org/apache/juneau/rest/test/OverlappingMethodsResource.java
index c5dfce1..0e943d4 100644
--- 
a/juneau-rest-test/src/main/java/org/apache/juneau/rest/test/OverlappingMethodsResource.java
+++ 
b/juneau-rest-test/src/main/java/org/apache/juneau/rest/test/OverlappingMethodsResource.java
@@ -45,14 +45,14 @@ public class OverlappingMethodsResource extends 
RestServletDefault {
        public static class Test1Guard extends RestGuard {
                @Override /* RestGuard */
                public boolean isRequestAllowed(RestRequest req) {
-                       return req.getQuery("t1","").equals("1");
+                       return req.getQuery().getFirst("t1","").equals("1");
                }
        }
 
        public static class Test2Guard extends RestGuard {
                @Override /* RestGuard */
                public boolean isRequestAllowed(RestRequest req) {
-                       return req.getQuery("t2","").equals("2");
+                       return req.getQuery().getFirst("t2","").equals("2");
                }
        }
 
@@ -77,14 +77,14 @@ public class OverlappingMethodsResource extends 
RestServletDefault {
        public static class Test3aMatcher extends RestMatcher {
                @Override /* RestMatcher */
                public boolean matches(RestRequest req) {
-                       return req.getQuery("t1","").equals("1");
+                       return req.getQuery().getFirst("t1","").equals("1");
                }
        }
 
        public static class Test3bMatcher extends RestMatcher {
                @Override /* RestMatcher */
                public boolean matches(RestRequest req) {
-                       return req.getQuery("t2","").equals("2");
+                       return req.getQuery().getFirst("t2","").equals("2");
                }
        }
 

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/98a53eb3/juneau-rest-test/src/main/java/org/apache/juneau/rest/test/ParamsResource.java
----------------------------------------------------------------------
diff --git 
a/juneau-rest-test/src/main/java/org/apache/juneau/rest/test/ParamsResource.java
 
b/juneau-rest-test/src/main/java/org/apache/juneau/rest/test/ParamsResource.java
index 0c29593..cfd7f15 100644
--- 
a/juneau-rest-test/src/main/java/org/apache/juneau/rest/test/ParamsResource.java
+++ 
b/juneau-rest-test/src/main/java/org/apache/juneau/rest/test/ParamsResource.java
@@ -68,25 +68,25 @@ public class ParamsResource extends RestServletDefault {
        public void doGet3(HttpServletRequest reqx, HttpServletResponse resx, 
String foo, int bar) {
                RestRequest req = (RestRequest)reqx;
                RestResponse res = (RestResponse)resx;
-               res.setOutput("GET /get3/"+foo+"/"+bar+" 
remainder="+req.getPathRemainder());
+               res.setOutput("GET /get3/"+foo+"/"+bar+" 
remainder="+req.getPathMatch().getRemainder());
        }
 
        // Test method name with overlapping name, remainder allowed.
        @RestMethod(name="GET2")
        public void get2(RestRequest req, RestResponse res) {
-               res.setOutput("GET2 remainder="+req.getPathRemainder());
+               res.setOutput("GET2 
remainder="+req.getPathMatch().getRemainder());
        }
 
        // Default POST
        @RestMethod(name="POST")
        public void doPost(RestRequest req, RestResponse res) {
-               res.setOutput("POST remainder="+req.getPathRemainder());
+               res.setOutput("POST 
remainder="+req.getPathMatch().getRemainder());
        }
 
        // Bean parameter
        @RestMethod(name="POST", path="/person/{person}")
        public void doPost(RestRequest req, RestResponse res, Person p) {
-               res.setOutput("POST 
/person/{name="+p.name+",birthDate.year="+p.birthDate.get(Calendar.YEAR)+"} 
remainder="+req.getPathRemainder());
+               res.setOutput("POST 
/person/{name="+p.name+",birthDate.year="+p.birthDate.get(Calendar.YEAR)+"} 
remainder="+req.getPathMatch().getRemainder());
        }
 
        // Various primitive types
@@ -113,7 +113,7 @@ public class ParamsResource extends RestServletDefault {
        @RestMethod(name="GET", path="/testParamGet/*")
        public String testParamGet(RestRequest req, @Query("p1") String p1, 
@Query("p2") int p2) throws Exception {
                RequestQuery q = req.getQuery();
-               return "p1=["+p1+","+req.getQuery("p1")+","+q.get("p1", 
String.class)+"],p2=["+p2+","+q.getFirst("p2")+","+q.get("p2", int.class)+"]";
+               return 
"p1=["+p1+","+req.getQuery().getFirst("p1")+","+q.get("p1", 
String.class)+"],p2=["+p2+","+q.getFirst("p2")+","+q.get("p2", int.class)+"]";
        }
 
        
//====================================================================================================
@@ -122,7 +122,7 @@ public class ParamsResource extends RestServletDefault {
        @RestMethod(name="POST", path="/testParamPost/*")
        public String testParamPost(RestRequest req, @FormData("p1") String p1, 
@FormData("p2") int p2) throws Exception {
                RequestFormData f = req.getFormData();
-               return "p1=["+p1+","+req.getFormData("p1")+","+f.get("p1", 
String.class)+"],p2=["+p2+","+req.getFormData("p2")+","+f.get("p2", 
int.class)+"]";
+               return 
"p1=["+p1+","+req.getFormData().getFirst("p1")+","+f.get("p1", 
String.class)+"],p2=["+p2+","+req.getFormData().getFirst("p2")+","+f.get("p2", 
int.class)+"]";
        }
 
        
//====================================================================================================
@@ -131,7 +131,7 @@ public class ParamsResource extends RestServletDefault {
        @RestMethod(name="GET", path="/testQParamGet/*")
        public String testQParamGet(RestRequest req, @Query("p1") String p1, 
@Query("p2") int p2) throws Exception {
                RequestQuery q = req.getQuery();
-               return "p1=["+p1+","+req.getQuery("p1")+","+q.get("p1", 
String.class)+"],p2=["+p2+","+q.getFirst("p2")+","+q.get("p2", int.class)+"]";
+               return 
"p1=["+p1+","+req.getQuery().getFirst("p1")+","+q.get("p1", 
String.class)+"],p2=["+p2+","+q.getFirst("p2")+","+q.get("p2", int.class)+"]";
        }
 
        
//====================================================================================================
@@ -140,7 +140,7 @@ public class ParamsResource extends RestServletDefault {
        @RestMethod(name="POST", path="/testQParamPost/*")
        public String testQParamPost(RestRequest req, @Query("p1") String p1, 
@Query("p2") int p2) throws Exception {
                RequestQuery q = req.getQuery();
-               return "p1=["+p1+","+req.getQuery("p1")+","+q.get("p1", 
String.class)+"],p2=["+p2+","+q.getFirst("p2")+","+q.get("p2", int.class)+"]";
+               return 
"p1=["+p1+","+req.getQuery().getFirst("p1")+","+q.get("p1", 
String.class)+"],p2=["+p2+","+q.getFirst("p2")+","+q.get("p2", int.class)+"]";
        }
 
        
//====================================================================================================
@@ -149,7 +149,7 @@ public class ParamsResource extends RestServletDefault {
        @RestMethod(name="GET", path="/testPlainParamGet/*")
        public String testPlainParamGet(RestRequest req, 
@Query(value="p1",format="PLAIN") String p1) throws Exception {
                RequestQuery q = req.getQuery();
-               return "p1=["+p1+","+req.getQuery("p1")+","+q.get("p1", 
String.class)+"]";
+               return 
"p1=["+p1+","+req.getQuery().getFirst("p1")+","+q.get("p1", String.class)+"]";
        }
 
        
//====================================================================================================
@@ -158,7 +158,7 @@ public class ParamsResource extends RestServletDefault {
        @RestMethod(name="POST", path="/testPlainParamPost/*")
        public String testPlainParamPost(RestRequest req, 
@FormData(value="p1",format="PLAIN") String p1) throws Exception {
                RequestFormData f = req.getFormData();
-               return "p1=["+p1+","+req.getFormData("p1")+","+f.get("p1", 
String.class)+"]";
+               return 
"p1=["+p1+","+req.getFormData().getFirst("p1")+","+f.get("p1", 
String.class)+"]";
        }
 
        
//====================================================================================================
@@ -167,7 +167,7 @@ public class ParamsResource extends RestServletDefault {
        @RestMethod(name="GET", path="/testPlainQParamGet/*")
        public String testPlainQParamGet(RestRequest req, 
@Query(value="p1",format="PLAIN") String p1) throws Exception {
                RequestQuery q = req.getQuery();
-               return "p1=["+p1+","+req.getQuery("p1")+","+q.get("p1", 
String.class)+"]";
+               return 
"p1=["+p1+","+req.getQuery().getFirst("p1")+","+q.get("p1", String.class)+"]";
        }
 
        
//====================================================================================================
@@ -176,7 +176,7 @@ public class ParamsResource extends RestServletDefault {
        @RestMethod(name="POST", path="/testPlainQParamPost/*")
        public String testPlainQParamPost(RestRequest req, 
@Query(value="p1",format="PLAIN") String p1) throws Exception {
                RequestQuery q = req.getQuery();
-               return "p1=["+p1+","+req.getQuery("p1")+","+q.get("p1", 
String.class)+"]";
+               return 
"p1=["+p1+","+req.getQuery().getFirst("p1")+","+q.get("p1", String.class)+"]";
        }
 
        
//====================================================================================================

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/98a53eb3/juneau-rest-test/src/main/java/org/apache/juneau/rest/test/PathsResource.java
----------------------------------------------------------------------
diff --git 
a/juneau-rest-test/src/main/java/org/apache/juneau/rest/test/PathsResource.java 
b/juneau-rest-test/src/main/java/org/apache/juneau/rest/test/PathsResource.java
index c0fc94f..3621c59 100644
--- 
a/juneau-rest-test/src/main/java/org/apache/juneau/rest/test/PathsResource.java
+++ 
b/juneau-rest-test/src/main/java/org/apache/juneau/rest/test/PathsResource.java
@@ -59,8 +59,8 @@ public class PathsResource extends RestServletDefault {
                        .append("pathInfo", req.getPathInfo())
                        .append("pathInfoUndecoded", req.getPathInfoUndecoded())
                        .append("pathInfoParts", req.getPathInfoParts())
-                       .append("pathRemainder", req.getPathRemainder())
-                       .append("pathRemainderUndecoded", 
req.getPathRemainderUndecoded())
+                       .append("pathRemainder", 
req.getPathMatch().getRemainder())
+                       .append("pathRemainderUndecoded", 
req.getPathMatch().getRemainderUndecoded())
                        .append("requestURI", req.getRequestURI())
                        .append("requestParentURI", req.getRequestParentURI())
                        .append("requestURL", req.getRequestURL())

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/98a53eb3/juneau-rest-test/src/main/java/org/apache/juneau/rest/test/UrisResource.java
----------------------------------------------------------------------
diff --git 
a/juneau-rest-test/src/main/java/org/apache/juneau/rest/test/UrisResource.java 
b/juneau-rest-test/src/main/java/org/apache/juneau/rest/test/UrisResource.java
index 8de0852..b5579d2 100644
--- 
a/juneau-rest-test/src/main/java/org/apache/juneau/rest/test/UrisResource.java
+++ 
b/juneau-rest-test/src/main/java/org/apache/juneau/rest/test/UrisResource.java
@@ -106,7 +106,7 @@ public class UrisResource extends RestServletDefault {
                ObjectMap m = new ObjectMap();
                m.put("contextPath", req.getContextPath());
                m.put("pathInfo", req.getPathInfo());
-               m.put("pathRemainder", req.getPathRemainder());
+               m.put("pathRemainder", req.getPathMatch().getRemainder());
                m.put("pathTranslated", req.getPathTranslated());
                m.put("requestParentURI", req.getRequestParentURI());
                m.put("requestURI", req.getRequestURI());

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/98a53eb3/juneau-rest/src/main/java/org/apache/juneau/rest/CallMethod.java
----------------------------------------------------------------------
diff --git a/juneau-rest/src/main/java/org/apache/juneau/rest/CallMethod.java 
b/juneau-rest/src/main/java/org/apache/juneau/rest/CallMethod.java
index 4fe77de..869684c 100644
--- a/juneau-rest/src/main/java/org/apache/juneau/rest/CallMethod.java
+++ b/juneau-rest/src/main/java/org/apache/juneau/rest/CallMethod.java
@@ -658,10 +658,11 @@ class CallMethod implements Comparable<CallMethod>  {
                if (patternVals.length > pathPattern.getVars().length)
                        remainder = patternVals[pathPattern.getVars().length];
                for (int i = 0; i < pathPattern.getVars().length; i++)
-                       req.setPathParameter(pathPattern.getVars()[i], 
patternVals[i]);
-
+                       req.getPathMatch().put(pathPattern.getVars()[i], 
patternVals[i]);
+               req.getPathMatch().setRemainder(remainder);
+               
                ObjectMap requestProperties = 
createRequestProperties(properties, req);
-               req.init(method, remainder, requestProperties, 
defaultRequestHeaders, defaultCharset, serializers, parsers, urlEncodingParser, 
encoders, pageTitle, pageText, pageLinks);
+               req.init(method, requestProperties, defaultRequestHeaders, 
defaultCharset, serializers, parsers, urlEncodingParser, encoders, pageTitle, 
pageText, pageLinks);
                res.init(requestProperties, defaultCharset, serializers, 
urlEncodingSerializer, encoders);
 
                // Class-level guards
@@ -753,11 +754,11 @@ class CallMethod implements Comparable<CallMethod>  {
                                                String prefix = k.substring(0, 
k.indexOf('.'));
                                                String remainder = 
k.substring(k.indexOf('.')+1);
                                                if ("path".equals(prefix))
-                                                       return 
req.getPathParameter(remainder);
+                                                       return 
req.getPathMatch().get(remainder);
                                                if ("query".equals(prefix))
-                                                       return 
req.getQuery(remainder);
+                                                       return 
req.getQuery().get(remainder);
                                                if ("formData".equals(prefix))
-                                                       return 
req.getFormData(remainder);
+                                                       return 
req.getFormData().get(remainder);
                                                if ("header".equals(prefix))
                                                        return 
req.getHeader(remainder);
                                        }
@@ -792,7 +793,7 @@ class CallMethod implements Comparable<CallMethod>  {
                                                return req.getPageText();
                                        if 
(k.equals(HtmlDocSerializerContext.HTMLDOC_links))
                                                return req.getPageLinks();
-                                       o = req.getPathParameter(k);
+                                       o = req.getPathMatch().get(k);
                                        if (o == null)
                                                o = req.getHeader(k);
                                }

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/98a53eb3/juneau-rest/src/main/java/org/apache/juneau/rest/RequestBody.java
----------------------------------------------------------------------
diff --git a/juneau-rest/src/main/java/org/apache/juneau/rest/RequestBody.java 
b/juneau-rest/src/main/java/org/apache/juneau/rest/RequestBody.java
index 1b509b4..5663bf3 100644
--- a/juneau-rest/src/main/java/org/apache/juneau/rest/RequestBody.java
+++ b/juneau-rest/src/main/java/org/apache/juneau/rest/RequestBody.java
@@ -85,10 +85,10 @@ public class RequestBody {
        /**
         * Reads the input from the HTTP request as JSON, XML, or HTML and 
converts the input to a POJO.
         * <p>
-        * If {@code allowHeaderParams} init parameter is <jk>true</jk>, then 
first looks for {@code &body=xxx} in the URL 
+        * If {@code allowHeaderParams} init parameter is <jk>true</jk>, then 
first looks for {@code &body=xxx} in the URL
         * query string.
         * <p>
-        * If type is <jk>null</jk> or <code>Object.<jk>class</jk></code>, then 
the actual type will be determined 
+        * If type is <jk>null</jk> or <code>Object.<jk>class</jk></code>, then 
the actual type will be determined
         * automatically based on the following input:
         * <table class='styled'>
         *      <tr><th>Type</th><th>JSON input</th><th>XML 
input</th><th>Return type</th></tr>
@@ -130,32 +130,32 @@ public class RequestBody {
         *      </tr>
         * </table>
         * <p>
-        * Refer to <a class="doclink" 
href="../../../../overview-summary.html#Core.PojoCategories">POJO 
Categories</a> for 
+        * Refer to <a class="doclink" 
href="../../../../overview-summary.html#Core.PojoCategories">POJO 
Categories</a> for
         * a complete definition of supported POJOs.
         * <p>
         * <h5 class='section'>Examples:</h5>
         * <p class='bcode'>
         *      <jc>// Parse into an integer.</jc>
-        *      <jk>int</jk> body = req.getBody(<jk>int</jk>.<jk>class</jk>);
+        *      <jk>int</jk> body = 
req.getBody().asType(<jk>int</jk>.<jk>class</jk>);
         *
         *      <jc>// Parse into an int array.</jc>
-        *      <jk>int</jk>[] body = 
req.getBody(<jk>int</jk>[].<jk>class</jk>);
+        *      <jk>int</jk>[] body = 
req.getBody().asType(<jk>int</jk>[].<jk>class</jk>);
 
         *      <jc>// Parse into a bean.</jc>
-        *      MyBean body = req.getBody(MyBean.<jk>class</jk>);
+        *      MyBean body = req.getBody().asType(MyBean.<jk>class</jk>);
         *
         *      <jc>// Parse into a linked-list of objects.</jc>
-        *      List body = req.getBody(LinkedList.<jk>class</jk>);
+        *      List body = req.getBody().asType(LinkedList.<jk>class</jk>);
         *
         *      <jc>// Parse into a map of object keys/values.</jc>
-        *      Map body = req.getBody(TreeMap.<jk>class</jk>);
+        *      Map body = req.getBody().asType(TreeMap.<jk>class</jk>);
         * </p>
         *
         * @param type The class type to instantiate.
         * @param <T> The class type to instantiate.
         * @return The input parsed to a POJO.
         * @throws IOException If a problem occurred trying to read from the 
reader.
-        * @throws ParseException If the input contains a syntax error or is 
malformed for the requested {@code Accept} 
+        * @throws ParseException If the input contains a syntax error or is 
malformed for the requested {@code Accept}
         * header or is not valid for the specified type.
         */
        public <T> T asType(Class<T> type) throws IOException, ParseException {
@@ -168,23 +168,23 @@ public class RequestBody {
         * <h5 class='section'>Examples:</h5>
         * <p class='bcode'>
         *      <jc>// Parse into a linked-list of strings.</jc>
-        *      List&lt;String&gt; body = 
req.getBody(LinkedList.<jk>class</jk>, String.<jk>class</jk>);
+        *      List&lt;String&gt; body = 
req.getBody().asType(LinkedList.<jk>class</jk>, String.<jk>class</jk>);
         *
         *      <jc>// Parse into a linked-list of linked-lists of strings.</jc>
-        *      List&lt;List&lt;String&gt;&gt; body = 
req.getBody(LinkedList.<jk>class</jk>, LinkedList.<jk>class</jk>, 
String.<jk>class</jk>);
+        *      List&lt;List&lt;String&gt;&gt; body = 
req.getBody().asType(LinkedList.<jk>class</jk>, LinkedList.<jk>class</jk>, 
String.<jk>class</jk>);
         *
         *      <jc>// Parse into a map of string keys/values.</jc>
-        *      Map&lt;String,String&gt; body = 
req.getBody(TreeMap.<jk>class</jk>, String.<jk>class</jk>, 
String.<jk>class</jk>);
+        *      Map&lt;String,String&gt; body = 
req.getBody().asType(TreeMap.<jk>class</jk>, String.<jk>class</jk>, 
String.<jk>class</jk>);
         *
         *      <jc>// Parse into a map containing string keys and values of 
lists containing beans.</jc>
-        *      Map&lt;String,List&lt;MyBean&gt;&gt; body = 
req.getBody(TreeMap.<jk>class</jk>, String.<jk>class</jk>, List.<jk>class</jk>, 
MyBean.<jk>class</jk>);
+        *      Map&lt;String,List&lt;MyBean&gt;&gt; body = 
req.getBody().asType(TreeMap.<jk>class</jk>, String.<jk>class</jk>, 
List.<jk>class</jk>, MyBean.<jk>class</jk>);
         * </p>
         *
         * @param type The type of object to create.
-        *      <br>Can be any of the following: {@link ClassMeta}, {@link 
Class}, {@link ParameterizedType}, 
+        *      <br>Can be any of the following: {@link ClassMeta}, {@link 
Class}, {@link ParameterizedType},
         *      {@link GenericArrayType}
         * @param args The type arguments of the class if it's a collection or 
map.
-        *      <br>Can be any of the following: {@link ClassMeta}, {@link 
Class}, {@link ParameterizedType}, 
+        *      <br>Can be any of the following: {@link ClassMeta}, {@link 
Class}, {@link ParameterizedType},
         *      {@link GenericArrayType}
         *      <br>Ignored if the main type is not a map or collection.
         * @param <T> The class type to instantiate.
@@ -197,7 +197,7 @@ public class RequestBody {
        /**
         * Returns the HTTP body content as a plain string.
         * <p>
-        * If {@code allowHeaderParams} init parameter is true, then first 
looks for {@code &body=xxx} in the URL query 
+        * If {@code allowHeaderParams} init parameter is true, then first 
looks for {@code &body=xxx} in the URL query
         * string.
         *
         * @return The incoming input from the connection as a plain string.
@@ -224,7 +224,7 @@ public class RequestBody {
        /**
         * Returns the HTTP body content as a {@link Reader}.
         * <p>
-        * If {@code allowHeaderParams} init parameter is true, then first 
looks for {@code &body=xxx} in the URL query 
+        * If {@code allowHeaderParams} init parameter is true, then first 
looks for {@code &body=xxx} in the URL query
         * string.
         * <p>
         * Automatically handles GZipped input streams.

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/98a53eb3/juneau-rest/src/main/java/org/apache/juneau/rest/RequestPathMatch.java
----------------------------------------------------------------------
diff --git 
a/juneau-rest/src/main/java/org/apache/juneau/rest/RequestPathMatch.java 
b/juneau-rest/src/main/java/org/apache/juneau/rest/RequestPathMatch.java
new file mode 100644
index 0000000..de40e53
--- /dev/null
+++ b/juneau-rest/src/main/java/org/apache/juneau/rest/RequestPathMatch.java
@@ -0,0 +1,213 @@
+// 
***************************************************************************************************************************
+// * 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.StringUtils.*;
+
+import java.lang.reflect.*;
+import java.util.*;
+
+import org.apache.juneau.*;
+import org.apache.juneau.parser.*;
+import org.apache.juneau.urlencoding.*;
+
+/**
+ * Contains information about the matched path on the HTTP request.
+ * <p>
+ * Provides access to the matched path variables and path match remainder.
+ */
+@SuppressWarnings("unchecked")
+public class RequestPathMatch extends TreeMap<String,String> {
+       private static final long serialVersionUID = 1L;
+
+       private UrlEncodingParser parser;
+       private BeanSession beanSession;
+       private String remainder;
+
+       RequestPathMatch() {
+               super(String.CASE_INSENSITIVE_ORDER);
+       }
+
+       RequestPathMatch setParser(UrlEncodingParser parser) {
+               this.parser = parser;
+               return this;
+       }
+
+       RequestPathMatch setBeanSession(BeanSession beanSession) {
+               this.beanSession = beanSession;
+               return this;
+       }
+
+       RequestPathMatch setRemainder(String remainder) {
+               this.remainder = remainder;
+               return this;
+       }
+
+       /**
+        * Sets a request query parameter value.
+        *
+        * @param name The parameter name.
+        * @param value The parameter value.
+        */
+       public void put(String name, Object value) {
+               put(name, value);
+       }
+
+       /**
+        * Returns the specified path parameter converted to a POJO.
+        * <p>
+        * The type can be any POJO type convertable from a <code>String</code> 
(See <a class="doclink"
+        * href="package-summary.html#PojosConvertableFromString">POJOs 
Convertable From Strings</a>).
+        * <p>
+        * <h5 class='section'>Examples:</h5>
+        * <p class='bcode'>
+        *      <jc>// Parse into an integer.</jc>
+        *      <jk>int</jk> myparam = req.getPathParameter(<js>"myparam"</js>, 
<jk>int</jk>.<jk>class</jk>);
+        *
+        *      <jc>// Parse into an int array.</jc>
+        *      <jk>int</jk>[] myparam = 
req.getPathParameter(<js>"myparam"</js>, <jk>int</jk>[].<jk>class</jk>);
+
+        *      <jc>// Parse into a bean.</jc>
+        *      MyBean myparam = req.getPathParameter(<js>"myparam"</js>, 
MyBean.<jk>class</jk>);
+        *
+        *      <jc>// Parse into a linked-list of objects.</jc>
+        *      List myparam = req.getPathParameter(<js>"myparam"</js>, 
LinkedList.<jk>class</jk>);
+        *
+        *      <jc>// Parse into a map of object keys/values.</jc>
+        *      Map myparam = req.getPathParameter(<js>"myparam"</js>, 
TreeMap.<jk>class</jk>);
+        * </p>
+        *
+        * @param name The attribute name.
+        * @param type The class type to convert the attribute value to.
+        * @param <T> The class type to convert the attribute value to.
+        * @return The attribute value converted to the specified class type.
+        * @throws ParseException
+        */
+       public <T> T get(String name, Class<T> type) throws ParseException {
+               return parse(name, beanSession.getClassMeta(type));
+       }
+
+       /**
+        * Returns the specified path parameter converted to a POJO.
+        * <p>
+        * The type can be any POJO type convertable from a <code>String</code> 
(See <a class="doclink" 
href="package-summary.html#PojosConvertableFromString">POJOs Convertable From 
Strings</a>).
+        * <p>
+        * Use this method if you want to parse into a parameterized 
<code>Map</code>/<code>Collection</code> object.
+        * <p>
+        * <h5 class='section'>Examples:</h5>
+        * <p class='bcode'>
+        *      <jc>// Parse into a linked-list of strings.</jc>
+        *      List&lt;String&gt; myparam = 
req.getPathParameter(<js>"myparam"</js>, LinkedList.<jk>class</jk>, 
String.<jk>class</jk>);
+        *
+        *      <jc>// Parse into a linked-list of linked-lists of strings.</jc>
+        *      List&lt;List&lt;String&gt;&gt; myparam = 
req.getPathParameter(<js>"myparam"</js>, LinkedList.<jk>class</jk>, 
LinkedList.<jk>class</jk>, String.<jk>class</jk>);
+        *
+        *      <jc>// Parse into a map of string keys/values.</jc>
+        *      Map&lt;String,String&gt; myparam = 
req.getPathParameter(<js>"myparam"</js>, TreeMap.<jk>class</jk>, 
String.<jk>class</jk>, String.<jk>class</jk>);
+        *
+        *      <jc>// Parse into a map containing string keys and values of 
lists containing beans.</jc>
+        *      Map&lt;String,List&lt;MyBean&gt;&gt; myparam = 
req.getPathParameter(<js>"myparam"</js>, TreeMap.<jk>class</jk>, 
String.<jk>class</jk>, List.<jk>class</jk>, MyBean.<jk>class</jk>);
+        * </p>
+        *
+        * @param name The attribute name.
+        * @param type The type of object to create.
+        *      <br>Can be any of the following: {@link ClassMeta}, {@link 
Class}, {@link ParameterizedType}, {@link GenericArrayType}
+        * @param args The type arguments of the class if it's a collection or 
map.
+        *      <br>Can be any of the following: {@link ClassMeta}, {@link 
Class}, {@link ParameterizedType}, {@link GenericArrayType}
+        *      <br>Ignored if the main type is not a map or collection.
+        * @param <T> The class type to convert the attribute value to.
+        * @return The attribute value converted to the specified class type.
+        * @throws ParseException
+        */
+       public <T> T get(String name, Type type, Type...args) throws 
ParseException {
+               return (T)parse(name, beanSession.getClassMeta(type, args));
+       }
+
+       /* Workhorse method */
+       <T> T parse(String name, ClassMeta<T> cm) throws ParseException {
+               Object attr = get(name);
+               T t = null;
+               if (attr != null)
+                       t = parser.parsePart(attr.toString(), cm);
+               if (t == null && cm.isPrimitive())
+                       return cm.getPrimitiveDefault();
+               return t;
+       }
+
+       /**
+        * Returns the decoded remainder of the URL following any path pattern 
matches.
+        * <p>
+        * The behavior of path remainder is shown below given the path pattern 
"/foo/*":
+        * <p>
+        * <table class='styled'>
+        *      <tr>
+        *              <th>URL</th>
+        *              <th>Path Remainder</th>
+        *      </tr>
+        *      <tr>
+        *              <td><code>/foo</code></td>
+        *              <td><jk>null</jk></td>
+        *      </tr>
+        *      <tr>
+        *              <td><code>/foo/</code></td>
+        *              <td><js>""</js></td>
+        *      </tr>
+        *      <tr>
+        *              <td><code>/foo//</code></td>
+        *              <td><js>"/"</js></td>
+        *      </tr>
+        *      <tr>
+        *              <td><code>/foo///</code></td>
+        *              <td><js>"//"</js></td>
+        *      </tr>
+        *      <tr>
+        *              <td><code>/foo/a/b</code></td>
+        *              <td><js>"a/b"</js></td>
+        *      </tr>
+        *      <tr>
+        *              <td><code>/foo//a/b/</code></td>
+        *              <td><js>"/a/b/"</js></td>
+        *      </tr>
+        *      <tr>
+        *              <td><code>/foo/a%2Fb</code></td>
+        *              <td><js>"a/b"</js></td>
+        *      </tr>
+        * </table>
+        *
+        * <h5 class='section'>Example:</h5>
+        * <p class='bcode'>
+        *      <jc>// REST method</jc>
+        *      
<ja>@RestMethod</ja>(name=<js>"GET"</js>,path=<js>"/foo/{bar}/*"</js>)
+        *      <jk>public</jk> String doGetById(RequestPathParams pathParams, 
<jk>int</jk> bar) {
+        *              <jk>return</jk> pathParams.getRemainder();
+        *      }
+        *
+        *      <jc>// Prints "path/remainder"</jc>
+        *      <jk>new</jk> RestCall(servletPath + 
<js>"/foo/123/path/remainder"</js>).connect();
+        * </p>
+        *
+        * @return The path remainder string.
+        */
+       public String getRemainder() {
+               return urlDecode(remainder);
+       }
+
+       /**
+        * Same as {@link #getRemainder()} but doesn't decode characters.
+        *
+        * @return The undecoded path remainder.
+        */
+       public String getRemainderUndecoded() {
+               return remainder;
+       }
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/98a53eb3/juneau-rest/src/main/java/org/apache/juneau/rest/RequestPathParams.java
----------------------------------------------------------------------
diff --git 
a/juneau-rest/src/main/java/org/apache/juneau/rest/RequestPathParams.java 
b/juneau-rest/src/main/java/org/apache/juneau/rest/RequestPathParams.java
deleted file mode 100644
index 8a12a0e..0000000
--- a/juneau-rest/src/main/java/org/apache/juneau/rest/RequestPathParams.java
+++ /dev/null
@@ -1,137 +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.lang.reflect.*;
-import java.util.*;
-
-import org.apache.juneau.*;
-import org.apache.juneau.parser.*;
-import org.apache.juneau.urlencoding.*;
-
-/**
- * Represents the path parameters on an HTTP request.
- */
-@SuppressWarnings("unchecked")
-public class RequestPathParams extends TreeMap<String,String> {
-       private static final long serialVersionUID = 1L;
-
-       private UrlEncodingParser parser;
-       private BeanSession beanSession;
-
-       RequestPathParams() {
-               super(String.CASE_INSENSITIVE_ORDER);
-       }
-
-       RequestPathParams setParser(UrlEncodingParser parser) {
-               this.parser = parser;
-               return this;
-       }
-
-       RequestPathParams setBeanSession(BeanSession beanSession) {
-               this.beanSession = beanSession;
-               return this;
-       }
-
-       /**
-        * Sets a request query parameter value.
-        *
-        * @param name The parameter name.
-        * @param value The parameter value.
-        */
-       public void put(String name, Object value) {
-               put(name, value);
-       }
-
-       /**
-        * Returns the specified path parameter converted to a POJO.
-        * <p>
-        * The type can be any POJO type convertable from a <code>String</code> 
(See <a class="doclink" 
-        * href="package-summary.html#PojosConvertableFromString">POJOs 
Convertable From Strings</a>).
-        * <p>
-        * <h5 class='section'>Examples:</h5>
-        * <p class='bcode'>
-        *      <jc>// Parse into an integer.</jc>
-        *      <jk>int</jk> myparam = req.getPathParameter(<js>"myparam"</js>, 
<jk>int</jk>.<jk>class</jk>);
-        *
-        *      <jc>// Parse into an int array.</jc>
-        *      <jk>int</jk>[] myparam = 
req.getPathParameter(<js>"myparam"</js>, <jk>int</jk>[].<jk>class</jk>);
-
-        *      <jc>// Parse into a bean.</jc>
-        *      MyBean myparam = req.getPathParameter(<js>"myparam"</js>, 
MyBean.<jk>class</jk>);
-        *
-        *      <jc>// Parse into a linked-list of objects.</jc>
-        *      List myparam = req.getPathParameter(<js>"myparam"</js>, 
LinkedList.<jk>class</jk>);
-        *
-        *      <jc>// Parse into a map of object keys/values.</jc>
-        *      Map myparam = req.getPathParameter(<js>"myparam"</js>, 
TreeMap.<jk>class</jk>);
-        * </p>
-        *
-        * @param name The attribute name.
-        * @param type The class type to convert the attribute value to.
-        * @param <T> The class type to convert the attribute value to.
-        * @return The attribute value converted to the specified class type.
-        * @throws ParseException
-        */
-       public <T> T get(String name, Class<T> type) throws ParseException {
-               return parse(name, beanSession.getClassMeta(type));
-       }
-
-       /**
-        * Returns the specified path parameter converted to a POJO.
-        * <p>
-        * The type can be any POJO type convertable from a <code>String</code> 
(See <a class="doclink" 
href="package-summary.html#PojosConvertableFromString">POJOs Convertable From 
Strings</a>).
-        * <p>
-        * Use this method if you want to parse into a parameterized 
<code>Map</code>/<code>Collection</code> object.
-        * <p>
-        * <h5 class='section'>Examples:</h5>
-        * <p class='bcode'>
-        *      <jc>// Parse into a linked-list of strings.</jc>
-        *      List&lt;String&gt; myparam = 
req.getPathParameter(<js>"myparam"</js>, LinkedList.<jk>class</jk>, 
String.<jk>class</jk>);
-        *
-        *      <jc>// Parse into a linked-list of linked-lists of strings.</jc>
-        *      List&lt;List&lt;String&gt;&gt; myparam = 
req.getPathParameter(<js>"myparam"</js>, LinkedList.<jk>class</jk>, 
LinkedList.<jk>class</jk>, String.<jk>class</jk>);
-        *
-        *      <jc>// Parse into a map of string keys/values.</jc>
-        *      Map&lt;String,String&gt; myparam = 
req.getPathParameter(<js>"myparam"</js>, TreeMap.<jk>class</jk>, 
String.<jk>class</jk>, String.<jk>class</jk>);
-        *
-        *      <jc>// Parse into a map containing string keys and values of 
lists containing beans.</jc>
-        *      Map&lt;String,List&lt;MyBean&gt;&gt; myparam = 
req.getPathParameter(<js>"myparam"</js>, TreeMap.<jk>class</jk>, 
String.<jk>class</jk>, List.<jk>class</jk>, MyBean.<jk>class</jk>);
-        * </p>
-        *
-        * @param name The attribute name.
-        * @param type The type of object to create.
-        *      <br>Can be any of the following: {@link ClassMeta}, {@link 
Class}, {@link ParameterizedType}, {@link GenericArrayType}
-        * @param args The type arguments of the class if it's a collection or 
map.
-        *      <br>Can be any of the following: {@link ClassMeta}, {@link 
Class}, {@link ParameterizedType}, {@link GenericArrayType}
-        *      <br>Ignored if the main type is not a map or collection.
-        * @param <T> The class type to convert the attribute value to.
-        * @return The attribute value converted to the specified class type.
-        * @throws ParseException
-        */
-       public <T> T get(String name, Type type, Type...args) throws 
ParseException {
-               return (T)parse(name, beanSession.getClassMeta(type, args));
-       }
-
-       /* Workhorse method */
-       <T> T parse(String name, ClassMeta<T> cm) throws ParseException {
-               Object attr = get(name);
-               T t = null;
-               if (attr != null)
-                       t = parser.parsePart(attr.toString(), cm);
-               if (t == null && cm.isPrimitive())
-                       return cm.getPrimitiveDefault();
-               return t;
-       }
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/98a53eb3/juneau-rest/src/main/java/org/apache/juneau/rest/RestParamDefaults.java
----------------------------------------------------------------------
diff --git 
a/juneau-rest/src/main/java/org/apache/juneau/rest/RestParamDefaults.java 
b/juneau-rest/src/main/java/org/apache/juneau/rest/RestParamDefaults.java
index dc29cc6..18d0e2f 100644
--- a/juneau-rest/src/main/java/org/apache/juneau/rest/RestParamDefaults.java
+++ b/juneau-rest/src/main/java/org/apache/juneau/rest/RestParamDefaults.java
@@ -538,7 +538,7 @@ class RestParamDefaults {
 
                @Override /* RestParam */
                public Object resolve(RestRequest req, RestResponse res) throws 
Exception {
-                       return req.getPathParams().get(name, type);
+                       return req.getPathMatch().get(name, type);
                }
        }
 
@@ -597,7 +597,7 @@ class RestParamDefaults {
                        if (multiPart)
                                return req.getFormData().getAll(name, type);
                        if (plainParams)
-                               return bs.convertToType(req.getFormData(name), 
bs.getClassMeta(type));
+                               return 
bs.convertToType(req.getFormData().getFirst(name), bs.getClassMeta(type));
                        return req.getFormData().get(name, type);
                }
        }
@@ -619,7 +619,7 @@ class RestParamDefaults {
                        if (multiPart)
                                return req.getQuery().getAll(name, type);
                        if (plainParams)
-                               return bs.convertToType(req.getQuery(name), 
bs.getClassMeta(type));
+                               return 
bs.convertToType(req.getQuery().getFirst(name), bs.getClassMeta(type));
                        return req.getQuery().get(name, type);
                }
        }
@@ -664,7 +664,7 @@ class RestParamDefaults {
 
                @Override /* RestParam */
                public Object resolve(RestRequest req, RestResponse res) throws 
Exception {
-                       return req.getPathRemainder();
+                       return req.getPathMatch().getRemainder();
                }
        }
 
@@ -905,12 +905,12 @@ class RestParamDefaults {
        static final class RequestPathParamsObject extends RestParam {
 
                protected RequestPathParamsObject() {
-                       super(OTHER, null, RequestPathParams.class);
+                       super(OTHER, null, RequestPathMatch.class);
                }
 
                @Override /* RestParam */
                public Object resolve(RestRequest req, RestResponse res) throws 
Exception {
-                       return req.getPathParams();
+                       return req.getPathMatch();
                }
        }
 

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/98a53eb3/juneau-rest/src/main/java/org/apache/juneau/rest/RestRequest.java
----------------------------------------------------------------------
diff --git a/juneau-rest/src/main/java/org/apache/juneau/rest/RestRequest.java 
b/juneau-rest/src/main/java/org/apache/juneau/rest/RestRequest.java
index dfced43..774fb5c 100644
--- a/juneau-rest/src/main/java/org/apache/juneau/rest/RestRequest.java
+++ b/juneau-rest/src/main/java/org/apache/juneau/rest/RestRequest.java
@@ -67,7 +67,6 @@ public final class RestRequest extends 
HttpServletRequestWrapper {
        private final RestContext context;
 
        private final String method;
-       private String pathRemainder;
        private RequestBody body;
        private Method javaMethod;
        private ObjectMap properties;
@@ -79,7 +78,7 @@ public final class RestRequest extends 
HttpServletRequestWrapper {
        private VarResolverSession varSession;
        private final RequestQuery queryParams;
        private RequestFormData formData;
-       private RequestPathParams pathParams;
+       private RequestPathMatch pathParams;
        private boolean isPost;
        private String servletURI, relativeServletURI;
        private String charset, defaultCharset;
@@ -111,7 +110,7 @@ public final class RestRequest extends 
HttpServletRequestWrapper {
                        // Can be overridden through a "method" GET attribute.
                        String _method = super.getMethod();
 
-                       String m = getQuery("method");
+                       String m = getQuery().getFirst("method");
                        if (context.allowMethodParam(m))
                                _method = m;
 
@@ -126,7 +125,7 @@ public final class RestRequest extends 
HttpServletRequestWrapper {
                        body = new RequestBody(this);
 
                        if (context.isAllowBodyParam()) {
-                               String b = getQuery("body");
+                               String b = getQuery().getFirst("body");
                                if (b != null) {
                                        headers.put("Content-Type", 
UonSerializer.DEFAULT.getResponseContentType());
                                        body.load(b.getBytes(IOUtils.UTF8));
@@ -136,9 +135,9 @@ public final class RestRequest extends 
HttpServletRequestWrapper {
                        if (context.isAllowHeaderParams())
                                headers.setQueryParams(queryParams);
 
-                       debug = "true".equals(getQuery("debug", "false")) || 
"true".equals(getHeader("Debug", "false"));
+                       debug = "true".equals(getQuery().getFirst("debug", 
"false")) || "true".equals(getHeaders().getFirst("Debug", "false"));
 
-                       this.pathParams = new RequestPathParams();
+                       this.pathParams = new RequestPathMatch();
 
                } catch (RestException e) {
                        throw e;
@@ -151,9 +150,8 @@ public final class RestRequest extends 
HttpServletRequestWrapper {
         * Called from RestServlet after a match has been made but before the 
guard or method invocation.
         */
        @SuppressWarnings("hiding")
-       final void init(Method javaMethod, String pathRemainder, ObjectMap 
properties, Map<String,String> mDefaultRequestHeaders, String defaultCharset, 
SerializerGroup mSerializers, ParserGroup mParsers, UrlEncodingParser 
mUrlEncodingParser, EncoderGroup encoders, String pageTitle, String pageText, 
String pageLinks) {
+       final void init(Method javaMethod, ObjectMap properties, 
Map<String,String> mDefaultRequestHeaders, String defaultCharset, 
SerializerGroup mSerializers, ParserGroup mParsers, UrlEncodingParser 
mUrlEncodingParser, EncoderGroup encoders, String pageTitle, String pageText, 
String pageLinks) {
                this.javaMethod = javaMethod;
-               this.pathRemainder = pathRemainder;
                this.properties = properties;
                this.urlEncodingParser = mUrlEncodingParser;
                this.beanSession = 
urlEncodingParser.getBeanContext().createSession();
@@ -238,35 +236,11 @@ public final class RestRequest extends 
HttpServletRequestWrapper {
                return headers;
        }
 
-       /**
-        * Convenience method for calling <code>getHeaders().put(name, 
value);</code>
-        *
-        * @param name The header name.
-        * @param value The header value.
-        */
-       public void setHeader(String name, Object value) {
-               getHeaders().put(name, value);
-       }
-
-       /**
-        * Convenience method for calling 
<code>getHeaders().getFirst(name);</code>
-        */
        @Override /* ServletRequest */
        public String getHeader(String name) {
                return getHeaders().getFirst(name);
        }
 
-       /**
-        * Convenience method for calling <code>getHeaders().getFirst(name, 
def);</code>
-        *
-        * @param name The HTTP header name.
-        * @param def The default value to return if the header value isn't 
found.
-        * @return The header value, or the default value if the header isn't 
present.
-        */
-       public String getHeader(String name, String def) {
-               return getHeaders().getFirst(name, def);
-       }
-
        @Override /* ServletRequest */
        public Enumeration<String> getHeaders(String name) {
                String[] v = headers.get(name);
@@ -360,36 +334,14 @@ public final class RestRequest extends 
HttpServletRequestWrapper {
        }
 
        /**
-        * Convenience method for calling <code>getQueryParams().put(name, 
value);</code>.
-        *
-        * @param name The parameter name.
-        * @param value The parameter value.
-        */
-       public void setQuery(String name, Object value) {
-               queryParams.put(name, value);
-       }
-
-       /**
-        * Convenience method for calling 
<code>getQueryParams().getFirst(name);</code>
-        *
-        * @param name The URL parameter name.
-        * @return The parameter value, or <jk>null</jk> if parameter not 
specified or has no value (e.g. <js>"&amp;foo"</js>.
+        * Shortcut for calling <code>getQuery().getFirst(name)</code>.
+        * @param name The query parameter name.
+        * @return The query parameter value, or <jk>null<jk> if not found.
         */
        public String getQuery(String name) {
                return getQuery().getFirst(name);
        }
 
-       /**
-        * Convenience method for calling <code>getQueryParams().getFirst(name, 
def);</code>
-        *
-        * @param name The URL parameter name.
-        * @param def The default value.
-        * @return The parameter value, or the default value if parameter not 
specified or has no value (e.g. <js>"&amp;foo"</js>.
-        */
-       public String getQuery(String name, String def) {
-               return getQuery().getFirst(name, def);
-       }
-
 
        
//--------------------------------------------------------------------------------
        // Form data parameters
@@ -421,37 +373,15 @@ public final class RestRequest extends 
HttpServletRequestWrapper {
        }
 
        /**
-        * Convenience method for calling <code>getFormData().put(name, 
value);</code>.
-        *
-        * @param name The parameter name.
-        * @param value The parameter value.
-        */
-       public void setFormData(String name, Object value) {
-               getFormData().put(name, value);
-       }
-
-       /**
-        * Convenience method for calling 
<code>getFormData().getFirst(name);</code>.
-        *
+        * Shortcut for calling <code>getFormData().getFirst(name)</code>.
         * @param name The form data parameter name.
-        * @return The parameter value, or <jk>null</jk> if parameter does not 
exist.
+        * @return The form data parameter value, or <jk>null<jk> if not found.
         */
        public String getFormData(String name) {
                return getFormData().getFirst(name);
        }
 
-       /**
-        * Convenience method for calling <code>getFormData().getFirst(name, 
def);</code>.
-        *
-        * @param name The form data parameter name.
-        * @param def The default value.
-        * @return The parameter value, or the default value if <jk>null</jk> 
or empty.
-        */
-       public String getFormData(String name, String def) {
-               return getFormData().getFirst(name, def);
-       }
-
-
+       
        
//--------------------------------------------------------------------------------
        // Path parameters
        
//--------------------------------------------------------------------------------
@@ -461,30 +391,10 @@ public final class RestRequest extends 
HttpServletRequestWrapper {
         *
         * @return The URL-encoded form data from the request.
         */
-       public RequestPathParams getPathParams() {
+       public RequestPathMatch getPathMatch() {
                return pathParams;
        }
 
-       /**
-        * Convenience method for calling <code>getPathParams().put(name, 
value);</code>.
-        *
-        * @param name The parameter name.
-        * @param value The parameter value.
-        */
-       public void setPathParameter(String name, String value) {
-               pathParams.put(name, StringUtils.toString(value));
-       }
-
-       /**
-        * Convenience method for calling 
<code>getPathParams().get(name);</code>.
-        *
-        * @param name The parameter name.
-        * @return The parameter value, or <jk>null</jk> if path parameter not 
specified.
-        */
-       public String getPathParameter(String name) {
-               return pathParams.get(name);
-       }
-
 
        
//--------------------------------------------------------------------------------
        // Body methods
@@ -603,73 +513,6 @@ public final class RestRequest extends 
HttpServletRequestWrapper {
        }
 
        /**
-        * Returns the decoded remainder of the URL following any path pattern 
matches.
-        * <p>
-        * The behavior of path remainder is shown below given the path pattern 
"/foo/*":
-        * <p>
-        * <table class='styled'>
-        *      <tr>
-        *              <th>URL</th>
-        *              <th>Path Remainder</th>
-        *      </tr>
-        *      <tr>
-        *              <td><code>/foo</code></td>
-        *              <td><jk>null</jk></td>
-        *      </tr>
-        *      <tr>
-        *              <td><code>/foo/</code></td>
-        *              <td><js>""</js></td>
-        *      </tr>
-        *      <tr>
-        *              <td><code>/foo//</code></td>
-        *              <td><js>"/"</js></td>
-        *      </tr>
-        *      <tr>
-        *              <td><code>/foo///</code></td>
-        *              <td><js>"//"</js></td>
-        *      </tr>
-        *      <tr>
-        *              <td><code>/foo/a/b</code></td>
-        *              <td><js>"a/b"</js></td>
-        *      </tr>
-        *      <tr>
-        *              <td><code>/foo//a/b/</code></td>
-        *              <td><js>"/a/b/"</js></td>
-        *      </tr>
-        *      <tr>
-        *              <td><code>/foo/a%2Fb</code></td>
-        *              <td><js>"a/b"</js></td>
-        *      </tr>
-        * </table>
-        *
-        * <h5 class='section'>Example:</h5>
-        * <p class='bcode'>
-        *      <jc>// REST method</jc>
-        *      
<ja>@RestMethod</ja>(name=<js>"GET"</js>,path=<js>"/foo/{bar}/*"</js>)
-        *      <jk>public</jk> doGetById(RestServlet res, RestResponse res, 
<jk>int</jk> bar) {
-        *              System.<jsm>err</jsm>.println(res.getRemainder());
-        *      }
-        *
-        *      <jc>// Prints "path/remainder"</jc>
-        *      <jk>new</jk> RestCall(servletPath + 
<js>"/foo/123/path/remainder"</js>).connect();
-        * </p>
-        *
-        * @return The path remainder string.
-        */
-       public String getPathRemainder() {
-               return urlDecode(pathRemainder);
-       }
-
-       /**
-        * Same as {@link #getPathRemainder()} but doesn't decode characters.
-        *
-        * @return The undecoded path remainder.
-        */
-       public String getPathRemainderUndecoded() {
-               return pathRemainder;
-       }
-
-       /**
         * Returns the URI of the parent resource.
         * <p>
         * Trailing slashes in the path are ignored by this method.
@@ -935,7 +778,7 @@ public final class RestRequest extends 
HttpServletRequestWrapper {
         * @return <jk>true</jk> if {@code &amp;plainText=true} was specified 
as a URL parameter
         */
        public boolean isPlainText() {
-               return "true".equals(getQuery("plainText", "false"));
+               return "true".equals(getQuery().getFirst("plainText", "false"));
        }
 
        /**

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/98a53eb3/juneau-rest/src/main/java/org/apache/juneau/rest/annotation/Body.java
----------------------------------------------------------------------
diff --git 
a/juneau-rest/src/main/java/org/apache/juneau/rest/annotation/Body.java 
b/juneau-rest/src/main/java/org/apache/juneau/rest/annotation/Body.java
index db5dcbe..8641e60 100644
--- a/juneau-rest/src/main/java/org/apache/juneau/rest/annotation/Body.java
+++ b/juneau-rest/src/main/java/org/apache/juneau/rest/annotation/Body.java
@@ -35,7 +35,7 @@ import java.lang.annotation.*;
  * <p class='bcode'>
  *     <ja>@RestMethod</ja>(name=<js>"POST"</js>)
  *     <jk>public void</jk> doPostPerson(RestRequest req, RestResponse res) {
- *             Person person = req.getBody(Person.<jk>class</jk>);
+ *             Person person = req.getBody().asType(Person.<jk>class</jk>);
  *             ...
  *     }
  * </p>

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/98a53eb3/juneau-rest/src/main/java/org/apache/juneau/rest/converters/Introspectable.java
----------------------------------------------------------------------
diff --git 
a/juneau-rest/src/main/java/org/apache/juneau/rest/converters/Introspectable.java
 
b/juneau-rest/src/main/java/org/apache/juneau/rest/converters/Introspectable.java
index cf5f16d..f84368e 100644
--- 
a/juneau-rest/src/main/java/org/apache/juneau/rest/converters/Introspectable.java
+++ 
b/juneau-rest/src/main/java/org/apache/juneau/rest/converters/Introspectable.java
@@ -40,8 +40,8 @@ public final class Introspectable implements RestConverter {
        @Override /* RestConverter */
        @SuppressWarnings({"unchecked", "rawtypes"})
        public Object convert(RestRequest req, Object o, ClassMeta cm) throws 
RestException {
-               String method = req.getQuery("invokeMethod");
-               String args = req.getQuery("invokeArgs");
+               String method = req.getQuery().getFirst("invokeMethod");
+               String args = req.getQuery().getFirst("invokeArgs");
                if (method == null)
                        return o;
                try {

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/98a53eb3/juneau-rest/src/main/java/org/apache/juneau/rest/converters/Traversable.java
----------------------------------------------------------------------
diff --git 
a/juneau-rest/src/main/java/org/apache/juneau/rest/converters/Traversable.java 
b/juneau-rest/src/main/java/org/apache/juneau/rest/converters/Traversable.java
index 4816453..734a804 100644
--- 
a/juneau-rest/src/main/java/org/apache/juneau/rest/converters/Traversable.java
+++ 
b/juneau-rest/src/main/java/org/apache/juneau/rest/converters/Traversable.java
@@ -49,12 +49,12 @@ public final class Traversable implements RestConverter {
                if (o == null)
                        return null;
 
-               if (req.getPathRemainder() != null) {
+               if (req.getPathMatch().getRemainder() != null) {
                        try {
                                if (cm.getPojoSwap() != null)
                                        o = 
cm.getPojoSwap().swap(req.getBeanSession(), o);
                                PojoRest p = new PojoRest(o, 
req.getBody().getReaderParser());
-                               o = p.get(req.getPathRemainder());
+                               o = p.get(req.getPathMatch().getRemainder());
                        } catch (SerializeException e) {
                                throw new 
RestException(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e);
                        } catch (PojoRestException e) {

Reply via email to