From commits-return-4762-archive-asf-public=cust-asf.ponee.io@juneau.apache.org Sat Jan 6 02:55:59 2018 Return-Path: X-Original-To: archive-asf-public@eu.ponee.io Delivered-To: archive-asf-public@eu.ponee.io Received: from cust-asf.ponee.io (cust-asf.ponee.io [163.172.22.183]) by mx-eu-01.ponee.io (Postfix) with ESMTP id 92014180647 for ; Sat, 6 Jan 2018 02:55:59 +0100 (CET) Received: by cust-asf.ponee.io (Postfix) id 81D1D160C28; Sat, 6 Jan 2018 01:55:59 +0000 (UTC) Delivered-To: archive-asf-public@cust-asf.ponee.io Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by cust-asf.ponee.io (Postfix) with SMTP id D60BC160C27 for ; Sat, 6 Jan 2018 02:55:57 +0100 (CET) Received: (qmail 87368 invoked by uid 500); 6 Jan 2018 01:55:57 -0000 Mailing-List: contact commits-help@juneau.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@juneau.apache.org Delivered-To: mailing list commits@juneau.apache.org Received: (qmail 87357 invoked by uid 99); 6 Jan 2018 01:55:56 -0000 Received: from pnap-us-west-generic-nat.apache.org (HELO spamd3-us-west.apache.org) (209.188.14.142) by apache.org (qpsmtpd/0.29) with ESMTP; Sat, 06 Jan 2018 01:55:56 +0000 Received: from localhost (localhost [127.0.0.1]) by spamd3-us-west.apache.org (ASF Mail Server at spamd3-us-west.apache.org) with ESMTP id 7B9B2180893 for ; Sat, 6 Jan 2018 01:55:56 +0000 (UTC) X-Virus-Scanned: Debian amavisd-new at spamd3-us-west.apache.org X-Spam-Flag: NO X-Spam-Score: -11.73 X-Spam-Level: X-Spam-Status: No, score=-11.73 tagged_above=-999 required=6.31 tests=[KAM_ASCII_DIVIDERS=0.8, KAM_SHORT=0.001, RCVD_IN_DNSWL_HI=-5, RCVD_IN_MSPIKE_H3=-0.01, RCVD_IN_MSPIKE_WL=-0.01, SPF_PASS=-0.001, T_RP_MATCHES_RCVD=-0.01, USER_IN_DEF_SPF_WL=-7.5] autolearn=disabled Received: from mx1-lw-us.apache.org ([10.40.0.8]) by localhost (spamd3-us-west.apache.org [10.40.0.10]) (amavisd-new, port 10024) with ESMTP id K7jNL95_DoiV for ; Sat, 6 Jan 2018 01:55:50 +0000 (UTC) Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by mx1-lw-us.apache.org (ASF Mail Server at mx1-lw-us.apache.org) with SMTP id 4E2625F6C8 for ; Sat, 6 Jan 2018 01:55:48 +0000 (UTC) Received: (qmail 86745 invoked by uid 99); 6 Jan 2018 01:55:47 -0000 Received: from git1-us-west.apache.org (HELO git1-us-west.apache.org) (140.211.11.23) by apache.org (qpsmtpd/0.29) with ESMTP; Sat, 06 Jan 2018 01:55:47 +0000 Received: by git1-us-west.apache.org (ASF Mail Server at git1-us-west.apache.org, from userid 33) id E0F14DFE46; Sat, 6 Jan 2018 01:55:44 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: jamesbognar@apache.org To: commits@juneau.incubator.apache.org Message-Id: X-Mailer: ASF-Git Admin Mailer Subject: juneau git commit: RestContext refactoring. Date: Sat, 6 Jan 2018 01:55:44 +0000 (UTC) Repository: juneau Updated Branches: refs/heads/master 30ac20a16 -> b766e1d07 RestContext refactoring. Project: http://git-wip-us.apache.org/repos/asf/juneau/repo Commit: http://git-wip-us.apache.org/repos/asf/juneau/commit/b766e1d0 Tree: http://git-wip-us.apache.org/repos/asf/juneau/tree/b766e1d0 Diff: http://git-wip-us.apache.org/repos/asf/juneau/diff/b766e1d0 Branch: refs/heads/master Commit: b766e1d07d2add197d3735cb5c08669013ad107f Parents: 30ac20a Author: JamesBognar Authored: Fri Jan 5 20:55:39 2018 -0500 Committer: JamesBognar Committed: Fri Jan 5 20:55:39 2018 -0500 ---------------------------------------------------------------------- juneau-doc/src/main/javadoc/overview.html | 2 +- .../java/org/apache/juneau/rest/RestChild.java | 36 ++ .../org/apache/juneau/rest/RestContext.java | 89 +++- .../apache/juneau/rest/RestContextBuilder.java | 418 ++++++++++--------- .../juneau/rest/RestResourceResolver.java | 6 +- .../juneau/rest/RestResourceResolverSimple.java | 20 +- .../juneau/rest/annotation/RestResource.java | 35 +- .../java/org/apache/juneau/rest/package.html | 8 +- 8 files changed, 394 insertions(+), 220 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/juneau/blob/b766e1d0/juneau-doc/src/main/javadoc/overview.html ---------------------------------------------------------------------- diff --git a/juneau-doc/src/main/javadoc/overview.html b/juneau-doc/src/main/javadoc/overview.html index 98c60a9..46901ca 100644 --- a/juneau-doc/src/main/javadoc/overview.html +++ b/juneau-doc/src/main/javadoc/overview.html @@ -4493,7 +4493,7 @@ The children annotation approach simply makes it easier to define them without having to touch the web.xml file again. Child resources can also be defined programmatically by using the - {@link org.apache.juneau.rest.RestContextBuilder#childResources(Class[])} method. + {@link org.apache.juneau.rest.RestContextBuilder#children(Class[])} method.

