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

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


The following commit(s) were added to refs/heads/master by this push:
     new ac54809  REST refactoring.
ac54809 is described below

commit ac548099580d30ddb95e4e4f559522c0472a1313
Author: JamesBognar <james.bog...@salesforce.com>
AuthorDate: Sun Jan 24 11:58:08 2021 -0500

    REST refactoring.
---
 .../org/apache/juneau/cp/BeanFactory_Test.java     |   4 +-
 .../java/org/apache/juneau/cp/BeanFactory.java     |  10 +
 .../build-overlay/pom.xml                          |  18 +-
 .../build-overlay/pom.xml                          |   4 +-
 .../juneau-examples-rest-springboot/pom.xml        |   4 +-
 .../apache/juneau/rest/mock/MockRestClient.java    |   2 +-
 juneau-rest/juneau-rest-server-springboot/pom.xml  |   2 +-
 .../rest/annotation/RestAnnotation_Test.java       |  27 +-
 .../rest/annotation/RestMethodAnnotation_Test.java |  10 +-
 .../juneau/rest/annotation/Rest_Context_Test.java  |   6 +-
 .../juneau/rest/annotation/Restx_Path_Test.java    |   6 +-
 .../main/java/org/apache/juneau/rest/RestCall.java |   2 +-
 ...RestMethodsBuilder.java => RestChildMatch.java} |  60 +--
 .../java/org/apache/juneau/rest/RestChildren.java  | 125 ++++++
 .../apache/juneau/rest/RestChildrenBuilder.java    |  92 +++++
 .../java/org/apache/juneau/rest/RestContext.java   | 450 ++++++++++++++++-----
 .../org/apache/juneau/rest/RestContextBuilder.java |  90 +++--
 .../org/apache/juneau/rest/RestMethodContext.java  |  67 ++-
 .../juneau/rest/RestMethodContextBuilder.java      |  58 ++-
 .../java/org/apache/juneau/rest/RestMethods.java   |  17 +-
 .../org/apache/juneau/rest/RestMethodsBuilder.java |  54 ++-
 .../java/org/apache/juneau/rest/RestServlet.java   |   4 +-
 .../org/apache/juneau/rest/annotation/Rest.java    |  64 +--
 .../juneau/rest/annotation/RestAnnotation.java     |  78 +++-
 .../apache/juneau/rest/annotation/RestMethod.java  |   4 +-
 .../rest/annotation/RestMethodAnnotation.java      |  18 +-
 pom.xml                                            |   2 +-
 27 files changed, 1020 insertions(+), 258 deletions(-)

diff --git 
a/juneau-core/juneau-core-utest/src/test/java/org/apache/juneau/cp/BeanFactory_Test.java
 
b/juneau-core/juneau-core-utest/src/test/java/org/apache/juneau/cp/BeanFactory_Test.java
index 1ddd4a7..17fd8c8 100644
--- 
a/juneau-core/juneau-core-utest/src/test/java/org/apache/juneau/cp/BeanFactory_Test.java
+++ 
b/juneau-core/juneau-core-utest/src/test/java/org/apache/juneau/cp/BeanFactory_Test.java
@@ -39,7 +39,7 @@ public class BeanFactory_Test {
                bf.addBean(A.class, new A());
                assertBoolean(bf.hasBean(A.class)).isTrue();
                assertObject(bf.getBean(A.class)).exists();
-               bf = new BeanFactory(bf, null);
+               bf = BeanFactory.of(bf);
                assertBoolean(bf.hasBean(A.class)).isTrue();
                assertObject(bf.getBean(A.class)).exists();
        }
