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 3fb86c2 Context API refactoring.
3fb86c2 is described below
commit 3fb86c271437f61e8028349941b295e6b3687101
Author: JamesBognar <[email protected]>
AuthorDate: Sat Aug 28 19:39:29 2021 -0400
Context API refactoring.
---
.../java/org/apache/juneau/rest/RestContext.java | 338 ++-------------------
.../org/apache/juneau/rest/RestContextBuilder.java | 171 +++++++++--
.../org/apache/juneau/rest/annotation/Rest.java | 8 +-
.../juneau/rest/annotation/RestAnnotation.java | 8 +-
4 files changed, 172 insertions(+), 353 deletions(-)
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 44cb212..3e9df51 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
@@ -383,82 +383,6 @@ public class RestContext extends BeanContext {
public static final String REST_children = PREFIX + ".children.lo";
/**
- * Configuration property: REST context class.
- *
- * <h5 class='section'>Property:</h5>
- * <ul class='spaced-list'>
- * <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<? extends {@link
org.apache.juneau.rest.RestContext}></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#contextClass()}
- * </ul>
- * <li><b>Methods:</b>
- * <ul>
- * <li class='jm'>{@link
org.apache.juneau.rest.RestContextBuilder#contextClass(Class)}
- * </ul>
- * </ul>
- *
- * <h5 class='section'>Description:</h5>
- * <p>
- * Allows you to extend the {@link RestContext} 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 RestContextBuilder} - The builder for the object.
- * <li>Any beans found in the specified {@link #REST_beanStore
bean store}.
- * <li>Any {@link Optional} beans that may or may not be found in
the specified {@link #REST_beanStore bean store}.
- * </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> MyRestContext <jk>extends</jk> RestContext {
- *
- * <jk>private final</jk> Optional<? <jk>extends</jk>
Supplier<Object>> <jf>fooSupplier</jf>;
- *
- * <jc>// Constructor that takes in builder and optional
injected attribute provider.</jc>
- * <jk>public</jk> MyRestContext(RestContextBuilder
<jv>builder</jv>, Optional<AnInjectedFooSupplier> <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>, BeanStore
<jv>beanStore</jv>) <jk>throws</jk> Exception {
- * <jk>return super</jk>
- *
.createDefaultRequestAttributes(<jv>resource</jv>, <jv>beanStore</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>(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>.contextClass(MyRestContext.<jk>class</jk>);
- * }
- *
- * <ja>@RestGet</ja>
- * <jk>public</jk> Object foo(RequestAttributes
<jv>attributes</jv>) {
- * <jk>return</jk>
<jv>attributes</jv>.get(<js>"foo"</js>);
- * }
- * }
- * </p>
- */
- public static final String REST_contextClass = PREFIX + ".context.c";
-
- /**
* Configuration property: Class-level response converters.
*
* <h5 class='section'>Property:</h5>
@@ -1758,220 +1682,6 @@ public class RestContext extends BeanContext {
public static final String REST_responseProcessors = PREFIX +
".responseProcessors.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<? extends {@link
org.apache.juneau.rest.RestChildren}></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_beanStore
bean store}.
- * <li>Any {@link Optional} beans that may or may not be found in
the specified {@link #REST_beanStore bean store}.
- * </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<AnOptionalSpringBean> <jv>bean2</jv>) {
- * <jk>super</jk>(<jv>builder</jv>);
- * }
- *
- * <jc>// Override any methods.</jc>
- *
- * <ja>@Override</ja>
- * <jk>public</jk> Optional<RestChildMatch>
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 operation context class.
- *
- * <h5 class='section'>Property:</h5>
- * <ul class='spaced-list'>
- * <li><b>ID:</b> {@link
org.apache.juneau.rest.RestContext#REST_restOperationContextClass
REST_restOperationContextClass}
- * <li><b>Name:</b>
<js>"RestContext.restOperationContextClass.c"</js>
- * <li><b>Data type:</b> <c>Class<? extends {@link
org.apache.juneau.rest.RestOpContext}></c>
- * <li><b>Default:</b> {@link
org.apache.juneau.rest.RestOpContext}
- * <li><b>Session property:</b> <jk>false</jk>
- * <li><b>Annotations:</b>
- * <ul>
- * <li class='ja'>{@link
org.apache.juneau.rest.annotation.Rest#restOpContextClass()}
- * <li class='ja'>{@link
org.apache.juneau.rest.annotation.RestOp#contextClass()}
- * </ul>
- * <li><b>Methods:</b>
- * <ul>
- * <li class='jm'>{@link
org.apache.juneau.rest.RestContextBuilder#restOpContextClass(Class)}
- * <li class='jm'>{@link
org.apache.juneau.rest.RestOpContextBuilder#contextClass(Class)}
- * </ul>
- * </ul>
- *
- * <h5 class='section'>Description:</h5>
- * <p>
- * Allows you to extend the {@link RestOpContext} 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 RestOpContextBuilder} - The builder for the object.
- * <li>Any beans found in the specified {@link #REST_beanStore
bean store}.
- * <li>Any {@link Optional} beans that may or may not be found in
the specified {@link #REST_beanStore bean store}.
- * </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> MyRestOperationContext <jk>extends</jk>
RestOpContext {
- *
- * <jk>private final</jk> Optional<? <jk>extends</jk>
Supplier<Object>> <jf>fooSupplier</jf>;
- *
- * <jc>// Constructor that takes in builder and optional
injected attribute provider.</jc>
- * <jk>public</jk>
MyRestOperationContext(RestOpContextBuilder <jv>builder</jv>,
Optional<AnInjectedFooSupplier> <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>, BeanStore
<jv>beanStore</jv>, Method <jv>method</jv>, RestContext <jv>context</jv>)
<jk>throws</jk> Exception {
- * <jk>return super</jk>
- *
.createDefaultRequestAttributes(<jv>resource</jv>, <jv>beanStore</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>(restOpContextClass=MyRestOperationContext.<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(MyRestOperationContext.<jk>class</jk>);
- * }
- *
- * <ja>@RestGet</ja>
- * <jk>public</jk> Object foo(RequestAttributes
<jv>attributes</jv>) {
- * <jk>return</jk>
<jv>attributes</jv>.get(<js>"foo"</js>);
- * }
- * }
- * </p>
- */
- public static final String REST_restOperationContextClass = PREFIX +
".restOperationContextClass.c";
-
- /**
- * Configuration property: REST operations class.
- *
- * <h5 class='section'>Property:</h5>
- * <ul class='spaced-list'>
- * <li><b>ID:</b> {@link
org.apache.juneau.rest.RestContext#REST_restOperationsClass
REST_restOperationsClass}
- * <li><b>Name:</b> <js>"RestContext.restOperationsClass.c"</js>
- * <li><b>Data type:</b> <c>Class<? extends {@link
org.apache.juneau.rest.RestOperations}></c>
- * <li><b>Default:</b> {@link
org.apache.juneau.rest.RestOperations}
- * <li><b>Session property:</b> <jk>false</jk>
- * <li><b>Annotations:</b>
- * <ul>
- * <li class='ja'>{@link
org.apache.juneau.rest.annotation.Rest#restOperationsClass()}
- * </ul>
- * <li><b>Methods:</b>
- * <ul>
- * <li class='jm'>{@link
org.apache.juneau.rest.RestContextBuilder#restOperationsClass(Class)}
- * </ul>
- * </ul>
- *
- * <h5 class='section'>Description:</h5>
- * <p>
- * Allows you to extend the {@link RestOperations} 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 RestOperationsBuilder} - The builder for the object.
- * <li>Any beans found in the specified {@link #REST_beanStore
bean store}.
- * <li>Any {@link Optional} beans that may or may not be found in
the specified {@link #REST_beanStore bean store}.
- * </ul>
- *
- * <h5 class='section'>Example:</h5>
- * <p class='bcode w800'>
- * <jc>// Our extended context class</jc>
- * <jk>public</jk> MyRestOperations <jk>extends</jk>
RestOperations {
- * <jk>public</jk> MyRestOperations(RestOperationsBuilder
<jv>builder</jv>, ARequiredSpringBean <jv>bean1</jv>,
Optional<AnOptionalSpringBean> <jv>bean2</jv>) {
- * <jk>super</jk>(<jv>builder</jv>);
- * }
- *
- * <jc>// Override any methods.</jc>
- *
- * <ja>@Override</ja>
- * <jk>public</jk> RestOpContext 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=MyRestOperations.<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(MyRestOperations.<jk>class</jk>);
- * }
- * }
- * </p>
- */
- public static final String REST_restOperationsClass = PREFIX +
".restOperationsClass.c";
-
- /**
* Configuration property: Java REST method parameter resolvers.
*
* <h5 class='section'>Property:</h5>
@@ -2675,7 +2385,7 @@ public class RestContext extends BeanContext {
preCallMethods = createPreCallMethods(r, cp,
bf).stream().map(this::toRestOpInvoker).toArray(RestOpInvoker[]:: new);
postCallMethods = createPostCallMethods(r, cp,
bf).stream().map(this::toRestOpInvoker).toArray(RestOpInvoker[]:: new);
- restOperations = createRestOperations(r, cp, bf);
+ restOperations = createRestOperations(r, builder, bf);
List<RestOpContext> opContexts =
restOperations.getOpContexts();
@@ -2695,7 +2405,7 @@ public class RestContext extends BeanContext {
consumes = AList.unmodifiable(s);
}
- restChildren = createRestChildren(r, cp, bf,
builder.inner);
+ restChildren = createRestChildren(r, builder, bf,
builder.inner);
swaggerProvider = createSwaggerProvider(r, cp, bf, ff,
m, vr);
@@ -4356,18 +4066,17 @@ public class RestContext extends BeanContext {
*
* @param resource
* The REST servlet or bean that this context defines.
- * @param properties
- * The properties of this bean.
- * <br>Consists of all properties gathered through the builder and
annotations on this class and all parent classes.
+ * @param builder
+ * The builder for this object.
* @param beanStore
* The factory used for creating beans and retrieving injected
beans.
* <br>Created by {@link
#createBeanStore(Object,ContextProperties,RestContext)}.
* @return The builder for the {@link RestOperations} object.
* @throws Exception An error occurred.
*/
- protected RestOperations createRestOperations(Object resource,
ContextProperties properties, BeanStore beanStore) throws Exception {
+ protected RestOperations createRestOperations(Object resource,
RestContextBuilder builder, BeanStore beanStore) throws Exception {
- RestOperations x = createRestOperationsBuilder(resource,
properties, beanStore).build();
+ RestOperations x = createRestOperationsBuilder(resource,
builder, beanStore).build();
x = BeanStore
.of(beanStore, resource)
@@ -4384,25 +4093,24 @@ public class RestContext extends BeanContext {
* Instantiates the REST methods builder for this REST resource.
*
* <p>
- * Allows subclasses to intercept and modify the builder used by the
{@link #createRestOperations(Object,ContextProperties,BeanStore)} method.
+ * Allows subclasses to intercept and modify the builder used by the
{@link #createRestOperations(Object,RestContextBuilder,BeanStore)} method.
*
* @param resource
* The REST servlet or bean that this context defines.
- * @param properties
- * The properties of this bean.
- * <br>Consists of all properties gathered through the builder and
annotations on this class and all parent classes.
+ * @param builder
+ * The builder for this object.
* @param beanStore
* The factory used for creating beans and retrieving injected
beans.
* <br>Created by {@link
#createBeanStore(Object,ContextProperties,RestContext)}.
* @return The REST methods builder for this REST resource.
* @throws Exception If REST methods builder could not be instantiated.
*/
- protected RestOperationsBuilder createRestOperationsBuilder(Object
resource, ContextProperties properties, BeanStore beanStore) throws Exception {
+ protected RestOperationsBuilder createRestOperationsBuilder(Object
resource, RestContextBuilder builder, BeanStore beanStore) throws Exception {
RestOperationsBuilder x = RestOperations
.create()
.beanStore(beanStore)
-
.implClass(properties.getClass(REST_restOperationsClass,
RestOperations.class).orElse(null));
+ .implClass(builder.operationsClass);
ClassInfo rci = ClassInfo.of(resource);
@@ -4426,7 +4134,7 @@ public class RestContext extends BeanContext {
RestOpContext roc = RestOpContext
.create(mi.inner(), this)
.beanStore(beanStore)
-
.contextClass(properties.getClass(REST_restOperationContextClass,
RestOpContext.class).orElse(null))
+
.contextClass(builder.opContextClass)
.build();
String httpMethod = roc.getHttpMethod();
@@ -4471,9 +4179,8 @@ public class RestContext extends BeanContext {
*
* @param resource
* The REST servlet or bean that this context defines.
- * @param properties
- * The properties of this bean.
- * <br>Consists of all properties gathered through the builder and
annotations on this class and all parent classes.
+ * @param builder
+ * The builder for this object.
* @param beanStore
* The factory used for creating beans and retrieving injected
beans.
* <br>Created by {@link
#createBeanStore(Object,ContextProperties,RestContext)}.
@@ -4482,9 +4189,9 @@ public class RestContext extends BeanContext {
* @return The builder for the {@link RestChildren} object.
* @throws Exception An error occurred.
*/
- protected RestChildren createRestChildren(Object resource,
ContextProperties properties, BeanStore beanStore, ServletConfig servletConfig)
throws Exception {
+ protected RestChildren createRestChildren(Object resource,
RestContextBuilder builder, BeanStore beanStore, ServletConfig servletConfig)
throws Exception {
- RestChildren x = createRestChildrenBuilder(resource,
properties, beanStore, servletConfig).build();
+ RestChildren x = createRestChildrenBuilder(resource, builder,
beanStore, servletConfig).build();
x = BeanStore
.of(beanStore, resource)
@@ -4501,13 +4208,12 @@ public class RestContext extends BeanContext {
* Instantiates the REST children builder for this REST resource.
*
* <p>
- * Allows subclasses to intercept and modify the builder used by the
{@link #createRestChildren(Object,ContextProperties,BeanStore,ServletConfig)}
method.
+ * Allows subclasses to intercept and modify the builder used by the
{@link #createRestChildren(Object,RestContextBuilder,BeanStore,ServletConfig)}
method.
*
* @param resource
* The REST servlet or bean that this context defines.
- * @param properties
- * The properties of this bean.
- * <br>Consists of all properties gathered through the builder and
annotations on this class and all parent classes.
+ * @param builder
+ * The builder for this object.
* @param beanStore
* The factory used for creating beans and retrieving injected
beans.
* <br>Created by {@link
#createBeanStore(Object,ContextProperties,RestContext)}.
@@ -4516,15 +4222,15 @@ public class RestContext extends BeanContext {
* @return The REST children builder for this REST resource.
* @throws Exception If REST children builder could not be instantiated.
*/
- protected RestChildrenBuilder createRestChildrenBuilder(Object
resource, ContextProperties properties, BeanStore beanStore, ServletConfig
servletConfig) throws Exception {
+ protected RestChildrenBuilder createRestChildrenBuilder(Object
resource, RestContextBuilder builder, BeanStore beanStore, ServletConfig
servletConfig) throws Exception {
RestChildrenBuilder x = RestChildren
.create()
.beanStore(beanStore)
- .implClass(properties.getClass(REST_restChildrenClass,
RestChildren.class).orElse(null));
+ .implClass(builder.childrenClass);
// Initialize our child resources.
- for (Object o : properties.getArray(REST_children,
Object.class).orElse(new Object[0])) {
+ for (Object o :
builder.getContextProperties().getArray(REST_children, Object.class).orElse(new
Object[0])) {
String path = null;
if (o instanceof RestChild) {
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 5843142..a4130e2 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
@@ -118,9 +118,13 @@ public class RestContextBuilder extends BeanContextBuilder
implements ServletCon
Charset defaultCharset;
long maxInput;
List<MediaType> consumes, produces;
+ Class<? extends RestChildren> childrenClass = RestChildren.class;
+ Class<? extends RestOpContext> opContextClass = RestOpContext.class;
+ Class<? extends RestOperations> operationsClass = RestOperations.class;
RestContextBuilder(Optional<RestContext> parentContext,
Optional<ServletConfig> servletConfig, Class<?> resourceClass, Optional<Object>
resource) throws ServletException {
try {
+ contextClass(RestContext.class);
this.resourceClass = resourceClass;
this.inner = servletConfig.orElse(null);
@@ -210,32 +214,16 @@ public class RestContextBuilder extends
BeanContextBuilder implements ServletCon
throw new NoSuchMethodError("Not implemented.");
}
- @SuppressWarnings("unchecked")
@Override /* BeanContextBuilder */
public RestContext build() {
try {
- // Temporary.
- Class<? extends RestContext> c =
getContextProperties().getClass(REST_contextClass,
RestContext.class).orElse(null);
- if (c != null)
- contextClass(c);
-
- c = (Class<? extends
RestContext>)getContextClass().orElse(getDefaultImplClass());
- return BeanStore.of(beanStore,
resource.get()).addBeans(RestContextBuilder.class, this).createBean(c);
+ return (RestContext) BeanStore.of(beanStore,
resource.get()).addBeans(RestContextBuilder.class,
this).createBean(getContextClass().orElse(RestContext.class));
} catch (Exception e) {
throw toHttpException(e, InternalServerError.class);
}
}
/**
- * Specifies the default implementation class if not specified via
{@link RestContext#REST_contextClass}.
- *
- * @return The default implementation class if not specified via {@link
RestContext#REST_contextClass}.
- */
- protected Class<? extends RestContext> getDefaultImplClass() {
- return RestContext.class;
- }
-
- /**
* Creates the bean store for this builder.
*
* @param parentContext The parent context if there is one.
@@ -1870,39 +1858,125 @@ public class RestContextBuilder extends
BeanContextBuilder implements ServletCon
}
/**
- * <i><l>RestContext</l> configuration property: </i> REST
children class.
+ * 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}
+ * <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_beanStore
bean store}.
+ * <li>Any {@link Optional} beans that may or may not be found in
the specified {@link #REST_beanStore bean store}.
* </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<AnOptionalSpringBean> <jv>bean2</jv>) {
+ * <jk>super</jk>(<jv>builder</jv>);
+ * }
+ *
+ * <jc>// Override any methods.</jc>
+ *
+ * <ja>@Override</ja>
+ * <jk>public</jk> Optional<RestChildMatch>
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>
+ *
* @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);
+ childrenClass = value;
+ return this;
}
/**
- * <i><l>RestContext</l> configuration property: </i> REST method
context class.
+ * REST operation context class.
*
* <p>
* Allows you to extend the {@link RestOpContext} class to modify how
any of the methods are implemented.
*
- * <ul class='seealso'>
- * <li class='jf'>{@link
RestContext#REST_restOperationContextClass}
+ * <p>
+ * The subclass must have a public constructor that takes in any of the
following arguments:
+ * <ul>
+ * <li>{@link RestOpContextBuilder} - The builder for the object.
+ * <li>Any beans found in the specified {@link #REST_beanStore
bean store}.
+ * <li>Any {@link Optional} beans that may or may not be found in
the specified {@link #REST_beanStore bean store}.
* </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> MyRestOperationContext <jk>extends</jk>
RestOpContext {
+ *
+ * <jk>private final</jk> Optional<? <jk>extends</jk>
Supplier<Object>> <jf>fooSupplier</jf>;
+ *
+ * <jc>// Constructor that takes in builder and optional
injected attribute provider.</jc>
+ * <jk>public</jk>
MyRestOperationContext(RestOpContextBuilder <jv>builder</jv>,
Optional<AnInjectedFooSupplier> <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>, BeanStore
<jv>beanStore</jv>, Method <jv>method</jv>, RestContext <jv>context</jv>)
<jk>throws</jk> Exception {
+ * <jk>return super</jk>
+ *
.createDefaultRequestAttributes(<jv>resource</jv>, <jv>beanStore</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>(restOpContextClass=MyRestOperationContext.<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(MyRestOperationContext.<jk>class</jk>);
+ * }
+ *
+ * <ja>@RestGet</ja>
+ * <jk>public</jk> Object foo(RequestAttributes
<jv>attributes</jv>) {
+ * <jk>return</jk>
<jv>attributes</jv>.get(<js>"foo"</js>);
+ * }
+ * }
+ * </p>
+ *
* @param value The new value for this setting.
* @return This object (for method chaining).
*/
@FluentSetter
public RestContextBuilder restOpContextClass(Class<? extends
RestOpContext> value) {
- return set(REST_restOperationContextClass, value);
+ opContextClass = value;
+ return this;
}
/**
@@ -1927,21 +2001,60 @@ public class RestContextBuilder extends
BeanContextBuilder implements ServletCon
}
/**
- * <i><l>RestContext</l> configuration property: </i> REST
methods class.
+ * REST operations class.
*
* <p>
* Allows you to extend the {@link RestOperations} class to modify how
any of the methods are implemented.
*
- * <ul class='seealso'>
- * <li class='jf'>{@link RestContext#REST_restOperationsClass}
+ * <p>
+ * The subclass must have a public constructor that takes in any of the
following arguments:
+ * <ul>
+ * <li>{@link RestOperationsBuilder} - The builder for the object.
+ * <li>Any beans found in the specified {@link #REST_beanStore
bean store}.
+ * <li>Any {@link Optional} beans that may or may not be found in
the specified {@link #REST_beanStore bean store}.
* </ul>
*
+ * <h5 class='section'>Example:</h5>
+ * <p class='bcode w800'>
+ * <jc>// Our extended context class</jc>
+ * <jk>public</jk> MyRestOperations <jk>extends</jk>
RestOperations {
+ * <jk>public</jk> MyRestOperations(RestOperationsBuilder
<jv>builder</jv>, ARequiredSpringBean <jv>bean1</jv>,
Optional<AnOptionalSpringBean> <jv>bean2</jv>) {
+ * <jk>super</jk>(<jv>builder</jv>);
+ * }
+ *
+ * <jc>// Override any methods.</jc>
+ *
+ * <ja>@Override</ja>
+ * <jk>public</jk> RestOpContext 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=MyRestOperations.<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(MyRestOperations.<jk>class</jk>);
+ * }
+ * }
+ * </p>
+ *
* @param value The new value for this setting.
* @return This object (for method chaining).
*/
@FluentSetter
public RestContextBuilder restOperationsClass(Class<? extends
RestOperations> value) {
- return set(REST_restOperationsClass, value);
+ operationsClass = value;
+ return this;
}
/**
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 9c2193d..ff3bf3d 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
@@ -278,7 +278,7 @@ public @interface Rest {
* Allows you to extend the {@link RestContext} class to modify how any
of the methods are implemented.
*
* <ul class='seealso'>
- * <li class='jm'>{@link RestContext#REST_contextClass}
+ * <li class='jm'>{@link RestContextBuilder#contextClass(Class)}
* </ul>
*/
Class<? extends RestContext> contextClass() default
RestContext.Null.class;
@@ -940,7 +940,7 @@ public @interface Rest {
* 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}
+ * <li class='jm'>{@link
RestContextBuilder#restChildrenClass(Class)}
* </ul>
*/
Class<? extends RestChildren> restChildrenClass() default
RestChildren.Null.class;
@@ -952,7 +952,7 @@ public @interface Rest {
* Allows you to extend the {@link RestOperations} class to modify how
any of the methods are implemented.
*
* <ul class='seealso'>
- * <li class='jf'>{@link RestContext#REST_restOperationsClass}
+ * <li class='jm'>{@link
RestContextBuilder#restOperationsClass(Class)}
* </ul>
*/
Class<? extends RestOperations> restOperationsClass() default
RestOperations.Null.class;
@@ -961,7 +961,7 @@ public @interface Rest {
* Allows you to extend the {@link RestOpContext} class to modify how
any of the methods are implemented.
*
* <ul class='seealso'>
- * <li class='jf'>{@link
RestContext#REST_restOperationContextClass}
+ * <li class='jm'>{@link
RestContextBuilder#restOpContextClass(Class)}
* </ul>
*/
Class<? extends RestOpContext> restOpContextClass() default
RestOpContext.Null.class;
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 73d5ec0..2328c19 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
@@ -1053,7 +1053,7 @@ public class RestAnnotation {
b.prependTo(REST_responseProcessors,
a.responseProcessors());
b.prependTo(REST_children, a.children());
b.prependTo(REST_restOperationArgs, a.restOpArgs());
- b.setIf(a.contextClass() != RestContext.Null.class,
REST_contextClass, a.contextClass());
+ value(a.contextClass(),
RestContext.Null.class).ifPresent(x -> b.contextClass(x));
value(a.uriContext()).ifPresent(x -> b.uriContext(x));
value(a.uriAuthority()).ifPresent(x ->
b.uriAuthority(x));
value(a.uriRelativity()).map(UriRelativity::valueOf).ifPresent(x ->
b.uriRelativity(x));
@@ -1066,9 +1066,9 @@ public class RestAnnotation {
b.setIf(a.beanStore() != BeanStore.Null.class,
REST_beanStore, a.beanStore());
b.setIf(a.callLogger() != RestLogger.Null.class,
REST_callLogger, a.callLogger());
b.setIf(a.swaggerProvider() !=
SwaggerProvider.Null.class, REST_swaggerProvider, a.swaggerProvider());
- b.setIf(a.restOpContextClass() !=
RestOpContext.Null.class, REST_restOperationContextClass,
a.restOpContextClass());
- b.setIf(a.restChildrenClass() !=
RestChildren.Null.class, REST_restChildrenClass, a.restChildrenClass());
- b.setIf(a.restOperationsClass() !=
RestOperations.Null.class, REST_restOperationsClass, a.restOperationsClass());
+ value(a.restOpContextClass(),
RestOpContext.Null.class).ifPresent(x -> b.restOpContextClass(x));
+ value(a.restChildrenClass(),
RestChildren.Null.class).ifPresent(x -> b.restChildrenClass(x));
+ value(a.restOperationsClass(),
RestOperations.Null.class).ifPresent(x -> b.restOperationsClass(x));
b.setIf(a.debugEnablement() !=
DebugEnablement.Null.class, REST_debugEnablement, a.debugEnablement());
b.setIfNotEmpty(REST_disableAllowBodyParam,
bool(a.disableAllowBodyParam()));
value(a.allowedHeaderParams()).ifPresent(x ->
b.allowedHeaderParams(x));