Note that these router pages can be arbitrarily nested deep. http://git-wip-us.apache.org/repos/asf/juneau/blob/b766e1d0/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestChild.java ---------------------------------------------------------------------- diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestChild.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestChild.java new file mode 100644 index 0000000..8817192 --- /dev/null +++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestChild.java @@ -0,0 +1,36 @@ +// *************************************************************************************************************************** +// * 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; + +/** + * Represents a simple child REST resource / path mapping. + */ +public class RestChild { + + final String path; + final Object resource; + + /** + * Constructor. + * + * @param path The child resource path relative to the parent resource URI. + * @param resource + * The child resource. + *
Can either be a Class (which will be instantiated using the registered {@link RestResourceResolver}, + * or an already-instantiated object. + */ + public RestChild(String path, Object resource) { + this.path = path; + this.resource = resource; + } +} http://git-wip-us.apache.org/repos/asf/juneau/blob/b766e1d0/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestContext.java ---------------------------------------------------------------------- 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 bc2aa30..0810abc 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 @@ -199,6 +199,82 @@ public final class RestContext extends BeanContext { public static final String REST_callHandler = PREFIX + "callHandler.o"; /** + * Configuration property: Children. + * + *

    + *
  • Name: "RestContext.children.lo" + *
  • Data type: List<Class | Object | RestChild> + *
  • Default: empty list + *
  • Session-overridable: false + *
+ * + *

+ * Defines children of this resource. + * + *

+ * A REST child resource is simply another servlet or object that is initialized as part of the parent resource and has a + * servlet path directly under the parent servlet path. + *
The main advantage to defining servlets as REST children is that you do not need to define them in the + * web.xml file of the web application. + *
This can cut down on the number of entries that show up in the web.xml file if you are defining + * large numbers of servlets. + * + *