@@ -270,7 +270,7 @@ public class BeanFactory_Test {
        public void d01b_createBean_construct_withArgs_inner() throws Exception 
{
                BeanFactory bf = new BeanFactory();
                assertThrown(()->bf.createBean(D1b.class)).stderr().is("Could 
not instantiate class "+CNAME+"$D1b: Public constructor found but could not 
find prerequisites: BeanFactory_Test,A.");
-               BeanFactory bf2 = new BeanFactory(null,this);
+               BeanFactory bf2 = BeanFactory.of(null,this);
                assertThrown(()->bf2.createBean(D1b.class)).stderr().is("Could 
not instantiate class "+CNAME+"$D1b: Public constructor found but could not 
find prerequisites: A.");
                bf2.addBean(A.class, new A());
                assertObject(bf2.createBean(D1b.class)).exists();
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/cp/BeanFactory.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/cp/BeanFactory.java
index 8b148af..e0b2bd7 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/cp/BeanFactory.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/cp/BeanFactory.java
@@ -61,6 +61,16 @@ public class BeanFactory {
        }
 
        /**
+        * Static creator.
+        *
+        * @param parent Parent bean factory.  Can be <jk>null</jk> if this is 
the root resource.
+        * @return A new {@link BeanFactory} object.
+        */
+       public static BeanFactory of(BeanFactory parent) {
+               return new BeanFactory(parent, null);
+       }
+
+       /**
         * Default constructor.
         */
        public BeanFactory() {
diff --git a/juneau-examples/juneau-examples-rest-jetty/build-overlay/pom.xml 
b/juneau-examples/juneau-examples-rest-jetty/build-overlay/pom.xml
index 19bc870..cdd1078 100644
--- a/juneau-examples/juneau-examples-rest-jetty/build-overlay/pom.xml
+++ b/juneau-examples/juneau-examples-rest-jetty/build-overlay/pom.xml
@@ -40,7 +40,7 @@
 
                <maven.javadoc.skip>true</maven.javadoc.skip>
                <derby.version>${derby.version}</derby.version>
-               
<springframework.version>${springframework.version}</springframework.version>
+               <springboot.version>${springboot.version}</springboot.version>
                <javax.inject.version>1</javax.inject.version>
                <juneau.version>${version}</juneau.version>
                <jena.version>${jena.version}</jena.version>
@@ -64,7 +64,7 @@
                        <artifactId>juneau-marshall-rdf</artifactId>
                        <version>\${juneau.version}</version>
                </dependency>
-                               
+
                <dependency>
                        <groupId>javax.inject</groupId>
                        <artifactId>javax.inject</artifactId>
@@ -88,11 +88,11 @@
                        <version>\${hibernate.version}</version>
                </dependency>
                <dependency>
-                   <groupId>xml-apis</groupId>
-                   <artifactId>xml-apis</artifactId>
-                   <version>\${xml.apis.version}</version>
+                       <groupId>xml-apis</groupId>
+                       <artifactId>xml-apis</artifactId>
+                       <version>\${xml.apis.version}</version>
                </dependency>
-               
+
                <!-- Optional RDF support -->
                <dependency>
                        <groupId>org.apache.jena</groupId>
@@ -131,11 +131,11 @@
                                        <target>1.8</target>
                                </configuration>
                        </plugin>
-                       
+
                        <plugin>
                                <groupId>org.apache.maven.plugins</groupId>
                                <artifactId>maven-resources-plugin</artifactId>
-                               <version>3.0.2</version>
+                               <version>3.0.2</version>
                                <executions>
                                        <execution>
                                                <id>package-config</id>
@@ -200,5 +200,5 @@
 
                </plugins>
        </build>
-       
+
 </project>
diff --git 
a/juneau-examples/juneau-examples-rest-springboot/build-overlay/pom.xml 
b/juneau-examples/juneau-examples-rest-springboot/build-overlay/pom.xml
index cf76288..ee67ba8 100644
--- a/juneau-examples/juneau-examples-rest-springboot/build-overlay/pom.xml
+++ b/juneau-examples/juneau-examples-rest-springboot/build-overlay/pom.xml
@@ -37,7 +37,7 @@
        <parent>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-parent</artifactId>
-               <version>${springframework.version}</version>
+               <version>2.4.2</version>
                <relativePath />
        </parent>
 
@@ -52,6 +52,7 @@
                
<javax.inject.version>${javax.inject.version}</javax.inject.version>
                <juneau.version>${version}</juneau.version>
                <jena.version>${jena.version}</jena.version>
+               <springboot.version>2.4.2</springboot.version>
        </properties>
 
        <dependencies>
@@ -140,6 +141,7 @@
                        <plugin>
                                <groupId>org.springframework.boot</groupId>
                                
<artifactId>spring-boot-maven-plugin</artifactId>
+                               <version>${springboot.version}</version>
                                <executions>
                                        <execution>
                                                <goals>
diff --git a/juneau-examples/juneau-examples-rest-springboot/pom.xml 
b/juneau-examples/juneau-examples-rest-springboot/pom.xml
index b9b1b79..e0b414c 100644
--- a/juneau-examples/juneau-examples-rest-springboot/pom.xml
+++ b/juneau-examples/juneau-examples-rest-springboot/pom.xml
@@ -37,7 +37,6 @@
                <!-- Java 8 required because Jetty requires it. -->
                <maven.compiler.source>1.8</maven.compiler.source>
                <maven.compiler.target>1.8</maven.compiler.target>
-               <springframework.version>2.0.1.RELEASE</springframework.version>
        </properties>
 
 
@@ -59,7 +58,7 @@
                <dependency>
                        <groupId>org.springframework.boot</groupId>
                        <artifactId>spring-boot-starter-web</artifactId>
-                       <version>${springframework.version}</version>
+                       <version>${springboot.version}</version>
                        <exclusions>
                                <exclusion>
                                        
<groupId>org.springframework.boot</groupId>
@@ -87,6 +86,7 @@
                        <plugin>
                                <groupId>org.springframework.boot</groupId>
                                
<artifactId>spring-boot-maven-plugin</artifactId>
+                               <version>${springboot.version}</version>
                                <executions>
                                        <execution>
                                                <goals>
diff --git 
a/juneau-rest/juneau-rest-mock/src/main/java/org/apache/juneau/rest/mock/MockRestClient.java
 
b/juneau-rest/juneau-rest-mock/src/main/java/org/apache/juneau/rest/mock/MockRestClient.java
index 1948382..775ef25 100644
--- 
a/juneau-rest/juneau-rest-mock/src/main/java/org/apache/juneau/rest/mock/MockRestClient.java
+++ 
b/juneau-rest/juneau-rest-mock/src/main/java/org/apache/juneau/rest/mock/MockRestClient.java
@@ -294,7 +294,7 @@ public class MockRestClient extends RestClient implements 
HttpClientConnection {
                        psb.set(MOCKRESTCLIENT_restBeanCtx, restBeanCtx);
 
                        if (servletPath == null)
-                               servletPath = 
toValidContextPath(restBeanCtx.getPath());
+                               servletPath = 
toValidContextPath(restBeanCtx.getFullPath());
 
                        rootUrl = rootUrl + emptyIfNull(contextPath) + 
emptyIfNull(servletPath);
 
diff --git a/juneau-rest/juneau-rest-server-springboot/pom.xml 
b/juneau-rest/juneau-rest-server-springboot/pom.xml
index f49dc04..a3da36f 100644
--- a/juneau-rest/juneau-rest-server-springboot/pom.xml
+++ b/juneau-rest/juneau-rest-server-springboot/pom.xml
@@ -39,7 +39,7 @@
         <dependency>
             <groupId>org.springframework.boot</groupId>
             <artifactId>spring-boot-starter-web</artifactId>
-            <version>${springframework.version}</version>
+            <version>${springboot.version}</version>
             <exclusions>
                 <exclusion>
                     <groupId>org.springframework.boot</groupId>
diff --git 
a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/RestAnnotation_Test.java
 
b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/RestAnnotation_Test.java
index 67fb3ab..7b43f6b 100644
--- 
a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/RestAnnotation_Test.java
+++ 
b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/RestAnnotation_Test.java
@@ -47,7 +47,7 @@ public class RestAnnotation_Test {
                .clientVersionHeader("clientVersionHeader")
                .config("config")
                .consumes("consumes")
-               .context(RestContext.class)
+               .contextClass(RestContext.class)
                .converters(RestConverter.class)
                .debug("debug")
                .debugOn("debugOn")
@@ -63,6 +63,7 @@ public class RestAnnotation_Test {
                .guards(RestGuard.class)
                .infoProvider(BasicRestInfoProvider.class)
                .maxInput("maxInput")
+               .methodContextClass(RestMethodContext.class)
                .messages("messages")
                .on("on")
                .onClass(RestAnnotation_Test.class)
@@ -73,6 +74,8 @@ public class RestAnnotation_Test {
                .produces("produces")
                .renderResponseStackTraces("renderResponseStackTraces")
                .responseHandlers(ResponseHandler.class)
+               .restChildrenClass(RestChildren.class)
+               .restMethodsClass(RestMethods.class)
                .restParams(RestParam.class)
                .roleGuard("roleGuard")
                .rolesDeclared("rolesDeclared")
@@ -98,7 +101,7 @@ public class RestAnnotation_Test {
                .clientVersionHeader("clientVersionHeader")
                .config("config")
                .consumes("consumes")
-               .context(RestContext.class)
+               .contextClass(RestContext.class)
                .converters(RestConverter.class)
                .debug("debug")
                .debugOn("debugOn")
@@ -114,6 +117,7 @@ public class RestAnnotation_Test {
                .guards(RestGuard.class)
                .infoProvider(BasicRestInfoProvider.class)
                .maxInput("maxInput")
+               .methodContextClass(RestMethodContext.class)
                .messages("messages")
                .on("on")
                .onClass(RestAnnotation_Test.class)
@@ -124,6 +128,8 @@ public class RestAnnotation_Test {
                .produces("produces")
                .renderResponseStackTraces("renderResponseStackTraces")
                .responseHandlers(ResponseHandler.class)
+               .restChildrenClass(RestChildren.class)
+               .restMethodsClass(RestMethods.class)
                .restParams(RestParam.class)
                .roleGuard("roleGuard")
                .rolesDeclared("rolesDeclared")
@@ -140,7 +146,7 @@ public class RestAnnotation_Test {
 
        @Test
        public void a01_basic() {
-               assertObject(a1).json().is(""
+               assertObject(a1).json().stderr().is(""
                        + "{"
                                + "allowedHeaderParams:'allowedHeaderParams',"
                                + "allowedMethodHeaders:'allowedMethodHeaders',"
@@ -151,7 +157,7 @@ public class RestAnnotation_Test {
                                + "clientVersionHeader:'clientVersionHeader',"
                                + "config:'config',"
                                + "consumes:['consumes'],"
-                               + 
"context:'org.apache.juneau.rest.RestContext',"
+                               + 
"contextClass:'org.apache.juneau.rest.RestContext',"
                                + 
"converters:['org.apache.juneau.rest.RestConverter'],"
                                + "debug:'debug',"
                                + "debugOn:'debugOn',"
@@ -169,6 +175,7 @@ public class RestAnnotation_Test {
                                + 
"infoProvider:'org.apache.juneau.rest.BasicRestInfoProvider',"
                                + "maxInput:'maxInput',"
                                + "messages:'messages',"
+                               + 
"methodContextClass:'org.apache.juneau.rest.RestMethodContext',"
                                + "on:['on'],"
                                + "onClass:['"+CNAME+"'],"
                                + "parsers:['org.apache.juneau.parser.Parser'],"
@@ -178,6 +185,8 @@ public class RestAnnotation_Test {
                                + "produces:['produces'],"
                                + 
"renderResponseStackTraces:'renderResponseStackTraces',"
                                + 
"responseHandlers:['org.apache.juneau.rest.ResponseHandler'],"
+                               + 
"restChildrenClass:'org.apache.juneau.rest.RestChildren',"
+                               + 
"restMethodsClass:'org.apache.juneau.rest.RestMethods',"
                                + 
"restParams:['org.apache.juneau.rest.RestParam'],"
                                + "roleGuard:'roleGuard',"
                                + "rolesDeclared:'rolesDeclared',"
@@ -248,7 +257,7 @@ public class RestAnnotation_Test {
                clientVersionHeader="clientVersionHeader",
                config="config",
                consumes="consumes",
-               context=RestContext.class,
+               contextClass=RestContext.class,
                converters=RestConverter.class,
                debug="debug",
                debugOn="debugOn",
@@ -264,6 +273,7 @@ public class RestAnnotation_Test {
                guards=RestGuard.class,
                infoProvider=BasicRestInfoProvider.class,
                maxInput="maxInput",
+               methodContextClass=RestMethodContext.class,
                messages="messages",
                on="on",
                onClass=RestAnnotation_Test.class,
@@ -274,6 +284,8 @@ public class RestAnnotation_Test {
                produces="produces",
                renderResponseStackTraces="renderResponseStackTraces",
                responseHandlers=ResponseHandler.class,
+               restChildrenClass=RestChildren.class,
+               restMethodsClass=RestMethods.class,
                restParams=RestParam.class,
                roleGuard="roleGuard",
                rolesDeclared="rolesDeclared",
@@ -301,7 +313,7 @@ public class RestAnnotation_Test {
                clientVersionHeader="clientVersionHeader",
                config="config",
                consumes="consumes",
-               context=RestContext.class,
+               contextClass=RestContext.class,
                converters=RestConverter.class,
                debug="debug",
                debugOn="debugOn",
@@ -317,6 +329,7 @@ public class RestAnnotation_Test {
                guards=RestGuard.class,
                infoProvider=BasicRestInfoProvider.class,
                maxInput="maxInput",
+               methodContextClass=RestMethodContext.class,
                messages="messages",
                on="on",
                onClass=RestAnnotation_Test.class,
@@ -327,6 +340,8 @@ public class RestAnnotation_Test {
                produces="produces",
                renderResponseStackTraces="renderResponseStackTraces",
                responseHandlers=ResponseHandler.class,
+               restChildrenClass=RestChildren.class,
+               restMethodsClass=RestMethods.class,
                restParams=RestParam.class,
                roleGuard="roleGuard",
                rolesDeclared="rolesDeclared",
diff --git 
a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/RestMethodAnnotation_Test.java
 
b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/RestMethodAnnotation_Test.java
index 3e46c26..e0b21c2 100644
--- 
a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/RestMethodAnnotation_Test.java
+++ 
b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/RestMethodAnnotation_Test.java
@@ -36,7 +36,7 @@ public class RestMethodAnnotation_Test {
        RestMethod a1 = RestMethodAnnotation.create()
                .clientVersion("clientVersion")
                .consumes("consumes")
-               .context(RestMethodContext.class)
+               .contextClass(RestMethodContext.class)
                .converters(RestConverter.class)
                .debug("debug")
                .defaultAccept("defaultAccept")
@@ -69,7 +69,7 @@ public class RestMethodAnnotation_Test {
        RestMethod a2 = RestMethodAnnotation.create()
                .clientVersion("clientVersion")
                .consumes("consumes")
-               .context(RestMethodContext.class)
+               .contextClass(RestMethodContext.class)
                .converters(RestConverter.class)
                .debug("debug")
                .defaultAccept("defaultAccept")
@@ -105,7 +105,7 @@ public class RestMethodAnnotation_Test {
                        + "{"
                                + "clientVersion:'clientVersion',"
                                + "consumes:['consumes'],"
-                               + 
"context:'org.apache.juneau.rest.RestMethodContext',"
+                               + 
"contextClass:'org.apache.juneau.rest.RestMethodContext',"
                                + 
"converters:['org.apache.juneau.rest.RestConverter'],"
                                + "debug:'debug',"
                                + "defaultAccept:'defaultAccept',"
@@ -181,7 +181,7 @@ public class RestMethodAnnotation_Test {
        @RestMethod(
                clientVersion="clientVersion",
                consumes="consumes",
-               context=RestMethodContext.class,
+               contextClass=RestMethodContext.class,
                converters=RestConverter.class,
                debug="debug",
                defaultAccept="defaultAccept",
@@ -216,7 +216,7 @@ public class RestMethodAnnotation_Test {
        @RestMethod(
                clientVersion="clientVersion",
                consumes="consumes",
-               context=RestMethodContext.class,
+               contextClass=RestMethodContext.class,
                converters=RestConverter.class,
                debug="debug",
                defaultAccept="defaultAccept",
diff --git 
a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/Rest_Context_Test.java
 
b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/Rest_Context_Test.java
index cba61b1..4280b10 100644
--- 
a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/Rest_Context_Test.java
+++ 
b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/Rest_Context_Test.java
@@ -42,7 +42,7 @@ public class Rest_Context_Test {
                a1.get().run().assertBody().is("RestContext");
        }
 
-       @Rest(context=X1.class)
+       @Rest(contextClass=X1.class)
        public static class A2 extends A1 {}
 
        @Test
@@ -64,7 +64,7 @@ public class Rest_Context_Test {
        public static class A4 extends A1 {
                 @RestHook(HookEvent.INIT)
                 public void init(RestContextBuilder builder) throws Exception {
-                        builder.context(X1.class);
+                        builder.contextClass(X1.class);
                 }
        }
 
@@ -81,7 +81,7 @@ public class Rest_Context_Test {
                }
        }
 
-       @Rest(context=X2.class)
+       @Rest(contextClass=X2.class)
        public static class A5 {
                @RestMethod
                public String get(RestContext context) {
diff --git 
a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/Restx_Path_Test.java
 
b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/Restx_Path_Test.java
index 46e1d75..abc51f0 100644
--- 
a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/Restx_Path_Test.java
+++ 
b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/Restx_Path_Test.java
@@ -30,20 +30,20 @@ public class Restx_Path_Test {
        public static class A  {
                @RestMethod(path="/")
                public String a(RestContext c) {
-                       return "A-" + c.getPath();
+                       return "A-" + c.getFullPath();
                }
        }
        @Rest(path="/p1", children={A2.class})
        public static class A1 {
                @RestMethod(path="/")
                public String a(RestContext c) {
-                       return "A01-" + c.getPath();
+                       return "A01-" + c.getFullPath();
                }
        }
        public static class A2a  {
                @RestMethod(path="/")
                public String a(RestContext c) {
-                       return "A02a-" + c.getPath();
+                       return "A02a-" + c.getFullPath();
                }
        }
        @Rest(path="/p2")
diff --git 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestCall.java
 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestCall.java
index 2893ab9..2298946 100644
--- 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestCall.java
+++ 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestCall.java
@@ -60,7 +60,7 @@ public class RestCall {
        public RestCall(Object resource, RestContext context, 
HttpServletRequest req, HttpServletResponse res) {
                this.context = context;
                this.resource = resource;
-               beanFactory = new BeanFactory(context.rootBeanFactory,  
resource);
+               beanFactory = BeanFactory.of(context.rootBeanFactory, resource);
                beanFactory.addBean(RestContext.class, context);
                request(req).response(res);
        }
diff --git 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestMethodsBuilder.java
 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestChildMatch.java
similarity index 57%
copy from 
juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestMethodsBuilder.java
copy to 
juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestChildMatch.java
index 1c7f97f..23a3ecd 100644
--- 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestMethodsBuilder.java
+++ 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestChildMatch.java
@@ -12,50 +12,54 @@
 // 
***************************************************************************************************************************
 package org.apache.juneau.rest;
 
-import java.util.*;
-
-import org.apache.juneau.collections.*;
+import org.apache.juneau.rest.annotation.*;
+import org.apache.juneau.rest.util.*;
 
 /**
- * Builder for {@link RestMethods} object.
+ * Represents a matched {@link Rest}-annotated child on an HTTP request.
  */
-public class RestMethodsBuilder  {
+public class RestChildMatch {
+
+       private UrlPathMatch pathMatch;
+       private RestContext childContext;
 
-       TreeMap<String,TreeSet<RestMethodContext>> map = new TreeMap<>();
-       Set<RestMethodContext> set = ASet.of();
+       /**
+        * Creator.
+        *
+        * @param pathMatch The path matching results.
+        * @param childContext The child context.
+        * @return A new {@link RestChildMatch} object.
+        */
+       public static RestChildMatch create(UrlPathMatch pathMatch, RestContext 
childContext) {
+               return new RestChildMatch(pathMatch, childContext);
+       }
 
        /**
-        * Adds a method context to this builder.
+        * Constructor.
         *
-        * @param mc The REST method context to add.
-        * @return Adds a method context to this builder.
+        * @param pathMatch The path matching results.
+        * @param childContext The child context.
         */
-       public RestMethodsBuilder add(RestMethodContext mc) {
-               return add(mc.getHttpMethod(), mc);
+       protected RestChildMatch(UrlPathMatch pathMatch, RestContext 
childContext) {
+               this.pathMatch = pathMatch;
+               this.childContext = childContext;
        }
 
        /**
-        * Adds a method context to this builder.
+        * Returns the path matching results of the REST child match.
         *
-        * @param httpMethodName The HTTP method name.
-        * @param mc The REST method context to add.
-        * @return Adds a method context to this builder.
+        * @return The path matching results of the REST child match.
         */
-       public RestMethodsBuilder add(String httpMethodName, RestMethodContext 
mc) {
-               httpMethodName = httpMethodName.toUpperCase();
-               if (! map.containsKey(httpMethodName))
-                       map.put(httpMethodName, new TreeSet<>());
-               map.get(httpMethodName).add(mc);
-               set.add(mc);
-               return this;
+       public UrlPathMatch getPathMatch() {
+               return pathMatch;
        }
 
        /**
-        * Creates a new {@link RestMethods} object using the contents of this 
builder.
+        * Returns the child context of the REST child match.
         *
-        * @return A new {@link RestMethods} object.
+        * @return The child context of the REST child match.
         */
-       public RestMethods build() {
-               return new RestMethods(this);
+       public RestContext getChildContext() {
+               return childContext;
        }
-}
\ No newline at end of file
+}
diff --git 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestChildren.java
 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestChildren.java
new file mode 100644
index 0000000..ca054de
--- /dev/null
+++ 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestChildren.java
@@ -0,0 +1,125 @@
+// 
***************************************************************************************************************************
+// * 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.util.*;
+
+import javax.servlet.*;
+
+import org.apache.juneau.rest.annotation.*;
+import org.apache.juneau.rest.util.*;
+
+/**
+ * Implements the child resources of a {@link Rest}-annotated class.
+ */
+public class RestChildren {
+
+       /**
+        * Represents a null value for the {@link Rest#restChildrenClass()} 
annotation.
+        */
+       @SuppressWarnings("javadoc")
+       public final class Null extends RestChildren {
+               public Null(RestChildrenBuilder builder) throws Exception {
+                       super(builder);
+               }
+       }
+
+       private final Map<String,RestContext> children = 
Collections.synchronizedMap(new LinkedHashMap<String,RestContext>());
+
+       /**
+        * Creates a new builder for this object.
+        *
+        * @return A new builder for this object.
+        */
+       public static RestChildrenBuilder create() {
+               return new RestChildrenBuilder();
+       }
+
+       /**
+        * Constructor.
+        *
+        * @param builder The builder containing the settings for this object.
+        */
+       public RestChildren(RestChildrenBuilder builder) {
+               for (RestContext rc : builder.list)
+                       children.put(rc.getPath(), rc);
+       }
+
+       /**
+        * Looks through the registered children of this object and returns the 
best match.
+        *
+        * @param call The HTTP call.
+        * @return The child that best matches the call, or an empty {@link 
Optional} if a match could not be made.
+        */
+       public Optional<RestChildMatch> findMatch(RestCall call) {
+               String pi = call.getPathInfoUndecoded();
+               if ((! children.isEmpty()) && pi != null && ! pi.equals("/")) {
+                       for (RestContext rc : children.values()) {
+                               UrlPathMatcher upp = rc.pathMatcher;
+                               UrlPathMatch uppm = 
upp.match(call.getUrlPath());
+                               if (uppm != null) {
+                                       return 
Optional.of(RestChildMatch.create(uppm, rc));
+                               }
+                       }
+               }
+               return Optional.empty();
+       }
+
+       /**
+        * Returns the children in this object as a map.
+        *
+        * <p>
+        * The keys are the {@link RestContext#getPath() paths} of the child 
contexts.
+        *
+        * @return The children as an unmodifiable map.
+        */
+       public Map<String,RestContext> asMap() {
+               return Collections.unmodifiableMap(children);
+       }
+
+
+       
//-----------------------------------------------------------------------------------------------------------------
+       // Lifecycle methods.
+       
//-----------------------------------------------------------------------------------------------------------------
+
+       /**
+        * Called during servlet initialization on all children to invoke all 
{@link HookEvent#POST_INIT} methods.
+        *
+        * @throws ServletException Error occurred.
+        */
+       public void postInit() throws ServletException {
+               for (RestContext childContext : children.values())
+                       childContext.postInit();
+       }
+
+       /**
+        * Called during servlet initialization on all children to invoke all 
{@link HookEvent#POST_INIT_CHILD_FIRST} methods.
+        *
+        * @throws ServletException Error occurred.
+        */
+       public void postInitChildFirst() throws ServletException {
+               for (RestContext childContext : children.values())
+                       childContext.postInitChildFirst();
+       }
+
+       /**
+        * Called during servlet destruction on all children to invoke all 
{@link HookEvent#DESTROY} and {@link Servlet#destroy()} methods.
+        */
+       public void destroy() {
+               for (RestContext r : children.values()) {
+                       r.destroy();
+                       if (r.getResource() instanceof Servlet)
+                               ((Servlet)r.getResource()).destroy();
+               }
+       }
+}
diff --git 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestChildrenBuilder.java
 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestChildrenBuilder.java
new file mode 100644
index 0000000..25b01a8
--- /dev/null
+++ 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestChildrenBuilder.java
@@ -0,0 +1,92 @@
+// 
***************************************************************************************************************************
+// * 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.rest.HttpRuntimeException.*;
+import static org.apache.juneau.internal.ObjectUtils.*;
+
+import java.util.*;
+
+import org.apache.juneau.collections.*;
+import org.apache.juneau.cp.*;
+import org.apache.juneau.http.exception.*;
+
+/**
+ * Builder for {@link RestChildren} objects.
+ */
+public class RestChildrenBuilder {
+
+       final List<RestContext> list = AList.create();
+
+       private BeanFactory beanFactory;
+       private Class<? extends RestChildren> implClass;
+
+       /**
+        * Instantiates a {@link RestChildren} object based on the contents of 
this builder.
+        *
+        * @return A new {@link RestChildren} object.
+        */
+       public RestChildren build() {
+               try {
+                       Class<? extends RestChildren> ic = 
firstNonNull(implClass, RestChildren.class);
+                       return 
BeanFactory.of(beanFactory).addBean(RestChildrenBuilder.class, 
this).createBean(ic);
+               } catch (Exception e) {
+                       throw toHttpException(e, InternalServerError.class);
+               }
+       }
+
+       /**
+        * Adds a child resource to this builder.
+        *
+        * @param childContext The REST context of the child resource.
+        * @return This object (for method chaining).
+        */
+       public RestChildrenBuilder add(RestContext childContext) {
+               this.list.add(childContext);
+               return this;
+       }
+
+
+       /**
+        * Specifies a {@link RestChildren} implementation subclass to use.
+        *
+        * <p>
+        * When specified, the {@link #build()} method will create an instance 
of that class instead of the default {@link RestChildren}.
+        *
+        * <p>
+        * The subclass must have a public constructor that takes in any of the 
following arguments:
+        * <ul>
+        *      <li>{@link RestChildrenBuilder} - This object.
+        *      <li>Any beans found in the specified {@link 
#beanFactory(BeanFactory) bean factory}.
+        *      <li>Any {@link Optional} beans that may or may not be found in 
the specified {@link #beanFactory(BeanFactory) bean factory}.
+        * </ul>
+        *
+        * @param implClass The implementation class to build.
+        * @return This object (for method chaining).
+        */
+       public RestChildrenBuilder implClass(Class<? extends RestChildren> 
implClass) {
+               this.implClass = implClass;
+               return this;
+       }
+
+       /**
+        * Specifies a {@link BeanFactory} to use when resolving constructor 
arguments.
+        *
+        * @param beanFactory The bean factory to use for resolving constructor 
arguments.
+        * @return This object (for method chaining).
+        */
+       public RestChildrenBuilder beanFactory(BeanFactory beanFactory) {
+               this.beanFactory = beanFactory;
+               return this;
+       }
+}
diff --git 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestContext.java
 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestContext.java
index 5c3212a..9c103d9 100644
--- 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestContext.java
+++ 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestContext.java
@@ -84,7 +84,9 @@ import org.apache.juneau.xml.*;
 @ConfigurableContext(nocache=true)
 public class RestContext extends BeanContext {
 
-       /** Represents a null value for the {@link Rest#context()} annotation.*/
+       /**
+        * Represents a null value for the {@link Rest#contextClass()} 
annotation.
+        */
        @SuppressWarnings("javadoc")
        public static final class Null extends RestContext {
                public Null(RestContextBuilder builder) throws Exception {
@@ -1474,6 +1476,84 @@ public class RestContext extends BeanContext {
        public static final String REST_messages = PREFIX + ".messages.lo";
 
        /**
+        * Configuration property:  REST method context class.
+        *
+        * <h5 class='section'>Property:</h5>
+        * <ul class='spaced-list'>
+        *      <li><b>ID:</b>  {@link 
org.apache.juneau.rest.RestContext#REST_methodContextClass 
REST_methodContextClass}
+        *      <li><b>Name:</b>  <js>"RestContext.methodContextClass.c"</js>
+        *      <li><b>Data type:</b>  <c>Class&lt;? extends {@link 
org.apache.juneau.rest.RestMethodContext}&gt;</c>
+        *      <li><b>Default:</b>  {@link 
org.apache.juneau.rest.RestMethodContext}
+        *      <li><b>Session property:</b>  <jk>false</jk>
+        *      <li><b>Annotations:</b>
+        *              <ul>
+        *                      <li class='ja'>{@link 
org.apache.juneau.rest.annotation.Rest#methodContextClass()}
+        *                      <li class='ja'>{@link 
org.apache.juneau.rest.annotation.RestMethod#contextClass()}
+        *              </ul>
+        *      <li><b>Methods:</b>
+        *              <ul>
+        *                      <li class='jm'>{@link 
org.apache.juneau.rest.RestContextBuilder#methodContextClass(Class)}
+        *                      <li class='jm'>{@link 
org.apache.juneau.rest.RestMethodContextBuilder#contextClass(Class)}
+        *              </ul>
+        * </ul>
+        *
+        * <h5 class='section'>Description:</h5>
+        * <p>
+        * Allows you to extend the {@link RestMethodContext} class to modify 
how any of the methods are implemented.
+        *
+        * <p>
+        * The subclass must have a public constructor that takes in any of the 
following arguments:
+        * <ul>
+        *      <li>{@link RestMethodContextBuilder} - The builder for the 
object.
+        *      <li>Any beans found in the specified {@link #REST_beanFactory 
bean factory}.
+        *      <li>Any {@link Optional} beans that may or may not be found in 
the specified {@link #REST_beanFactory bean factory}.
+        * </ul>
+        *
+        * <h5 class='section'>Example:</h5>
+        * <p class='bcode w800'>
+        *      <jc>// Our extended context class that adds a request attribute 
to all requests.</jc>
+        *      <jc>// The attribute value is provided by an injected spring 
bean.</jc>
+        *      <jk>public</jk> MyRestMethodContext <jk>extends</jk> 
RestMethodContext {
+        *
+        *              <jk>private final</jk> Optional&lt;? <jk>extends</jk> 
Supplier&lt;Object&gt;&gt; <jf>fooSupplier</jf>;
+        *
+        *              <jc>// Constructor that takes in builder and optional 
injected attribute provider.</jc>
+        *              <jk>public</jk> 
MyRestMethodContext(RestMethodContextBuilder <jv>builder</jv>, 
Optional&lt;AnInjectedFooSupplier&gt; <jv>fooSupplier</jv>) {
+        *                      <jk>super</jk>(<jv>builder</jv>);
+        *                      <jk>this</jk>.<jf>fooSupplier</jf> = 
<jv>fooSupplier</jv>.orElseGet(()-><jk>null</jk>);
+        *              }
+        *
+        *              <jc>// Override the method used to create default 
request attributes.</jc>
+        *              <ja>@Override</ja>
+        *              <jk>protected</jk> NamedAttributeList 
createDefaultRequestAttributes(Object <jv>resource</jv>, BeanFactory 
<jv>beanFactory</jv>, Method <jv>method</jv>, RestContext <jv>context</jv>) 
<jk>throws</jk> Exception {
+        *                      <jk>return super</jk>
+        *                              
.createDefaultRequestAttributes(<jv>resource</jv>, <jv>beanFactory</jv>, 
<jv>method</jv>, <jv>context</jv>)
+        *                              
.append(NamedAttribute.<jsm>of</jsm>(<js>"foo"</js>, 
()-><jf>fooSupplier</jf>.get());
+        *              }
+        *      }
+        * </p>
+        * <p class='bcode w800'>
+        *      <jc>// Option #1 - Defined via annotation.</jc>
+        *      
<ja>@Rest</ja>(methodContextClass=MyRestMethodContext.<jk>class</jk>)
+        *      <jk>public class</jk> MyResource {
+        *              ...
+        *
+        *              <jc>// Option #2 - Defined via builder passed in 
through init method.</jc>
+        *              <ja>@RestHook</ja>(<jsf>INIT</jsf>)
+        *              <jk>public void</jk> init(RestContextBuilder 
<jv>builder</jv>) <jk>throws</jk> Exception {
+        *                      
<jv>builder</jv>.methodContextClass(MyRestMethodContext.<jk>class</jk>);
+        *              }
+        *
+        *              <ja>@RestMethod</ja>
+        *              <jk>public</jk> Object getFoo(RequestAttributes 
<jv>attributes</jv>) {
+        *                      <jk>return</jk> 
<jv>attributes</jv>.get(<js>"foo"</js>);
+        *              }
+        *      }
+        * </p>
+        */
+       public static final String REST_methodContextClass = PREFIX + 
".methodContextClass.c";
+
+       /**
         * Configuration property:  Parsers.
         *
         * <h5 class='section'>Property:</h5>
@@ -2225,6 +2305,142 @@ public class RestContext extends BeanContext {
        public static final String REST_responseHandlers = PREFIX + 
".responseHandlers.lo";
 
        /**
+        * Configuration property:  REST children class.
+        *
+        * <h5 class='section'>Property:</h5>
+        * <ul class='spaced-list'>
+        *      <li><b>ID:</b>  {@link 
org.apache.juneau.rest.RestContext#REST_restChildrenClass 
REST_restChildrenClass}
+        *      <li><b>Name:</b>  <js>"RestContext.restChildrenClass.c"</js>
+        *      <li><b>Data type:</b>  <c>Class&lt;? extends {@link 
org.apache.juneau.rest.RestChildren}&gt;</c>
+        *      <li><b>Default:</b>  {@link org.apache.juneau.rest.RestChildren}
+        *      <li><b>Session property:</b>  <jk>false</jk>
+        *      <li><b>Annotations:</b>
+        *              <ul>
+        *                      <li class='ja'>{@link 
org.apache.juneau.rest.annotation.Rest#restChildrenClass()}
+        *              </ul>
+        *      <li><b>Methods:</b>
+        *              <ul>
+        *                      <li class='jm'>{@link 
org.apache.juneau.rest.RestContextBuilder#restChildrenClass(Class)}
+        *              </ul>
+        * </ul>
+        *
+        * <h5 class='section'>Description:</h5>
+        * <p>
+        * Allows you to extend the {@link RestChildren} class to modify how 
any of the methods are implemented.
+        *
+        * <p>
+        * The subclass must have a public constructor that takes in any of the 
following arguments:
+        * <ul>
+        *      <li>{@link RestChildrenBuilder} - The builder for the object.
+        *      <li>Any beans found in the specified {@link #REST_beanFactory 
bean factory}.
+        *      <li>Any {@link Optional} beans that may or may not be found in 
the specified {@link #REST_beanFactory bean factory}.
+        * </ul>
+        *
+        * <h5 class='section'>Example:</h5>
+        * <p class='bcode w800'>
+        *      <jc>// Our extended context class</jc>
+        *      <jk>public</jk> MyRestChildren <jk>extends</jk> RestChildren {
+        *              <jk>public</jk> MyRestChildren(RestChildrenBuilder 
<jv>builder</jv>, ARequiredSpringBean <jv>bean1</jv>, 
Optional&lt;AnOptionalSpringBean&gt; <jv>bean2</jv>) {
+        *                      <jk>super</jk>(<jv>builder</jv>);
+        *              }
+        *
+        *              <jc>// Override any methods.</jc>
+        *
+        *              <ja>@Override</ja>
+        *              <jk>public</jk> Optional&lt;RestChildMatch&gt; 
findMatch(RestCall <jv>call</jv>) {
+        *                      String <jv>path</jv> = 
<jv>call</jv>.getPathInfo();
+        *                      <jk>if</jk> 
(<jv>path</jv>.endsWith(<js>"/foo"</js>)) {
+        *                              <jc>// Do our own special handling.</jc>
+        *                      }
+        *                      <jk>return super</jk>.findMatch(<jv>call</jv>);
+        *              }
+        *      }
+        * </p>
+        * <p class='bcode w800'>
+        *      <jc>// Option #1 - Defined via annotation.</jc>
+        *      <ja>@Rest</ja>(restChildrenClass=MyRestChildren.<jk>class</jk>)
+        *      <jk>public class</jk> MyResource {
+        *              ...
+        *
+        *              <jc>// Option #2 - Defined via builder passed in 
through init method.</jc>
+        *              <ja>@RestHook</ja>(<jsf>INIT</jsf>)
+        *              <jk>public void</jk> init(RestContextBuilder 
<jv>builder</jv>) <jk>throws</jk> Exception {
+        *                      
<jv>builder</jv>.restChildrenClass(MyRestChildren.<jk>class</jk>);
+        *              }
+        *      }
+        * </p>
+        */
+       public static final String REST_restChildrenClass = PREFIX + 
".restChildrenClass.c";
+
+       /**
+        * Configuration property:  REST methods class.
+        *
+        * <h5 class='section'>Property:</h5>
+        * <ul class='spaced-list'>
+        *      <li><b>ID:</b>  {@link 
org.apache.juneau.rest.RestContext#REST_restMethodsClass REST_restMethodsClass}
+        *      <li><b>Name:</b>  <js>"RestContext.restMethodsClass.c"</js>
+        *      <li><b>Data type:</b>  <c>Class&lt;? extends {@link 
org.apache.juneau.rest.RestMethods}&gt;</c>
+        *      <li><b>Default:</b>  {@link org.apache.juneau.rest.RestMethods}
+        *      <li><b>Session property:</b>  <jk>false</jk>
+        *      <li><b>Annotations:</b>
+        *              <ul>
+        *                      <li class='ja'>{@link 
org.apache.juneau.rest.annotation.Rest#restMethodsClass()}
+        *              </ul>
+        *      <li><b>Methods:</b>
+        *              <ul>
+        *                      <li class='jm'>{@link 
org.apache.juneau.rest.RestContextBuilder#restMethodsClass(Class)}
+        *              </ul>
+        * </ul>
+        *
+        * <h5 class='section'>Description:</h5>
+        * <p>
+        * Allows you to extend the {@link RestMethods} class to modify how any 
of the methods are implemented.
+        *
+        * <p>
+        * The subclass must have a public constructor that takes in any of the 
following arguments:
+        * <ul>
+        *      <li>{@link RestMethodsBuilder} - The builder for the object.
+        *      <li>Any beans found in the specified {@link #REST_beanFactory 
bean factory}.
+        *      <li>Any {@link Optional} beans that may or may not be found in 
the specified {@link #REST_beanFactory bean factory}.
+        * </ul>
+        *
+        * <h5 class='section'>Example:</h5>
+        * <p class='bcode w800'>
+        *      <jc>// Our extended context class</jc>
+        *      <jk>public</jk> MyRestMethods <jk>extends</jk> RestMethods {
+        *              <jk>public</jk> MyRestMethods(RestMethodsBuilder 
<jv>builder</jv>, ARequiredSpringBean <jv>bean1</jv>, 
Optional&lt;AnOptionalSpringBean&gt; <jv>bean2</jv>) {
+        *                      <jk>super</jk>(<jv>builder</jv>);
+        *              }
+        *
+        *              <jc>// Override any methods.</jc>
+        *
+        *              <ja>@Override</ja>
+        *              <jk>public</jk> RestMethodContext findMethod(RestCall 
<jv>call</jv>) <jk>throws</jk> MethodNotAllowed, PreconditionFailed, NotFound {
+        *                      String <jv>path</jv> = 
<jv>call</jv>.getPathInfo();
+        *                      <jk>if</jk> 
(<jv>path</jv>.endsWith(<js>"/foo"</js>)) {
+        *                              <jc>// Do our own special handling.</jc>
+        *                      }
+        *                      <jk>return super</jk>.findMethod(<jv>call</jv>);
+        *              }
+        *      }
+        * </p>
+        * <p class='bcode w800'>
+        *      <jc>// Option #1 - Defined via annotation.</jc>
+        *      <ja>@Rest</ja>(restMethodsClass=MyRestMethods.<jk>class</jk>)
+        *      <jk>public class</jk> MyResource {
+        *              ...
+        *
+        *              <jc>// Option #2 - Defined via builder passed in 
through init method.</jc>
+        *              <ja>@RestHook</ja>(<jsf>INIT</jsf>)
+        *              <jk>public void</jk> init(RestContextBuilder 
<jv>builder</jv>) <jk>throws</jk> Exception {
+        *                      
<jv>builder</jv>.restMethodsClass(MyRestMethods.<jk>class</jk>);
+        *              }
+        *      }
+        * </p>
+        */
+       public static final String REST_restMethodsClass = PREFIX + 
".restMethodsClass.c";
+
+       /**
         * Configuration property:  Java REST method parameter resolvers.
         *
         * <h5 class='section'>Property:</h5>
@@ -2809,22 +3025,20 @@ public class RestContext extends BeanContext {
        /**
         * Configuration property:  REST context class.
         *
-        * <review>NEEDS REVIEW</review>
-        *
         * <h5 class='section'>Property:</h5>
         * <ul class='spaced-list'>
-        *      <li><b>ID:</b>  {@link 
org.apache.juneau.rest.RestContext#REST_context REST_context}
-        *      <li><b>Name:</b>  <js>"RestContext.context.c"</js>
+        *      <li><b>ID:</b>  {@link 
org.apache.juneau.rest.RestContext#REST_contextClass REST_contextClass}
+        *      <li><b>Name:</b>  <js>"RestContext.contextClass.c"</js>
         *      <li><b>Data type:</b>  <c>Class&lt;? extends {@link 
org.apache.juneau.rest.RestContext}&gt;</c>
         *      <li><b>Default:</b>  {@link org.apache.juneau.rest.RestContext}
         *      <li><b>Session property:</b>  <jk>false</jk>
         *      <li><b>Annotations:</b>
         *              <ul>
-        *                      <li class='ja'>{@link 
org.apache.juneau.rest.annotation.Rest#context()}
+        *                      <li class='ja'>{@link 
org.apache.juneau.rest.annotation.Rest#contextClass()}
         *              </ul>
         *      <li><b>Methods:</b>
         *              <ul>
-        *                      <li class='jm'>{@link 
org.apache.juneau.rest.RestContextBuilder#context(Class)}
+        *                      <li class='jm'>{@link 
org.apache.juneau.rest.RestContextBuilder#contextClass(Class)}
         *              </ul>
         * </ul>
         *
@@ -2833,37 +3047,56 @@ public class RestContext extends BeanContext {
         * Allows you to extend the {@link RestContext} class to modify how any 
of the methods are implemented.
         *
         * <p>
-        * The subclass must provide the following:
+        * The subclass must have a public constructor that takes in any of the 
following arguments:
         * <ul>
-        *      <li>A public constructor that takes in one parameter that 
should be passed to the super constructor:  {@link RestContextBuilder}.
+        *      <li>{@link RestContextBuilder} - The builder for the object.
+        *      <li>Any beans found in the specified {@link #REST_beanFactory 
bean factory}.
+        *      <li>Any {@link Optional} beans that may or may not be found in 
the specified {@link #REST_beanFactory bean factory}.
         * </ul>
         *
         * <h5 class='section'>Example:</h5>
         * <p class='bcode w800'>
-        *      <jc>// Our extended context class</jc>
+        *      <jc>// Our extended context class that adds a request attribute 
to all requests.</jc>
+        *      <jc>// The attribute value is provided by an injected spring 
bean.</jc>
         *      <jk>public</jk> MyRestContext <jk>extends</jk> RestContext {
-        *              <jk>public</jk> MyRestContext(RestContextBuilder 
<jv>builder</jv>) {
+        *
+        *              <jk>private final</jk> Optional&lt;? <jk>extends</jk> 
Supplier&lt;Object&gt;&gt; <jf>fooSupplier</jf>;
+        *
+        *              <jc>// Constructor that takes in builder and optional 
injected attribute provider.</jc>
+        *              <jk>public</jk> MyRestContext(RestMethodContextBuilder 
<jv>builder</jv>, Optional&lt;AnInjectedFooSupplier&gt; <jv>fooSupplier</jv>) {
         *                      <jk>super</jk>(<jv>builder</jv>);
+        *                      <jk>this</jk>.<jf>fooSupplier</jf> = 
<jv>fooSupplier</jv>.orElseGet(()-><jk>null</jk>);
         *              }
         *
-        *              <jc>// Override any methods.</jc>
+        *              <jc>// Override the method used to create default 
request attributes.</jc>
+        *              <ja>@Override</ja>
+        *              <jk>protected</jk> NamedAttributeList 
createDefaultRequestAttributes(Object <jv>resource</jv>, BeanFactory 
<jv>beanFactory</jv>) <jk>throws</jk> Exception {
+        *                      <jk>return super</jk>
+        *                              
.createDefaultRequestAttributes(<jv>resource</jv>, <jv>beanFactory</jv>)
+        *                              
.append(NamedAttribute.<jsm>of</jsm>(<js>"foo"</js>, 
()-><jf>fooSupplier</jf>.get());
+        *              }
         *      }
         * </p>
         * <p class='bcode w800'>
         *      <jc>// Option #1 - Defined via annotation.</jc>
-        *      <ja>@Rest</ja>(context=MyRestContext.<jk>class</jk>)
+        *      <ja>@Rest</ja>(contextClass=MyRestContext.<jk>class</jk>)
         *      <jk>public class</jk> MyResource {
         *              ...
         *
         *              <jc>// Option #2 - Defined via builder passed in 
through init method.</jc>
         *              <ja>@RestHook</ja>(<jsf>INIT</jsf>)
         *              <jk>public void</jk> init(RestContextBuilder 
<jv>builder</jv>) <jk>throws</jk> Exception {
-        *                      
<jv>builder</jv>.context(MyRestContext.<jk>class</jk>);
+        *                      
<jv>builder</jv>.contextClass(MyRestContext.<jk>class</jk>);
+        *              }
+        *
+        *              <ja>@RestMethod</ja>
+        *              <jk>public</jk> Object getFoo(RequestAttributes 
<jv>attributes</jv>) {
+        *                      <jk>return</jk> 
<jv>attributes</jv>.get(<js>"foo"</js>);
         *              }
         *      }
         * </p>
         */
-       public static final String REST_context = PREFIX + ".context.c";
+       public static final String REST_contextClass = PREFIX + ".context.c";
 
        /**
         * Configuration property:  Resource URI authority path.
@@ -3162,7 +3395,7 @@ public class RestContext extends BeanContext {
                clientVersionHeader,
                uriAuthority,
                uriContext;
-       final String fullPath;
+       final String path, fullPath;
        final UrlPathMatcher pathMatcher;
 
        private final Set<String> allowedMethodParams, allowedHeaderParams, 
allowedMethodHeaders;
@@ -3183,7 +3416,7 @@ public class RestContext extends BeanContext {
        private final Config config;
        private final VarResolver varResolver;
        private final RestMethods restMethods;
-       private final Map<String,RestContext> childResources;
+       private final RestChildren restChildren;
        private final StackTraceStore stackTraceStore;
        private final Logger logger;
        private final RestInfoProvider infoProvider;
@@ -3346,14 +3579,13 @@ public class RestContext extends BeanContext {
                        msgs = createMessages(r);
 
                        fullPath = (builder.parentContext == null ? "" : 
(builder.parentContext.fullPath + '/')) + builder.getPath();
+                       path = builder.getPath();
 
-                       String p = builder.getPath();
+                       String p = path;
                        if (! p.endsWith("/*"))
                                p += "/*";
                        pathMatcher = UrlPathMatcher.of(p);
 
-                       childResources = Collections.synchronizedMap(new 
LinkedHashMap<String,RestContext>());  // Not unmodifiable on purpose so that 
children can be replaced.
-
                        startCallMethods = 
createStartCallMethods(r).stream().map(this::toMethodInvoker).toArray(MethodInvoker[]::new);
                        endCallMethods = 
createEndCallMethods(r).stream().map(this::toMethodInvoker).toArray(MethodInvoker[]::new);
                        postInitMethods = 
createPostInitMethods(r).stream().map(this::toMethodInvoker).toArray(MethodInvoker[]::new);
@@ -3364,42 +3596,7 @@ public class RestContext extends BeanContext {
                        postCallMethods = 
createPostCallMethods(r).stream().map(this::toRestMethodInvoker).toArray(RestMethodInvoker[]::
 new);
 
                        restMethods = createRestMethods(r).build();
-
-
-                       // Initialize our child resources.
-                       for (Object o : getArrayProperty(REST_children, 
Object.class)) {
-                               String path = null;
-
-                               if (o instanceof RestChild) {
-                                       RestChild rc = (RestChild)o;
-                                       path = rc.path;
-                                       o = rc.resource;
-                               }
-
-                               RestContextBuilder cb = null;
-
-                               if (o instanceof Class) {
-                                       Class<?> oc = (Class<?>)o;
-                                       // Don't allow specifying yourself as a 
child.  Causes an infinite loop.
-                                       if (oc == builder.resourceClass)
-                                               continue;
-                                       cb = RestContext.create(this, 
builder.inner, oc, null);
-                                       o = new BeanFactory(beanFactory, 
r).addBean(RestContextBuilder.class, cb).createBean(oc);
-                               } else {
-                                       cb = RestContext.create(this, 
builder.inner, o.getClass(), o);
-                               }
-
-                               if (path != null)
-                                       cb.path(path);
-
-                               RestContext cc = cb.init(o).build();
-
-                               MethodInfo mi = 
ClassInfo.of(o).getMethod("setContext", RestContext.class);
-                               if (mi != null)
-                                       mi.accessible().invoke(o, cc);
-
-                               childResources.put(cb.getPath(), cc);
-                       }
+                       restChildren = createRestChildren(r).build();
 
                        infoProvider = createInfoProvider(r, beanFactory);
 
@@ -3755,7 +3952,7 @@ public class RestContext extends BeanContext {
                        x = (BeanFactory)resource;
 
                BeanFactory parent = parentContext == null ? null : 
parentContext.rootBeanFactory;
-               BeanFactory bf = new BeanFactory(parent, resource);
+               BeanFactory bf = BeanFactory.of(parent, resource);
                bf.addBean(BeanFactory.class, bf);
 
                if (x == null)
@@ -4555,7 +4752,11 @@ public class RestContext extends BeanContext {
         * @throws Exception An error occurred.
         */
        protected RestMethodsBuilder createRestMethods(Object resource) throws 
Exception {
-               RestMethodsBuilder x = new RestMethodsBuilder();
+               RestMethodsBuilder x = RestMethods
+                       .create()
+                       .beanFactory(rootBeanFactory)
+                       .implClass(getClassProperty(REST_restMethodsClass, 
RestMethods.class));
+
                ClassInfo rci = ClassInfo.of(resource);
 
                for (MethodInfo mi : rci.getPublicMethods()) {
@@ -4575,8 +4776,12 @@ public class RestContext extends BeanContext {
                                        if (mi.isNotPublic())
                                                throw new 
RestServletException("@RestMethod method {0}.{1} must be defined as public.", 
rci.inner().getName(), mi.getSimpleName());
 
-                                       RestMethodContextBuilder rmcb = new 
RestMethodContextBuilder(mi.inner(), this);
-                                       RestMethodContext rmc = rmcb.build();
+                                       RestMethodContext rmc = 
RestMethodContext
+                                               .create(mi.inner(), this)
+                                               .beanFactory(rootBeanFactory)
+                                               
.implClass(getClassProperty(REST_methodContextClass, RestMethodContext.class))
+                                               .build();
+
                                        String httpMethod = rmc.getHttpMethod();
 
                                        // RRPC is a special case where a 
method returns an interface that we
@@ -4584,9 +4789,11 @@ public class RestContext extends BeanContext {
                                        // We override the CallMethod.invoke() 
method to insert our logic.
                                        if ("RRPC".equals(httpMethod)) {
 
-                                               RestMethodContext smb = new 
RestMethodContextBuilder(mi.inner(), this)
+                                               RestMethodContext smb = 
RestMethodContext
+                                                       .create(mi.inner(), 
this)
                                                        .dotAll()
-                                                       
.context(RrpcRestMethodContext.class)
+                                                       
.beanFactory(rootBeanFactory)
+                                                       
.implClass(RrpcRestMethodContext.class)
                                                        .build();
                                                x
                                                        .add("GET", smb)
@@ -4605,6 +4812,56 @@ public class RestContext extends BeanContext {
        }
 
        /**
+        * Creates the builder for the children of this resource.
+        *
+        * @param resource The REST resource object.
+        * @return The builder for the {@link RestChildren} object.
+        * @throws Exception An error occurred.
+        */
+       protected RestChildrenBuilder createRestChildren(Object resource) 
throws Exception {
+               RestChildrenBuilder x = RestChildren
+                       .create()
+                       .beanFactory(rootBeanFactory)
+                       .implClass(getClassProperty(REST_restChildrenClass, 
RestChildren.class));
+
+               // Initialize our child resources.
+               for (Object o : getArrayProperty(REST_children, Object.class)) {
+                       String path = null;
+
+                       if (o instanceof RestChild) {
+                               RestChild rc = (RestChild)o;
+                               path = rc.path;
+                               o = rc.resource;
+                       }
+
+                       RestContextBuilder cb = null;
+
+                       if (o instanceof Class) {
+                               Class<?> oc = (Class<?>)o;
+                               // Don't allow specifying yourself as a child.  
Causes an infinite loop.
+                               if (oc == builder.resourceClass)
+                                       continue;
+                               cb = RestContext.create(this, builder.inner, 
oc, null);
+                               o = BeanFactory.of(beanFactory, 
resource).addBean(RestContextBuilder.class, cb).createBean(oc);
+                       } else {
+                               cb = RestContext.create(this, builder.inner, 
o.getClass(), o);
+                       }
+
+                       if (path != null)
+                               cb.path(path);
+
+                       RestContext cc = cb.init(o).build();
+
+                       MethodInfo mi = ClassInfo.of(o).getMethod("setContext", 
RestContext.class);
+                       if (mi != null)
+                               mi.accessible().invoke(o, cc);
+
+                       x.add(cc);
+               }
+               return x;
+       }
+
+       /**
         * Instantiates the list of {@link HookEvent#START_CALL} methods.
         *
         * @param resource The REST resource object.
@@ -4835,7 +5092,7 @@ public class RestContext extends BeanContext {
 
        /**
         * Returns the path for this resource as defined by the {@link 
Rest#path() @Rest(path)} annotation or
-        * {@link RestContextBuilder#path(String)} method concatenated with 
those on all parent classes.
+        * {@link RestContextBuilder#path(String)} method.
         *
         * <p>
         * If path is not specified, returns <js>""</js>.
@@ -4847,6 +5104,23 @@ public class RestContext extends BeanContext {
         * @return The servlet path.
         */
        public String getPath() {
+               return path;
+       }
+
+       /**
+        * Returns the path for this resource as defined by the {@link 
Rest#path() @Rest(path)} annotation or
+        * {@link RestContextBuilder#path(String)} method concatenated with 
those on all parent classes.
+        *
+        * <p>
+        * If path is not specified, returns <js>""</js>.
+        *
+        * <ul class='seealso'>
+        *      <li class='jf'>{@link #REST_path}
+        * </ul>
+        *
+        * @return The full path.
+        */
+       public String getFullPath() {
                return fullPath;
        }
 
@@ -4938,7 +5212,7 @@ public class RestContext extends BeanContext {
         *      Keys are the {@link Rest#path() @Rest(path)} annotation defined 
on the child resource.
         */
        public Map<String,RestContext> getChildResources() {
-               return Collections.unmodifiableMap(childResources);
+               return restChildren.asMap();
        }
 
        /**
@@ -5351,7 +5625,7 @@ public class RestContext extends BeanContext {
                List<ClassInfo> pt = mi.getParamTypes();
                RestParam[] rp = new RestParam[pt.size()];
 
-               beanFactory = new BeanFactory(beanFactory, getResource());
+               beanFactory = BeanFactory.of(beanFactory, getResource());
 
                for (int i = 0; i < pt.size(); i++) {
                        ParamInfo pi = mi.getParam(i);
@@ -5384,7 +5658,7 @@ public class RestContext extends BeanContext {
                List<ClassInfo> pt = mi.getParamTypes();
                RestParam[] rp = new RestParam[pt.size()];
 
-               beanFactory = new BeanFactory(beanFactory, getResource());
+               beanFactory = BeanFactory.of(beanFactory, getResource());
 
                for (int i = 0; i < pt.size(); i++) {
                        ParamInfo pi = mi.getParam(i);
@@ -5499,24 +5773,20 @@ public class RestContext extends BeanContext {
                        }
 
                        // If this resource has child resources, try to 
recursively call them.
-                       String pi = call.getPathInfoUndecoded();
-                       if ((! childResources.isEmpty()) && pi != null && ! 
pi.equals("/")) {
-                               for (RestContext rc : 
getChildResources().values()) {
-                                       UrlPathMatcher upp = rc.pathMatcher;
-                                       UrlPathMatch uppm = 
upp.match(call.getUrlPath());
-                                       if (uppm != null) {
-                                               if (! uppm.hasEmptyVars()) {
-                                                       
call.pathVars(uppm.getVars());
-                                                       HttpServletRequest 
childRequest = new OverrideableHttpServletRequest(call.getRequest())
-                                                               
.pathInfo(nullIfEmpty(urlDecode(uppm.getSuffix())))
-                                                               
.servletPath(call.getServletPath() + uppm.getPrefix());
-                                                       
rc.execute(rc.getResource(), childRequest, call.getResponse());  // TODO - 
resource needs to be dynamically retrieved.
-                                               } else {
-                                                       
call.debug(isDebug(call)).status(SC_NOT_FOUND).finish();
-                                               }
-                                               return;
-                                       }
+                       Optional<RestChildMatch> childMatch = 
restChildren.findMatch(call);
+                       if (childMatch.isPresent()) {
+                               UrlPathMatch uppm = 
childMatch.get().getPathMatch();
+                               RestContext rc = 
childMatch.get().getChildContext();
+                               if (! uppm.hasEmptyVars()) {
+                                       call.pathVars(uppm.getVars());
+                                       HttpServletRequest childRequest = new 
OverrideableHttpServletRequest(call.getRequest())
+                                               
.pathInfo(nullIfEmpty(urlDecode(uppm.getSuffix())))
+                                               
.servletPath(call.getServletPath() + uppm.getPrefix());
+                                       rc.execute(rc.getResource(), 
childRequest, call.getResponse());
+                               } else {
+                                       
call.debug(isDebug(call)).status(SC_NOT_FOUND).finish();
                                }
+                               return;
                        }
 
                        if (isDebug(call))
@@ -5835,8 +6105,7 @@ public class RestContext extends BeanContext {
                                throw new ServletException(e.unwrap());
                        }
                }
-               for (RestContext childContext : this.childResources.values())
-                       childContext.postInit();
+               restChildren.postInit();
                return this;
        }
 
@@ -5849,8 +6118,7 @@ public class RestContext extends BeanContext {
        public RestContext postInitChildFirst() throws ServletException {
                if (initialized.get())
                        return this;
-               for (RestContext childContext : this.childResources.values())
-                       childContext.postInitChildFirst();
+               restChildren.postInitChildFirst();
                for (MethodInvoker x : postInitChildFirstMethods) {
                        try {
                                x.invokeUsingFactory(beanFactory, 
getResource());
@@ -5863,7 +6131,7 @@ public class RestContext extends BeanContext {
        }
 
        /**
-        * Called during servlet initialization to invoke all {@link 
HookEvent#DESTROY} methods.
+        * Called during servlet destruction to invoke all {@link 
HookEvent#DESTROY} methods.
         */
        protected void destroy() {
                for (MethodInvoker x : destroyMethods) {
@@ -5874,11 +6142,7 @@ public class RestContext extends BeanContext {
                        }
                }
 
-               for (RestContext r : childResources.values()) {
-                       r.destroy();
-                       if (r.getResource() instanceof Servlet)
-                               ((Servlet)r.getResource()).destroy();
-               }
+               restChildren.destroy();
        }
 
        /**
diff --git 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestContextBuilder.java
 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestContextBuilder.java
index 5b60ff0..be2f879 100644
--- 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestContextBuilder.java
+++ 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestContextBuilder.java
@@ -184,8 +184,8 @@ public class RestContextBuilder extends BeanContextBuilder 
implements ServletCon
        public RestContext build() {
                try {
                        PropertyStore ps = getPropertyStore();
-                       Class<? extends RestContext> c = 
ps.getClassProperty(REST_context, RestContext.class, RestContext.class);
-                       BeanFactory bf = new BeanFactory(beanFactory, resource);
+                       Class<? extends RestContext> c = 
ps.getClassProperty(REST_contextClass, RestContext.class, RestContext.class);
+                       BeanFactory bf = BeanFactory.of(beanFactory, resource);
                        bf.addBean(RestContextBuilder.class, this);
                        return bf.createBean(c);
                } catch (Exception e) {
@@ -214,7 +214,7 @@ public class RestContextBuilder extends BeanContextBuilder 
implements ServletCon
                if (x == null && parentContext.isPresent()) {
                        x = parentContext.get().rootBeanFactory;
                }
-               return new BeanFactory(x, resource.orElse(null));
+               return BeanFactory.of(x, resource.orElse(null));
        }
 
        /**
@@ -745,41 +745,19 @@ public class RestContextBuilder extends 
BeanContextBuilder implements ServletCon
        /**
         * <i><l>RestContext</l> configuration property:&emsp;</i>  REST 
context class.
         *
-        * <review>NEEDS REVIEW</review>
         * <p>
         * Allows you to extend the {@link RestContext} class to modify how any 
of the methods are implemented.
         *
-        * <p>
-        * The subclass must provide the following:
-        * <ul>
-        *      <li>A public constructor that takes in one parameter that 
should be passed to the super constructor:  {@link RestContextBuilder}.
+        * <ul class='seealso'>
+        *      <li class='jf'>{@link RestContext#REST_contextClass}
         * </ul>
         *
-        * <h5 class='section'>Example:</h5>
-        * <p class='bcode w800'>
-        *      <jc>// Our REST class</jc>
-        *      <ja>@Rest</ja>(context=MyRestContext.<jk>class</jk>)
-        *      <jk>public class</jk> MyResource {
-        *              ...
-        *      }
-        * </p>
-        * <p class='bcode w800'>
-        *      <ja>@Rest</ja>
-        *      <jk>public class</jk> MyResource {
-        *              ...
-        *              <ja>@RestHook</ja>(<jsf>INIT</jsf>)
-        *              <jk>public void</jk> init(RestContextBuilder 
<jv>builder</jv>) <jk>throws</jk> Exception {
-        *                      
<jv>builder</jv>.context(MyRestContext.<jk>class</jk>);
-        *              }
-        *      }
-        * </p>
-        *
         * @param value The new value for this setting.
         * @return This object (for method chaining).
         */
        @FluentSetter
-       public RestContextBuilder context(Class<? extends RestContext> value) {
-               return set(REST_context, value);
+       public RestContextBuilder contextClass(Class<? extends RestContext> 
value) {
+               return set(REST_contextClass, value);
        }
 
        /**
@@ -1371,6 +1349,24 @@ public class RestContextBuilder extends 
BeanContextBuilder implements ServletCon
        }
 
        /**
+        * <i><l>RestContext</l> configuration property:&emsp;</i>  REST method 
context class.
+        *
+        * <p>
+        * Allows you to extend the {@link RestMethodContext} class to modify 
how any of the methods are implemented.
+        *
+        * <ul class='seealso'>
+        *      <li class='jf'>{@link RestContext#REST_methodContextClass}
+        * </ul>
+        *
+        * @param value The new value for this setting.
+        * @return This object (for method chaining).
+        */
+       @FluentSetter
+       public RestContextBuilder methodContextClass(Class<? extends 
RestMethodContext> value) {
+               return set(REST_methodContextClass, value);
+       }
+
+       /**
         * <i><l>RestContext</l> configuration property:&emsp;</i>  Parser 
listener.
         *
         * <p>
@@ -1628,6 +1624,42 @@ public class RestContextBuilder extends 
BeanContextBuilder implements ServletCon
        }
 
        /**
+        * <i><l>RestContext</l> configuration property:&emsp;</i>  REST 
children class.
+        *
+        * <p>
+        * Allows you to extend the {@link RestChildren} class to modify how 
any of the methods are implemented.
+        *
+        * <ul class='seealso'>
+        *      <li class='jf'>{@link RestContext#REST_restChildrenClass}
+        * </ul>
+        *
+        * @param value The new value for this setting.
+        * @return This object (for method chaining).
+        */
+       @FluentSetter
+       public RestContextBuilder restChildrenClass(Class<? extends 
RestChildren> value) {
+               return set(REST_restChildrenClass, value);
+       }
+
+       /**
+        * <i><l>RestContext</l> configuration property:&emsp;</i>  REST 
methods class.
+        *
+        * <p>
+        * Allows you to extend the {@link RestMethods} class to modify how any 
of the methods are implemented.
+        *
+        * <ul class='seealso'>
+        *      <li class='jf'>{@link RestContext#REST_restMethodsClass}
+        * </ul>
+        *
+        * @param value The new value for this setting.
+        * @return This object (for method chaining).
+        */
+       @FluentSetter
+       public RestContextBuilder restMethodsClass(Class<? extends RestMethods> 
value) {
+               return set(REST_restMethodsClass, value);
+       }
+
+       /**
         * <i><l>RestContext</l> configuration property:&emsp;</i>  Java method 
parameter resolvers.
         *
         * <p>
diff --git 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestMethodContext.java
 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestMethodContext.java
index 1f1d218..59ec1cc 100644
--- 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestMethodContext.java
+++ 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestMethodContext.java
@@ -65,7 +65,7 @@ import org.apache.juneau.utils.*;
 @ConfigurableContext(nocache=true)
 public class RestMethodContext extends BeanContext implements 
Comparable<RestMethodContext>  {
 
-       /** Represents a null value for the {@link RestMethod#context()} 
annotation.*/
+       /** Represents a null value for the {@link RestMethod#contextClass()} 
annotation.*/
        @SuppressWarnings("javadoc")
        public static final class Null extends RestMethodContext {
                public Null(RestMethodContextBuilder builder) throws Exception {
@@ -168,18 +168,20 @@ public class RestMethodContext extends BeanContext 
implements Comparable<RestMet
         * Configuration property:  REST method context class.
         *
         * <ul class='spaced-list'>
-        *      <li><b>ID:</b>  {@link 
org.apache.juneau.rest.RestMethodContext#RESTMETHOD_context RESTMETHOD_context}
-        *      <li><b>Name:</b>  <js>"RestMethodContext.context.c"</js>
+        *      <li><b>ID:</b>  {@link 
org.apache.juneau.rest.RestMethodContext#RESTMETHOD_contextClass 
RESTMETHOD_contextClass}
+        *      <li><b>Name:</b>  <js>"RestMethodContext.contextClass.c"</js>
         *      <li><b>Data type:</b>  <c>Class&lt;? extends {@link 
org.apache.juneau.rest.RestMethodContext}&gt;</c>
         *      <li><b>Default:</b>  {@link 
org.apache.juneau.rest.RestMethodContext}
         *      <li><b>Session property:</b>  <jk>false</jk>
         *      <li><b>Annotations:</b>
         *              <ul>
-        *                      <li class='ja'>{@link 
org.apache.juneau.rest.annotation.RestMethod#context()}
+        *                      <li class='ja'>{@link 
org.apache.juneau.rest.annotation.Rest#methodContextClass()}
+        *                      <li class='ja'>{@link 
org.apache.juneau.rest.annotation.RestMethod#contextClass()}
         *              </ul>
         *      <li><b>Methods:</b>
         *              <ul>
-        *                      <li class='jm'>{@link 
org.apache.juneau.rest.RestMethodContextBuilder#context(Class)}
+        *                      <li class='jm'>{@link 
org.apache.juneau.rest.RestContextBuilder#methodContextClass(Class)}
+        *                      <li class='jm'>{@link 
org.apache.juneau.rest.RestMethodContextBuilder#contextClass(Class)}
         *              </ul>
         * </ul>
         *
@@ -188,12 +190,48 @@ public class RestMethodContext extends BeanContext 
implements Comparable<RestMet
         * Allows you to extend the {@link RestMethodContext} class to modify 
how any of the functions are implemented.
         *
         * <p>
-        * The subclass must provide the following:
+        * The subclass must have a public constructor that takes in any of the 
following arguments:
         * <ul>
-        *      <li>A public constructor that takes in one parameter that 
should be passed to the super constructor:  {@link RestMethodContextBuilder}.
+        *      <li>{@link RestMethodContextBuilder} - The builder for the 
object.
+        *      <li>Any beans found in the specified {@link #REST_beanFactory 
bean factory}.
+        *      <li>Any {@link Optional} beans that may or may not be found in 
the specified {@link #REST_beanFactory bean factory}.
         * </ul>
+        *
+        * <h5 class='section'>Example:</h5>
+        * <p class='bcode w800'>
+        *      <jc>// Our extended context class that adds a request attribute 
to all requests.</jc>
+        *      <jc>// The attribute value is provided by an injected spring 
bean.</jc>
+        *      <jk>public</jk> MyRestMethodContext <jk>extends</jk> 
RestMethodContext {
+        *
+        *              <jk>private final</jk> Optional&lt;? <jk>extends</jk> 
Supplier&lt;Object&gt;&gt; <jf>fooSupplier</jf>;
+        *
+        *              <jc>// Constructor that takes in builder and optional 
injected attribute provider.</jc>
+        *              <jk>public</jk> 
MyRestMethodContext(RestMethodContextBuilder <jv>builder</jv>, 
Optional&lt;AnInjectedFooSupplier&gt; <jv>fooSupplier</jv>) {
+        *                      <jk>super</jk>(<jv>builder</jv>);
+        *                      <jk>this</jk>.<jf>fooSupplier</jf> = 
<jv>fooSupplier</jv>.orElseGet(()-><jk>null</jk>);
+        *              }
+        *
+        *              <jc>// Override the method used to create default 
request attributes.</jc>
+        *              <ja>@Override</ja>
+        *              <jk>protected</jk> NamedAttributeList 
createDefaultRequestAttributes(Object <jv>resource</jv>, BeanFactory 
<jv>beanFactory</jv>, Method <jv>method</jv>, RestContext <jv>context</jv>) 
<jk>throws</jk> Exception {
+        *                      <jk>return super</jk>
+        *                              
.createDefaultRequestAttributes(<jv>resource</jv>, <jv>beanFactory</jv>, 
<jv>method</jv>, <jv>context</jv>)
+        *                              
.append(NamedAttribute.<jsm>of</jsm>(<js>"foo"</js>, 
()-><jf>fooSupplier</jf>.get());
+        *              }
+        *      }
+        * </p>
+        * <p class='bcode w800'>
+        *      <ja>@Rest</ja>
+        *      <jk>public class</jk> MyResource {
+        *              ...
+        *              
<ja>@RestMethod</ja>(contextClass=MyRestMethodContext.<jk>class</jk>)
+        *              <jk>public</jk> Object getFoo(RequestAttributes 
<jv>attributes</jv>) {
+        *                      <jk>return</jk> 
<jv>attributes</jv>.get(<js>"foo"</js>);
+        *              }
+        *      }
+        * </p>
         */
-       public static final String RESTMETHOD_context = PREFIX + ".context.c";
+       public static final String RESTMETHOD_contextClass = PREFIX + 
".contextClass.c";
 
        /**
         * Configuration property:  Debug mode.
@@ -675,6 +713,17 @@ public class RestMethodContext extends BeanContext 
implements Comparable<RestMet
        final int hierarchyDepth;
 
        /**
+        * Creator.
+        *
+        * @param method The Java method this context belongs to.
+        * @param context The Java class context.
+        * @return A new builder.
+        */
+       public static RestMethodContextBuilder create(java.lang.reflect.Method 
method, RestContext context) {
+               return new RestMethodContextBuilder(method, context);
+       }
+
+       /**
         * Context constructor.
         *
         * @param builder The builder for this object.
@@ -693,7 +742,7 @@ public class RestMethodContext extends BeanContext 
implements Comparable<RestMet
                        mi = MethodInfo.of(method).accessible();
                        Object r = context.getResource();
 
-                       beanFactory = new BeanFactory(context.rootBeanFactory, 
r)
+                       beanFactory = BeanFactory.of(context.rootBeanFactory, r)
                                .addBean(RestMethodContext.class, this)
                                .addBean(Method.class, method)
                                .addBean(PropertyStore.class, ps);
diff --git 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestMethodContextBuilder.java
 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestMethodContextBuilder.java
index 02824cd..a542074 100644
--- 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestMethodContextBuilder.java
+++ 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestMethodContextBuilder.java
@@ -39,23 +39,29 @@ public class RestMethodContextBuilder extends 
BeanContextBuilder {
        RestContext restContext;
        Method restMethod;
 
+       private BeanFactory beanFactory;
+       private Class<? extends RestMethodContext> implClass;
+
        @Override /* BeanContextBuilder */
        public RestMethodContext build() {
                try {
                        PropertyStore ps = getPropertyStore();
-                       Class<? extends RestMethodContext> c = 
ps.getClassProperty(RESTMETHOD_context, RestMethodContext.class, 
RestMethodContext.class);
-                       BeanFactory bf = new 
BeanFactory(restContext.rootBeanFactory, restContext.getResource());
-                       bf.addBean(RestMethodContextBuilder.class, this);
-                       return bf.createBean(c);
+
+                       Class<? extends RestMethodContext> ic = implClass;
+                       if (ic == null)
+                               ic = 
ps.getClassProperty(RESTMETHOD_contextClass, RestMethodContext.class, 
RestMethodContext.class);
+
+                       return 
BeanFactory.of(beanFactory).addBean(RestMethodContextBuilder.class, 
this).createBean(ic);
                } catch (Exception e) {
                        throw toHttpException(e, InternalServerError.class);
                }
        }
 
-       RestMethodContextBuilder(java.lang.reflect.Method method, RestContext 
context) throws RestServletException {
+       RestMethodContextBuilder(java.lang.reflect.Method method, RestContext 
context) {
 
                this.restContext = context;
                this.restMethod = method;
+               this.beanFactory = context.rootBeanFactory;
 
                String sig = method.getDeclaringClass().getName() + '.' + 
method.getName();
                MethodInfo mi = MethodInfo.of(context.getResource().getClass(), 
method);
@@ -81,10 +87,8 @@ public class RestMethodContextBuilder extends 
BeanContextBuilder {
 
                        
applyAnnotations(mi.getAnnotationList(ConfigAnnotationFilter.INSTANCE), vrs);
 
-               } catch (RestServletException e) {
-                       throw e;
                } catch (Exception e) {
-                       throw new RestServletException(e, "Exception occurred 
while initializing method ''{0}''", sig);
+                       throw toHttpException(e, InternalServerError.class);
                }
        }
 
@@ -98,6 +102,40 @@ public class RestMethodContextBuilder extends 
BeanContextBuilder {
                return this;
        }
 
+
+       /**
+        * Specifies a {@link RestMethodContext} implementation subclass to use.
+        *
+        * <p>
+        * When specified, the {@link #build()} method will create an instance 
of that class instead of the default {@link RestMethodContext}.
+        *
+        * <p>
+        * The subclass must have a public constructor that takes in any of the 
following arguments:
+        * <ul>
+        *      <li>{@link RestMethodContextBuilder} - This object.
+        *      <li>Any beans found in the specified {@link 
#beanFactory(BeanFactory) bean factory}.
+        *      <li>Any {@link Optional} beans that may or may not be found in 
the specified {@link #beanFactory(BeanFactory) bean factory}.
+        * </ul>
+        *
+        * @param implClass The implementation class to build.
+        * @return This object (for method chaining).
+        */
+       public RestMethodContextBuilder implClass(Class<? extends 
RestMethodContext> implClass) {
+               this.implClass = implClass;
+               return this;
+       }
+
+       /**
+        * Specifies a {@link BeanFactory} to use when resolving constructor 
arguments.
+        *
+        * @param beanFactory The bean factory to use for resolving constructor 
arguments.
+        * @return This object (for method chaining).
+        */
+       public RestMethodContextBuilder beanFactory(BeanFactory beanFactory) {
+               this.beanFactory = beanFactory;
+               return this;
+       }
+
        
//----------------------------------------------------------------------------------------------------
        // Properties
        
//----------------------------------------------------------------------------------------------------
@@ -135,8 +173,8 @@ public class RestMethodContextBuilder extends 
BeanContextBuilder {
         * @return This object (for method chaining).
         */
        @FluentSetter
-       public RestMethodContextBuilder context(Class<? extends 
RestMethodContext> value) {
-               return set(RESTMETHOD_context, value);
+       public RestMethodContextBuilder contextClass(Class<? extends 
RestMethodContext> value) {
+               return set(RESTMETHOD_contextClass, value);
        }
 
        /**
diff --git 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestMethods.java
 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestMethods.java
index 2690e28..f9558ce 100644
--- 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestMethods.java
+++ 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestMethods.java
@@ -23,6 +23,16 @@ import org.apache.juneau.rest.annotation.*;
  */
 public class RestMethods {
 
+       /**
+        * Represents a null value for the {@link Rest#restMethodsClass()} 
annotation.
+        */
+       @SuppressWarnings("javadoc")
+       public final class Null extends RestMethods {
+               public Null(RestMethodsBuilder builder) throws Exception {
+                       super(builder);
+               }
+       }
+
        private final Map<String,List<RestMethodContext>> map;
        private List<RestMethodContext> list;
 
@@ -35,7 +45,12 @@ public class RestMethods {
                return new RestMethodsBuilder();
        }
 
-       RestMethods(RestMethodsBuilder builder) {
+       /**
+        * Constructor.
+        *
+        * @param builder The builder containing the settings for this object.
+        */
+       public RestMethods(RestMethodsBuilder builder) {
                AMap<String,List<RestMethodContext>> m = AMap.create();
                for (Map.Entry<String,TreeSet<RestMethodContext>> e : 
builder.map.entrySet())
                        m.put(e.getKey(), AList.of(e.getValue()));
diff --git 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestMethodsBuilder.java
 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestMethodsBuilder.java
index 1c7f97f..ef47f57 100644
--- 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestMethodsBuilder.java
+++ 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestMethodsBuilder.java
@@ -12,9 +12,14 @@
 // 
***************************************************************************************************************************
 package org.apache.juneau.rest;
 
+import static org.apache.juneau.internal.ObjectUtils.*;
+import static org.apache.juneau.rest.HttpRuntimeException.*;
+
 import java.util.*;
 
 import org.apache.juneau.collections.*;
+import org.apache.juneau.cp.*;
+import org.apache.juneau.http.exception.*;
 
 /**
  * Builder for {@link RestMethods} object.
@@ -24,6 +29,23 @@ public class RestMethodsBuilder  {
        TreeMap<String,TreeSet<RestMethodContext>> map = new TreeMap<>();
        Set<RestMethodContext> set = ASet.of();
 
+       private BeanFactory beanFactory;
+       private Class<? extends RestMethods> implClass;
+
+       /**
+        * Instantiates a {@link RestMethods} object based on the contents of 
this builder.
+        *
+        * @return A new {@link RestMethods} object.
+        */
+       public RestMethods build() {
+               try {
+                       Class<? extends RestMethods> ic = 
firstNonNull(implClass, RestMethods.class);
+                       return 
BeanFactory.of(beanFactory).addBean(RestMethodsBuilder.class, 
this).createBean(ic);
+               } catch (Exception e) {
+                       throw toHttpException(e, InternalServerError.class);
+               }
+       }
+
        /**
         * Adds a method context to this builder.
         *
@@ -51,11 +73,35 @@ public class RestMethodsBuilder  {
        }
 
        /**
-        * Creates a new {@link RestMethods} object using the contents of this 
builder.
+        * Specifies a {@link RestMethods} implementation subclass to use.
         *
-        * @return A new {@link RestMethods} object.
+        * <p>
+        * When specified, the {@link #build()} method will create an instance 
of that class instead of the default {@link RestMethods}.
+        *
+        * <p>
+        * The subclass must have a public constructor that takes in any of the 
following arguments:
+        * <ul>
+        *      <li>{@link RestMethodsBuilder} - This object.
+        *      <li>Any beans found in the specified {@link 
#beanFactory(BeanFactory) bean factory}.
+        *      <li>Any {@link Optional} beans that may or may not be found in 
the specified {@link #beanFactory(BeanFactory) bean factory}.
+        * </ul>
+        *
+        * @param implClass The implementation class to build.
+        * @return This object (for method chaining).
         */
-       public RestMethods build() {
-               return new RestMethods(this);
+       public RestMethodsBuilder implClass(Class<? extends RestMethods> 
implClass) {
+               this.implClass = implClass;
+               return this;
+       }
+
+       /**
+        * Specifies a {@link BeanFactory} to use when resolving constructor 
arguments.
+        *
+        * @param beanFactory The bean factory to use for resolving constructor 
arguments.
+        * @return This object (for method chaining).
+        */
+       public RestMethodsBuilder beanFactory(BeanFactory beanFactory) {
+               this.beanFactory = beanFactory;
+               return this;
        }
 }
\ No newline at end of file
diff --git 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestServlet.java
 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestServlet.java
index 05187e2..bff6623 100644
--- 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestServlet.java
+++ 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestServlet.java
@@ -74,7 +74,7 @@ public abstract class RestServlet extends HttpServlet {
         * @return A new bean factory.
         */
        public BeanFactory createBeanFactory(Optional<BeanFactory> parent) {
-               return new BeanFactory(parent.orElse(null), this);
+               return BeanFactory.of(parent.orElse(null), this);
        }
 
        /**
@@ -101,7 +101,7 @@ public abstract class RestServlet extends HttpServlet {
        public synchronized String getPath() {
                RestContext context = this.context.get();
                if (context != null)
-                       return context.getPath();
+                       return context.getFullPath();
                ClassInfo ci = ClassInfo.of(getClass());
                String path = "";
                for (Rest rr : ci.getAnnotations(Rest.class))
diff --git 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/Rest.java
 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/Rest.java
index b1eedd1..ec3470e 100644
--- 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/Rest.java
+++ 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/Rest.java
@@ -271,39 +271,16 @@ public @interface Rest {
        String[] consumes() default {};
 
        /**
-        * Allows you to extend the {@link RestContext} class to modify how any 
of the methods are implemented.
+        * REST context class.
         *
-        * <review>NEEDS REVIEW</review>
         * <p>
-        * The subclass must provide the following:
-        * <ul>
-        *      <li>A public constructor that takes in one parameter that 
should be passed to the super constructor:  {@link RestContextBuilder}.
-        * </ul>
-        *
-        * <h5 class='section'>Example:</h5>
-        * <p class='bcode w800'>
-        *      <jc>// Our extended context class</jc>
-        *      <jk>public</jk> MyRestContext <jk>extends</jk> RestContext {
-        *              <jk>public</jk> MyRestContext(RestContextBuilder 
<jv>builder</jv>) {
-        *                      <jk>super</jk>(<jv>builder</jv>);
-        *              }
-        *
-        *              // Override any methods.
-        *      }
-        * </p>
-        * <p class='bcode w800'>
-        *      <jc>// Our REST class</jc>
-        *      <ja>@Rest</ja>(context=MyRestContext.<jk>class</jk>)
-        *      <jk>public class</jk> MyResource {
-        *              ...
-        *      }
-        * </p>
+        * Allows you to extend the {@link RestContext} class to modify how any 
of the methods are implemented.
         *
         * <ul class='seealso'>
-        *      <li class='jm'>{@link RestContextBuilder#context(Class)}
+        *      <li class='jm'>{@link RestContext#REST_contextClass}
         * </ul>
         */
-       Class<? extends RestContext> context() default RestContext.Null.class;
+       Class<? extends RestContext> contextClass() default 
RestContext.Null.class;
 
        /**
         * Class-level response converters.
@@ -730,6 +707,15 @@ public @interface Rest {
        String messages() default "";
 
        /**
+        * Allows you to extend the {@link RestMethodContext} class to modify 
how any of the methods are implemented.
+        * 
+        * <ul class='seealso'>
+        *      <li class='jf'>{@link RestContext#REST_methodContextClass}
+        * </ul>
+        */
+       Class<? extends RestMethodContext> methodContextClass() default 
RestMethodContext.Null.class;
+
+       /**
         * Dynamically apply this annotation to the specified classes.
         *
         * <ul class='seealso'>
@@ -974,6 +960,30 @@ public @interface Rest {
        Class<? extends ResponseHandler>[] responseHandlers() default {};
 
        /**
+        * REST children class.
+        *
+        * <p>
+        * Allows you to extend the {@link RestChildren} class to modify how 
any of the methods are implemented.
+        *
+        * <ul class='seealso'>
+        *      <li class='jf'>{@link RestContext#REST_restChildrenClass}
+        * </ul>
+        */
+       Class<? extends RestChildren> restChildrenClass() default 
RestChildren.Null.class;
+
+       /**
+        * REST methods class.
+        *
+        * <p>
+        * Allows you to extend the {@link RestMethods} class to modify how any 
of the methods are implemented.
+        *
+        * <ul class='seealso'>
+        *      <li class='jf'>{@link RestContext#REST_restMethodsClass}
+        * </ul>
+        */
+       Class<? extends RestMethods> restMethodsClass() default 
RestMethods.Null.class;
+
+       /**
         * Java method parameter resolvers.
         *
         * <p>
diff --git 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestAnnotation.java
 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestAnnotation.java
index 8e7f88b..f0cb789 100644
--- 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestAnnotation.java
+++ 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestAnnotation.java
@@ -90,12 +90,15 @@ public class RestAnnotation {
                Class<? extends StaticFiles> staticFiles = 
StaticFiles.Null.class;
                Class<? extends ResponseHandler>[] responseHandlers = new 
Class[0];
                Class<? extends RestLogger> callLogger = RestLogger.Null.class;
-               Class<? extends RestContext> context = RestContext.Null.class;
+               Class<? extends RestContext> contextClass = 
RestContext.Null.class;
                Class<? extends RestConverter>[] converters = new Class[0];
                Class<? extends RestGuard>[] guards = new Class[0];
                Class<? extends RestInfoProvider> 
infoProvider=RestInfoProvider.Null.class;
                Class<? extends RestParam>[] restParams = new Class[0];
                Class<? extends BeanFactory> beanFactory = 
BeanFactory.Null.class;
+               Class<? extends RestMethodContext> methodContextClass = 
RestMethodContext.Null.class;
+               Class<? extends RestChildren> restChildrenClass = 
RestChildren.Null.class;
+               Class<? extends RestMethods> restMethodsClass = 
RestMethods.Null.class;
                Class<?>[] children={}, parsers={}, serializers={};
                ResourceSwagger swagger = ResourceSwaggerAnnotation.DEFAULT;
                String disableAllowBodyParam="", allowedHeaderParams="", 
allowedMethodHeaders="", allowedMethodParams="", clientVersionHeader="", 
config="", debug="", debugOn="", defaultAccept="", defaultCharset="", 
defaultContentType="", maxInput="", messages="", path="", 
renderResponseStackTraces="", roleGuard="", rolesDeclared="", siteName="", 
uriAuthority="", uriContext="", uriRelativity="", uriResolution="";
@@ -228,13 +231,13 @@ public class RestAnnotation {
                }
 
                /**
-                * Sets the {@link Rest#context()} property on this annotation.
+                * Sets the {@link Rest#contextClass()} property on this 
annotation.
                 *
                 * @param value The new value for this property.
                 * @return This object (for method chaining).
                 */
-               public Builder context(Class<? extends RestContext> value) {
-                       this.context = value;
+               public Builder contextClass(Class<? extends RestContext> value) 
{
+                       this.contextClass = value;
                        return this;
                }
 
@@ -415,6 +418,17 @@ public class RestAnnotation {
                }
 
                /**
+                * Sets the {@link Rest#methodContextClass()} property on this 
annotation.
+                *
+                * @param value The new value for this property.
+                * @return This object (for method chaining).
+                */
+               public Builder methodContextClass(Class<? extends 
RestMethodContext> value) {
+                       this.methodContextClass = value;
+                       return this;
+               }
+
+               /**
                 * Sets the {@link Rest#parsers()} property on this annotation.
                 *
                 * @param value The new value for this property.
@@ -492,6 +506,28 @@ public class RestAnnotation {
                }
 
                /**
+                * Sets the {@link Rest#restChildrenClass()} property on this 
annotation.
+                *
+                * @param value The new value for this property.
+                * @return This object (for method chaining).
+                */
+               public Builder restChildrenClass(Class<? extends RestChildren> 
value) {
+                       this.restChildrenClass = value;
+                       return this;
+               }
+
+               /**
+                * Sets the {@link Rest#restMethodsClass()} property on this 
annotation.
+                *
+                * @param value The new value for this property.
+                * @return This object (for method chaining).
+                */
+               public Builder restMethodsClass(Class<? extends RestMethods> 
value) {
+                       this.restMethodsClass = value;
+                       return this;
+               }
+
+               /**
                 * Sets the {@link Rest#restParams()} property on this 
annotation.
                 *
                 * @param value The new value for this property.
@@ -655,12 +691,15 @@ public class RestAnnotation {
                private final Class<? extends StaticFiles> staticFiles;
                private final Class<? extends ResponseHandler>[] 
responseHandlers;
                private final Class<? extends RestLogger> callLogger;
-               private final Class<? extends RestContext> context;
+               private final Class<? extends RestContext> contextClass;
                private final Class<? extends RestConverter>[] converters;
                private final Class<? extends RestGuard>[] guards;
                private final Class<? extends RestInfoProvider> infoProvider;
                private final Class<? extends RestParam>[] restParams;
                private final Class<? extends BeanFactory> beanFactory;
+               private final Class<? extends RestMethodContext> 
methodContextClass;
+               private final Class<? extends RestChildren> restChildrenClass;
+               private final Class<? extends RestMethods> restMethodsClass;
                private final Class<?>[] children, parsers, serializers;
                private final ResourceSwagger swagger;
                private final String disableAllowBodyParam, 
allowedHeaderParams, allowedMethodHeaders, allowedMethodParams, 
clientVersionHeader, config, debug, debugOn, defaultAccept, defaultCharset, 
defaultContentType, maxInput, messages, path, renderResponseStackTraces, 
roleGuard, rolesDeclared, siteName, uriAuthority, uriContext, uriRelativity, 
uriResolution;
@@ -678,7 +717,7 @@ public class RestAnnotation {
                        this.clientVersionHeader = b.clientVersionHeader;
                        this.config = b.config;
                        this.consumes = copyOf(b.consumes);
-                       this.context = b.context;
+                       this.contextClass = b.contextClass;
                        this.converters = copyOf(b.converters);
                        this.debug = b.debug;
                        this.debugOn = b.debugOn;
@@ -695,6 +734,9 @@ public class RestAnnotation {
                        this.infoProvider = b.infoProvider;
                        this.maxInput = b.maxInput;
                        this.messages = b.messages;
+                       this.methodContextClass = b.methodContextClass;
+                       this.restChildrenClass = b.restChildrenClass;
+                       this.restMethodsClass = b.restMethodsClass;
                        this.restParams = copyOf(b.restParams);
                        this.parsers = copyOf(b.parsers);
                        this.partParser = b.partParser;
@@ -768,8 +810,8 @@ public class RestAnnotation {
                }
 
                @Override /* Rest */
-               public Class<? extends RestContext> context() {
-                       return context;
+               public Class<? extends RestContext> contextClass() {
+                       return contextClass;
                }
 
                @Override /* Rest */
@@ -853,6 +895,11 @@ public class RestAnnotation {
                }
 
                @Override /* Rest */
+               public Class<? extends RestMethodContext> methodContextClass() {
+                       return methodContextClass;
+               }
+
+               @Override /* Rest */
                public Class<?>[] parsers() {
                        return parsers;
                }
@@ -888,6 +935,16 @@ public class RestAnnotation {
                }
 
                @Override /* Rest */
+               public Class<? extends RestChildren> restChildrenClass() {
+                       return restChildrenClass;
+               }
+
+               @Override /* Rest */
+               public Class<? extends RestMethods> restMethodsClass() {
+                       return restMethodsClass;
+               }
+
+               @Override /* Rest */
                public Class<? extends RestParam>[] restParams() {
                        return restParams;
                }
@@ -985,7 +1042,7 @@ public class RestAnnotation {
                        psb.prependTo(REST_guards, reverse(a.guards()));
                        psb.prependTo(REST_children, a.children());
                        psb.prependTo(REST_restParams, a.restParams());
-                       psb.setIf(a.context() != RestContext.Null.class, 
REST_context, a.context());
+                       psb.setIf(a.contextClass() != RestContext.Null.class, 
REST_contextClass, a.contextClass());
                        psb.setIfNotEmpty(REST_uriContext, 
string(a.uriContext()));
                        psb.setIfNotEmpty(REST_uriAuthority, 
string(a.uriAuthority()));
                        psb.setIfNotEmpty(REST_uriRelativity, 
string(a.uriRelativity()));
@@ -998,6 +1055,9 @@ public class RestAnnotation {
                        psb.setIf(a.beanFactory() != BeanFactory.Null.class, 
REST_beanFactory, a.beanFactory());
                        psb.setIf(a.callLogger() != RestLogger.Null.class, 
REST_callLogger, a.callLogger());
                        psb.setIf(a.infoProvider() != 
RestInfoProvider.Null.class, REST_infoProvider, a.infoProvider());
+                       psb.setIf(a.methodContextClass() != 
RestMethodContext.Null.class, REST_methodContextClass, a.methodContextClass());
+                       psb.setIf(a.restChildrenClass() != 
RestChildren.Null.class, REST_restChildrenClass, a.restChildrenClass());
+                       psb.setIf(a.restMethodsClass() != 
RestMethods.Null.class, REST_restMethodsClass, a.restMethodsClass());
                        psb.setIfNotEmpty(REST_disableAllowBodyParam, 
bool(a.disableAllowBodyParam()));
                        psb.setIfNotEmpty(REST_allowedHeaderParams, 
string(a.allowedHeaderParams()));
                        psb.setIfNotEmpty(REST_allowedMethodHeaders, 
string(a.allowedMethodHeaders()));
diff --git 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestMethod.java
 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestMethod.java
index 7f0ed4a..7b9c113 100644
--- 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestMethod.java
+++ 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestMethod.java
@@ -126,10 +126,10 @@ public @interface RestMethod {
         * </ul>
         *
         * <ul class='seealso'>
-        *      <li class='jm'>{@link RestMethodContextBuilder#context(Class)}
+        *      <li class='jm'>{@link 
RestMethodContextBuilder#contextClass(Class)}
         * </ul>
         */
-       Class<? extends RestMethodContext> context() default 
RestMethodContext.Null.class;
+       Class<? extends RestMethodContext> contextClass() default 
RestMethodContext.Null.class;
 
        /**
         * Class-level response converters.
diff --git 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestMethodAnnotation.java
 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestMethodAnnotation.java
index db221bf..9db07dd 100644
--- 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestMethodAnnotation.java
+++ 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestMethodAnnotation.java
@@ -61,7 +61,7 @@ public class RestMethodAnnotation {
                Class<? extends RestConverter>[] converters = new Class[0];
                Class<? extends RestGuard>[] guards = new Class[0];
                Class<? extends RestMatcher>[] matchers = new Class[0];
-               Class<? extends RestMethodContext> context = 
RestMethodContext.Null.class;
+               Class<? extends RestMethodContext> contextClass = 
RestMethodContext.Null.class;
                Class<?>[] encoders=new Class<?>[0], parsers=new Class<?>[0], 
serializers=new Class<?>[0];
                int priority = 0;
                MethodSwagger swagger = MethodSwaggerAnnotation.DEFAULT;
@@ -107,13 +107,13 @@ public class RestMethodAnnotation {
                }
 
                /**
-                * Sets the {@link RestMethod#context()} property on this 
annotation.
+                * Sets the {@link RestMethod#contextClass()} property on this 
annotation.
                 *
                 * @param value The new value for this property.
                 * @return This object (for method chaining).
                 */
-               public Builder context(Class<? extends RestMethodContext> 
value) {
-                       this.context = value;
+               public Builder contextClass(Class<? extends RestMethodContext> 
value) {
+                       this.contextClass = value;
                        return this;
                }
 
@@ -425,7 +425,7 @@ public class RestMethodAnnotation {
                private final Class<? extends RestConverter>[] converters;
                private final Class<? extends RestGuard>[] guards;
                private final Class<? extends RestMatcher>[] matchers;
-               private final Class<? extends RestMethodContext> context;
+               private final Class<? extends RestMethodContext> contextClass;
                private final Class<?>[] encoders, parsers, serializers;
                private final int priority;
                private final MethodSwagger swagger;
@@ -436,7 +436,7 @@ public class RestMethodAnnotation {
                        super(b);
                        this.clientVersion = b.clientVersion;
                        this.consumes = copyOf(b.consumes);
-                       this.context = b.context;
+                       this.contextClass = b.contextClass;
                        this.converters = copyOf(b.converters);
                        this.debug = b.debug;
                        this.defaultAccept = b.defaultAccept;
@@ -477,8 +477,8 @@ public class RestMethodAnnotation {
                }
 
                @Override /* RestMethod */
-               public Class<? extends RestMethodContext> context() {
-                       return context;
+               public Class<? extends RestMethodContext> contextClass() {
+                       return contextClass;
                }
 
                @Override /* RestMethod */
@@ -634,7 +634,7 @@ public class RestMethodAnnotation {
                        psb.set(REST_serializers, 
merge(ConverterUtils.toType(psb.peek(REST_serializers), Object[].class), 
a.serializers()));
                        psb.set(REST_parsers, 
merge(ConverterUtils.toType(psb.peek(REST_parsers), Object[].class), 
a.parsers()));
                        psb.set(REST_encoders, 
merge(ConverterUtils.toType(psb.peek(REST_encoders), Object[].class), 
a.encoders()));
-                       psb.setIf(a.context() != RestMethodContext.Null.class, 
RESTMETHOD_context, a.context());
+                       psb.setIf(a.contextClass() != 
RestMethodContext.Null.class, RESTMETHOD_contextClass, a.contextClass());
                        psb.setIfNotEmpty(REST_produces, 
stringList(a.produces()));
                        psb.setIfNotEmpty(REST_consumes, 
stringList(a.consumes()));
                        stringStream(a.defaultRequestHeaders()).map(x -> 
BasicHeader.ofPair(x)).forEach(x -> 
psb.appendTo(RESTMETHOD_defaultRequestHeaders, x));
diff --git a/pom.xml b/pom.xml
index 3813479..c8f3260 100644
--- a/pom.xml
+++ b/pom.xml
@@ -50,7 +50,7 @@
                <derby.version>10.10.2.0</derby.version>
                <hibernate.version>5.0.9.Final</hibernate.version>
                <javax.inject.version>1</javax.inject.version>
-               <springframework.version>2.0.1.RELEASE</springframework.version>
+               <springboot.version>2.4.2</springboot.version>
                <xml.apis.version>1.4.01</xml.apis.version>
        </properties>
 

Reply via email to