+ * Child resources must specify a value for {@link RestResource#path()} that identifies the subpath of the child resource + * relative to the parent path. + * + *

+ * Child resources can be nested arbitrarily deep using this technique (i.e. children can also have children). + * + *

+ *
Servlet initialization:
+ *
+ *

+ * A child resource will be initialized immediately after the parent servlet is initialized. + * The child resource receives the same servlet config as the parent resource. + * This allows configuration information such as servlet initialization parameters to filter to child + * resources. + *

+ *
+ *
Runtime behavior:
+ *
+ *

+ * As a rule, methods defined on the HttpServletRequest object will behave as if the child + * servlet were deployed as a top-level resource under the child's servlet path. + * For example, the getServletPath() and getPathInfo() methods on the + * HttpServletRequest object will behave as if the child resource were deployed using the + * child's servlet path. + * Therefore, the runtime behavior should be equivalent to deploying the child servlet in the + * web.xml file of the web application. + *

+ *
+ *
+ * + *
Notes:
+ *
    + *
  • Property: {@link RestContext#REST_children} + *
  • Annotations: + *
      + *
    • {@link RestResource#children()} + *
    + *
  • Methods: + *
      + *
    • {@link RestContextBuilder#child(String,Object)} + *
    • {@link RestContextBuilder#children(Class...)} + *
    • {@link RestContextBuilder#children(Object...)} + *
    + *
  • When defined as classes, instances are resolved using the registered {@link #REST_resourceResolver} which + * by default is {@link RestResourceResolverSimple} which requires the class have one of the following + * constructors: + *
      + *
    • public T(RestContextBuilder) + *
    • public T() + *
    + *
+ */ + public static final String REST_children = PREFIX + "children.lo"; + + /** * Configuration property: Classpath resource finder. * *
    @@ -1400,7 +1476,6 @@ public final class RestContext extends BeanContext { * @param builder The servlet configuration object. * @throws Exception If any initialization problems were encountered. */ - @SuppressWarnings("unchecked") public RestContext(RestContextBuilder builder) throws Exception { super(builder.getPropertyStore()); @@ -1701,13 +1776,13 @@ public final class RestContext extends BeanContext { // Initialize our child resources. resourceResolver = getInstanceProperty(REST_resourceResolver, resource, RestResourceResolver.class, parentContext == null ? RestResourceResolverSimple.class : parentContext.resourceResolver, true, this, ps); - for (Object o : builder.childResources) { + for (Object o : getArrayProperty(REST_children, Object.class)) { String path = null; Object r = null; - if (o instanceof Pair) { - Pair p = (Pair)o; - path = p.first(); - r = p.second(); + if (o instanceof RestChild) { + RestChild rc = (RestChild)o; + path = rc.path; + r = rc.resource; } else if (o instanceof Class) { Class c = (Class)o; // Don't allow specifying yourself as a child. Causes an infinite loop. @@ -1723,7 +1798,7 @@ public final class RestContext extends BeanContext { if (o instanceof Class) { Class oc = (Class)o; childBuilder = new RestContextBuilder(builder.inner, oc, this); - r = resourceResolver.resolve(oc, childBuilder); + r = resourceResolver.resolve(resource, oc, childBuilder); } else { r = o; childBuilder = new RestContextBuilder(builder.inner, o.getClass(), this); http://git-wip-us.apache.org/repos/asf/juneau/blob/b766e1d0/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestContextBuilder.java ---------------------------------------------------------------------- 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 8a3d14c..3d727f6 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 @@ -98,8 +98,6 @@ public class RestContextBuilder extends BeanContextBuilder implements ServletCon ObjectMap properties; ConfigFile configFile; VarResolverBuilder varResolverBuilder; - - List childResources = new ArrayList<>(); String path; HtmlDocBuilder htmlDocBuilder; @@ -199,7 +197,7 @@ public class RestContextBuilder extends BeanContextBuilder implements ServletCon responseHandlers(r.responseHandlers()); converters(r.converters()); guards(reverse(r.guards())); - childResources(r.children()); + children(r.children()); beanFilters(r.beanFilters()); pojoSwaps(r.pojoSwaps()); paramResolvers(r.paramResolvers()); @@ -412,60 +410,6 @@ public class RestContextBuilder extends BeanContextBuilder implements ServletCon } /** - * Adds a child resource to this resource. - * - *

    - * Child resources are resources that are accessed under the path of the parent resource. - * - *

    - * This is the programmatic equivalent to the {@link RestResource#children() @RestResource.children()} annotation. - * - * @param path The child path of the resource. Must conform to {@link RestResource#path()} format. - * @param child The child resource. - * @return This object (for method chaining). - */ - public RestContextBuilder childResource(String path, Object child) { - this.childResources.add(new Pair<>(path, child)); - return this; - } - - /** - * Add child resources to this resource. - * - *

    - * Child resources are resources that are accessed under the path of the parent resource. - * - *

    - * This is the programmatic equivalent to the {@link RestResource#children() @RestResource.children()} annotation. - * - * @param children The child resources to add to this resource. - * Children must be annotated with {@link RestResource#path()} to identify the child path. - * @return This object (for method chaining). - */ - public RestContextBuilder childResources(Object...children) { - this.childResources.addAll(Arrays.asList(children)); - return this; - } - - /** - * Add child resources to this resource. - * - *

    - * Child resources are resources that are accessed under the path of the parent resource. - * - *

    - * This is the programmatic equivalent to the {@link RestResource#children() @RestResource.children()} annotation. - * - * @param children The child resources to add to this resource. - * Children must be annotated with {@link RestResource#path()} to identify the child path. - * @return This object (for method chaining). - */ - public RestContextBuilder childResources(Class...children) { - this.childResources.addAll(Arrays.asList(children)); - return this; - } - - /** * Returns an instance of an HTMLDOC builder for setting HTMLDOC-related properties. * * @return An instance of an HTMLDOC builder for setting HTMLDOC-related properties. @@ -561,73 +505,77 @@ public class RestContextBuilder extends BeanContextBuilder implements ServletCon //---------------------------------------------------------------------------------------------------- /** - * Configuration property: Resource path. + * Configuration property: Allow body URL parameter. * - *

    - * Identifies the URL subpath relative to the parent resource. + *

      + *
    • Name: "RestContext.allowBodyParam.b" + *
    • Data type: Boolean + *
    • Default: true + *
    • Session-overridable: false + *
    * *

    + * When enabled, the HTTP body content on PUT and POST requests can be passed in as text using the "body" + * URL parameter. + *
    + * For example: "?body=(name='John%20Smith',age=45)" + * *

    Notes:
    *
      - *
    • Property: {@link RestContext#REST_path} + *
    • Property: {@link RestContext#REST_allowBodyParam} *
    • Annotations: *
        - *
      • {@link RestResource#path()} - *
      + *
    • {@link RestResource#allowBodyParam()} + *
    *
  • Methods: *
      - *
    • {@link RestContextBuilder#path(String)} + *
    • {@link RestContextBuilder#allowBodyParam(boolean)} *
    - *
  • This annotation is ignored on top-level servlets (i.e. servlets defined in web.xml files). - *
    Therefore, implementers can optionally specify a path value for documentation purposes. - *
  • Typically, this setting is only applicable to resources defined as children through the - * {@link RestResource#children()} annotation. - *
    However, it may be used in other ways (e.g. defining paths for top-level resources in microservices). + *
  • Parameter name is case-insensitive. + *
  • Useful for debugging PUT and POST methods using only a browser. * * - * @param path The URL path of this resource. + * @param value The new value for this setting. * @return This object (for method chaining). */ - public RestContextBuilder path(String path) { - if (startsWith(path, '/')) - path = path.substring(1); - this.path = path; - return this; + public RestContextBuilder allowBodyParam(boolean value) { + return set(REST_allowBodyParam, value); } /** - * Configuration property: Resource context path. + * Configuration property: Allowed method parameters. * *

    - * Overrides the context path value for this resource and any child resources. + * When specified, the HTTP method can be overridden by passing in a "method" URL parameter on a regular + * GET request. + *
    + * For example: "?method=OPTIONS" * - *

    - * This setting is useful if you want to use "context:/child/path" URLs in child resource POJOs but - * the context path is not actually specified on the servlet container. - * The net effect is that the {@link RestRequest#getContextPath()} and {@link RestRequest#getServletPath()} methods - * will return this value instead of the actual context path of the web app. - * - *

    *

    Notes:
    *
      - *
    • Property: {@link RestContext#REST_contextPath} + *
    • Property: {@link RestContext#REST_allowedMethodParams} *
    • Annotations: *
        - *
      • {@link RestResource#contextPath()} + *
      • {@link RestResource#allowedMethodParams()} *
      *
    • Methods: *
        - *
      • @link RestContextBuilder#contextPath(String)} + *
      • {@link RestContextBuilder#allowedMethodParams(String...)} *
      + *
    • Parameter name is case-insensitive. + *
    • Use "*" to represent all methods. *
    * - * @param contextPath The context path for this resource and any child resources. + *

    + * Note that per the HTTP specification, special care should + * be taken when allowing non-safe (POST, PUT, DELETE) methods to be invoked through GET requests. + * + * @param value The new value for this setting. * @return This object (for method chaining). */ - public RestContextBuilder contextPath(String contextPath) { - if (! contextPath.isEmpty()) - set(REST_contextPath, contextPath); - return this; + public RestContextBuilder allowedMethodParams(String...value) { + return set(REST_allowedMethodParams, StringUtils.join(value, ',')); } /** @@ -662,77 +610,229 @@ public class RestContextBuilder extends BeanContextBuilder implements ServletCon } /** - * Configuration property: Allow body URL parameter. - * - *

      - *
    • Name: "RestContext.allowBodyParam.b" - *
    • Data type: Boolean - *
    • Default: true - *
    • Session-overridable: false - *
    + * Configuration property: REST call handler. * *

    - * When enabled, the HTTP body content on PUT and POST requests can be passed in as text using the "body" - * URL parameter. - *
    - * For example: "?body=(name='John%20Smith',age=45)" - * + * This class handles the basic lifecycle of an HTTP REST call. + *
    Subclasses can be used to customize how these HTTP calls are handled. + + *

    *

    Notes:
    *
      - *
    • Property: {@link RestContext#REST_allowBodyParam} + *
    • Property: {@link RestContext#REST_callHandler} *
    • Annotations: *
        - *
      • {@link RestResource#allowBodyParam()} + *
      • {@link RestResource#callHandler()} *
      *
    • Methods: *
        - *
      • {@link RestContextBuilder#allowBodyParam(boolean)} + *
      • {@link RestContextBuilder#callHandler(Class)} + *
      • {@link RestContextBuilder#callHandler(RestCallHandler)} *
      - *
    • Parameter name is case-insensitive. - *
    • Useful for debugging PUT and POST methods using only a browser. *
    * - * @param value The new value for this setting. + * @param restHandler The new call handler for this resource. * @return This object (for method chaining). */ - public RestContextBuilder allowBodyParam(boolean value) { - return set(REST_allowBodyParam, value); + public RestContextBuilder callHandler(Class restHandler) { + return set(REST_callHandler, restHandler); } /** - * Configuration property: Allowed method parameters. + * Configuration property: REST call handler. * *

    - * When specified, the HTTP method can be overridden by passing in a "method" URL parameter on a regular - * GET request. - *
    - * For example: "?method=OPTIONS" + * Same as {@link #callHandler(Class)} but allows you to pass in a call handler instance. + * + * @param restHandler The new call handler for this resource. + * @return This object (for method chaining). + */ + public RestContextBuilder callHandler(RestCallHandler restHandler) { + return set(REST_callHandler, restHandler); + } + + /** + * Configuration property: Children. + * + *

    + * Defines children of this resource. + * + *

    + * A REST child resource is simply another servlet that is initialized as part of the parent resource and has a + * servlet path directly under the parent servlet path. + *
    The main advantage to defining servlets as REST children is that you do not need to define them in the + * web.xml file of the web application. + *
    This can cut down on the number of entries that show up in the web.xml file if you are defining + * large numbers of servlets. + * + *

    + * Child resources must specify a value for {@link RestResource#path()} that identifies the subpath of the child resource + * relative to the parent path. * + *

    + * It should be noted that servlets can be nested arbitrarily deep using this technique (i.e. children can also have + * children). + * + *

    + *
    Servlet initialization:
    + *
    + *

    + * A child resource will be initialized immediately after the parent servlet is initialized. + * The child resource receives the same servlet config as the parent resource. + * This allows configuration information such as servlet initialization parameters to filter to child + * resources. + *

    + *
    + *
    Runtime behavior:
    + *
    + *

    + * As a rule, methods defined on the HttpServletRequest object will behave as if the child + * servlet were deployed as a top-level resource under the child's servlet path. + * For example, the getServletPath() and getPathInfo() methods on the + * HttpServletRequest object will behave as if the child resource were deployed using the + * child's servlet path. + * Therefore, the runtime behavior should be equivalent to deploying the child servlet in the + * web.xml file of the web application. + *

    + *
    + *
    + * *
    Notes:
    *
      - *
    • Property: {@link RestContext#REST_allowedMethodParams} - *
    • Annotations: + *
    • Property: {@link RestContext#REST_children} + *
    • Annotations: *
        - *
      • {@link RestResource#allowedMethodParams()} + *
      • {@link RestResource#children()} + *
      + *
    • Methods: + *
        + *
      • {@link RestContextBuilder#child(String,Object)} + *
      • {@link RestContextBuilder#children(Class...)} + *
      • {@link RestContextBuilder#children(Object...)} + *
      + *
    • When defined as classes, instances are resolved using the registered {@link RestContext#REST_resourceResolver} which + * by default is {@link RestResourceResolverSimple} which requires the class have one of the following + * constructors: + *
        + *
      • public T(RestContextBuilder) + *
      • public T() *
      + *
    + * + * @param children The children to add to this resource.. + * @return This object (for method chaining). + */ + public RestContextBuilder children(Class...children) { + return addTo(REST_children, children); + } + + /** + * Configuration property: Children. + * + *

    + * Same as {@link #children(Class...)} but allows you to pass in already-constructed child instances. + * + * @param children + * The children to add to this resource. + *
    Objects can be any of the following: + *

      + *
    • A class that can be resolved to an instance using the registered {@link RestContext#REST_resourceResolver resource resolver}. + *
      The class must specify a {@link RestResource#path()} annotation to identify parent-relative path for the child. + *
    • A resource instance. + *
      The class must specify a {@link RestResource#path()} annotation to identify parent-relative path for the child. + *
    • An instance of {@link RestChild} that defines the path/resource mapping. + *
    + * @return This object (for method chaining). + */ + public RestContextBuilder children(Object...children) { + return addTo(REST_children, children); + } + + /** + * Configuration property: Children. + * + *

    + * Shortcut for adding a single child to this resource. + * + *

    + * This can be used for resources that don't have a {@link RestResource#path()} annotation. + * + * @param path The child path relative to the parent resource URI. + * @param child The child to add to this resource. + * @return This object (for method chaining). + */ + public RestContextBuilder child(String path, Object child) { + return addTo(REST_children, new RestChild(path, child)); + } + + /** + * Configuration property: Resource path. + * + *

    + * Identifies the URL subpath relative to the parent resource. + * + *

    + *

    Notes:
    + *
      + *
    • Property: {@link RestContext#REST_path} + *
    • Annotations: + *
        + *
      • {@link RestResource#path()} + *
      *
    • Methods: *
        - *
      • {@link RestContextBuilder#allowedMethodParams(String...)} + *
      • {@link RestContextBuilder#path(String)} *
      - *
    • Parameter name is case-insensitive. - *
    • Use "*" to represent all methods. + *
    • This annotation is ignored on top-level servlets (i.e. servlets defined in web.xml files). + *
      Therefore, implementers can optionally specify a path value for documentation purposes. + *
    • Typically, this setting is only applicable to resources defined as children through the + * {@link RestResource#children()} annotation. + *
      However, it may be used in other ways (e.g. defining paths for top-level resources in microservices). *
    * + * @param path The URL path of this resource. + * @return This object (for method chaining). + */ + public RestContextBuilder path(String path) { + if (startsWith(path, '/')) + path = path.substring(1); + this.path = path; + return this; + } + + /** + * Configuration property: Resource context path. + * *

    - * Note that per the HTTP specification, special care should - * be taken when allowing non-safe (POST, PUT, DELETE) methods to be invoked through GET requests. + * Overrides the context path value for this resource and any child resources. * - * @param value The new value for this setting. + *

    + * This setting is useful if you want to use "context:/child/path" URLs in child resource POJOs but + * the context path is not actually specified on the servlet container. + * The net effect is that the {@link RestRequest#getContextPath()} and {@link RestRequest#getServletPath()} methods + * will return this value instead of the actual context path of the web app. + * + *

    + *

    Notes:
    + *
      + *
    • Property: {@link RestContext#REST_contextPath} + *
    • Annotations: + *
        + *
      • {@link RestResource#contextPath()} + *
      + *
    • Methods: + *
        + *
      • @link RestContextBuilder#contextPath(String)} + *
      + *
    + * + * @param contextPath The context path for this resource and any child resources. * @return This object (for method chaining). */ - public RestContextBuilder allowedMethodParams(String...value) { - return set(REST_allowedMethodParams, StringUtils.join(value, ',')); + public RestContextBuilder contextPath(String contextPath) { + if (! contextPath.isEmpty()) + set(REST_contextPath, contextPath); + return this; } /** @@ -1632,64 +1732,6 @@ public class RestContextBuilder extends BeanContextBuilder implements ServletCon } /** - * Configuration property: REST call handler. - * - *

    - * This class handles the basic lifecycle of an HTTP REST call. - *
    Subclasses can be used to customize how these HTTP calls are handled. - - *

    - *

    Notes:
    - *
      - *
    • Property: {@link RestContext#REST_callHandler} - *
    • Annotations: - *
        - *
      • {@link RestResource#callHandler()} - *
      - *
    • Methods: - *
        - *
      • {@link RestContextBuilder#callHandler(Class)} - *
      • {@link RestContextBuilder#callHandler(RestCallHandler)} - *
      - *
    - * - * @param restHandler The new call handler for this resource. - * @return This object (for method chaining). - */ - public RestContextBuilder callHandler(Class restHandler) { - return set(REST_callHandler, restHandler); - } - - /** - * Configuration property: REST call handler. - * - *

    - * This class handles the basic lifecycle of an HTTP REST call. - *
    Subclasses can be used to customize how these HTTP calls are handled. - * - *

    - *

    Notes:
    - *
      - *
    • Property: {@link RestContext#REST_callHandler} - *
    • Annotations: - *
        - *
      • {@link RestResource#callHandler()} - *
      - *
    • Methods: - *
        - *
      • {@link RestContextBuilder#callHandler(Class)} - *
      • {@link RestContextBuilder#callHandler(RestCallHandler)} - *
      - *
    - * - * @param restHandler The new call handler for this resource. - * @return This object (for method chaining). - */ - public RestContextBuilder callHandler(RestCallHandler restHandler) { - return set(REST_callHandler, restHandler); - } - - /** * Configuration property: REST info provider. * *

    http://git-wip-us.apache.org/repos/asf/juneau/blob/b766e1d0/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestResourceResolver.java ---------------------------------------------------------------------- diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestResourceResolver.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestResourceResolver.java index aef11de..8489a29 100644 --- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestResourceResolver.java +++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestResourceResolver.java @@ -45,11 +45,13 @@ public interface RestResourceResolver { * *

    * The default implementation simply creates a new class instance using {@link Class#newInstance()}. - * + * + * @param parent + * The parent resource (i.e. the instance whose class has the {@link RestResource#children()} annotation. * @param c The class to resolve. * @param builder The initialization configuration for the resource. * @return The instance of that class. * @throws Exception If class could not be resolved. */ - Object resolve(Class c, RestContextBuilder builder) throws Exception; + Object resolve(Object parent, Class c, RestContextBuilder builder) throws Exception; } http://git-wip-us.apache.org/repos/asf/juneau/blob/b766e1d0/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestResourceResolverSimple.java ---------------------------------------------------------------------- diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestResourceResolverSimple.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestResourceResolverSimple.java index eda2fe2..0121558 100644 --- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestResourceResolverSimple.java +++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestResourceResolverSimple.java @@ -12,12 +12,10 @@ // *************************************************************************************************************************** package org.apache.juneau.rest; -import static org.apache.juneau.internal.ClassUtils.*; - -import java.lang.reflect.*; +import org.apache.juneau.internal.*; /** - * Denotes the default resolver. + * Denotes the default resolver for child resources. * * The default implementation simply instantiates the class using one of the following constructors: *

      @@ -29,6 +27,9 @@ import java.lang.reflect.*; * The former constructor can be used to get access to the {@link RestContextBuilder} object to get access to the * config file and initialization information or make programmatic modifications to the resource before * full initialization. + * + *

      + * Child classes can also be defined as inner-classes of the parent resource class. * *

      * Non-RestServlet classes can also add the following method to get access to the {@link RestContextBuilder} @@ -41,14 +42,11 @@ import java.lang.reflect.*; public class RestResourceResolverSimple implements RestResourceResolver { @Override /* RestResourceResolver */ - public Object resolve(Class c, RestContextBuilder builder) throws Exception { + public Object resolve(Object parent, Class c, RestContextBuilder builder) throws Exception { try { - Constructor c1 = findPublicConstructor(c, RestContextBuilder.class); - if (c1 != null) - return c1.newInstance(builder); - c1 = findPublicConstructor(c); - if (c1 != null) - return c1.newInstance(); + Object r = ClassUtils.newInstanceFromOuter(parent, Object.class, c, true, builder); + if (r != null) + return r; } catch (Exception e) { throw new RestServletException("Could not instantiate resource class ''{0}''", c.getName()).initCause(e); } http://git-wip-us.apache.org/repos/asf/juneau/blob/b766e1d0/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestResource.java ---------------------------------------------------------------------- diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestResource.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestResource.java index de0f449..58ccab0 100644 --- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestResource.java +++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestResource.java @@ -613,18 +613,21 @@ public @interface RestResource { String[] defaultResponseHeaders() default {}; /** + *Children. + * + *

      * Defines children of this resource. * *

      * A REST child resource is simply another servlet that is initialized as part of the parent resource and has a * servlet path directly under the parent servlet path. - * The main advantage to defining servlets as REST children is that you do not need to define them in the + *
      The main advantage to defining servlets as REST children is that you do not need to define them in the * web.xml file of the web application. - * This can cut down on the number of entries that show up in the web.xml file if you are defining + *
      This can cut down on the number of entries that show up in the web.xml file if you are defining * large numbers of servlets. * *

      - * Child resources must specify a value for {@link #path()} that identifies the subpath of the child resource + * Child resources must specify a value for {@link RestResource#path()} that identifies the subpath of the child resource * relative to the parent path. * *

      @@ -654,10 +657,28 @@ public @interface RestResource { *

      * * - * - *

      - * The programmatic equivalent to this annotation are the {@link RestContextBuilder#childResource(String, Object)}/ - * {@link RestContextBuilder#childResources(Class...)}/{@link RestContextBuilder#childResources(Object...)} methods. + * + *

      Notes:
      + *
        + *
      • Property: {@link RestContext#REST_children} + *
      • Annotations: + *
          + *
        • {@link RestResource#children()} + *
        + *
      • Methods: + *
          + *
        • {@link RestContextBuilder#child(String,Object)} + *
        • {@link RestContextBuilder#children(Class...)} + *
        • {@link RestContextBuilder#children(Object...)} + *
        + *
      • When defined as classes, instances are resolved using the registered {@link RestContext#REST_resourceResolver} which + * by default is {@link RestResourceResolverSimple} which requires the class have one of the following + * constructors: + *
          + *
        • public T(RestContextBuilder) + *
        • public T() + *
        + *
      */ Class[] children() default {}; http://git-wip-us.apache.org/repos/asf/juneau/blob/b766e1d0/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/package.html ---------------------------------------------------------------------- diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/package.html b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/package.html index ac9a814..b5a3441 100644 --- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/package.html +++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/package.html @@ -2065,18 +2065,18 @@ }

      - Children can also be defined programmatically by overriding any of the following methods: + Children can also be defined programmatically using any of the following methods:

      • {@link org.apache.juneau.rest.RestContextBuilder}
        • - {@link org.apache.juneau.rest.RestContextBuilder#childResource(String,Object)} + {@link org.apache.juneau.rest.RestContextBuilder#child(String,Object)}
        • - {@link org.apache.juneau.rest.RestContextBuilder#childResources(Class[])} + {@link org.apache.juneau.rest.RestContextBuilder#children(Class[])}
        • - {@link org.apache.juneau.rest.RestContextBuilder#childResources(Object[])} + {@link org.apache.juneau.rest.RestContextBuilder#children(Object[])}