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 f363702 Context API refactoring.
f363702 is described below
commit f36370246c04d152479bf74552e228d556b7872a
Author: JamesBognar <[email protected]>
AuthorDate: Mon Sep 13 19:34:46 2021 -0400
Context API refactoring.
---
.../java/org/apache/juneau/rest/RestContext.java | 116 +----------------
.../org/apache/juneau/rest/RestContextBuilder.java | 104 +++++++++++++++-
.../org/apache/juneau/rest/RestOperations.java | 137 +++++++++++++++++++--
.../apache/juneau/rest/RestOperationsBuilder.java | 116 -----------------
4 files changed, 234 insertions(+), 239 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 92cb97b..2abf3a9 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
@@ -294,11 +294,10 @@ public class RestContext extends Context {
destroyMethods =
builder.destroyMethods().stream().map(this::toMethodInvoker).toArray(MethodInvoker[]::new);
preCallMethods =
builder.preCallMethods().stream().map(this::toRestOpInvoker).toArray(RestOpInvoker[]::
new);
postCallMethods =
builder.postCallMethods().stream().map(this::toRestOpInvoker).toArray(RestOpInvoker[]::
new);
+ restOperations = builder.restOperations(this).build();
Object r = resource.get();
- restOperations = createRestOperations(r, builder, bs);
-
List<RestOpContext> opContexts =
restOperations.getOpContexts();
if (builder.produces != null)
@@ -464,119 +463,6 @@ public class RestContext extends Context {
}
/**
- * Creates the set of {@link RestOpContext} objects that represent the
methods on this resource.
- *
- * @param resource
- * The REST servlet or bean that this context defines.
- * @param builder
- * The builder for this object.
- * @param beanStore
- * The factory used for creating beans and retrieving injected
beans.
- * <br>Created by {@link RestContextBuilder#beanStore()}.
- * @return The builder for the {@link RestOperations} object.
- * @throws Exception An error occurred.
- */
- protected RestOperations createRestOperations(Object resource,
RestContextBuilder builder, BeanStore beanStore) throws Exception {
-
- RestOperations x = createRestOperationsBuilder(resource,
builder, beanStore).build();
-
- x = BeanStore
- .of(beanStore, resource)
- .addBean(RestOperations.class, x)
- .beanCreateMethodFinder(RestOperations.class, resource)
- .find("createRestOperations")
- .withDefault(x)
- .run();
-
- return x;
- }
-
- /**
- * Instantiates the REST methods builder for this REST resource.
- *
- * <p>
- * 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 builder
- * The builder for this object.
- * @param beanStore
- * The factory used for creating beans and retrieving injected
beans.
- * <br>Created by {@link RestContextBuilder#beanStore()}.
- * @return The REST methods builder for this REST resource.
- * @throws Exception If REST methods builder could not be instantiated.
- */
- protected RestOperationsBuilder createRestOperationsBuilder(Object
resource, RestContextBuilder builder, BeanStore beanStore) throws Exception {
-
- RestOperationsBuilder x = RestOperations
- .create()
- .beanStore(beanStore)
- .implClass(builder.operationsClass);
-
- ClassInfo rci = ClassInfo.of(resource);
-
- for (MethodInfo mi : rci.getPublicMethods()) {
- AnnotationList al =
mi.getAnnotationGroupList(RestOp.class);
-
- // Also include methods on @Rest-annotated interfaces.
- if (al.size() == 0) {
- for (Method mi2 : mi.getMatching()) {
- Class<?> ci2 = mi2.getDeclaringClass();
- if (ci2.isInterface() &&
ci2.getAnnotation(Rest.class) != null) {
-
al.add(AnnotationInfo.of(MethodInfo.of(mi2), RestOpAnnotation.DEFAULT));
- }
- }
- }
- if (al.size() > 0) {
- try {
- if (mi.isNotPublic())
- throw new
RestServletException("@RestOp method {0}.{1} must be defined as public.",
rci.inner().getName(), mi.getSimpleName());
-
- RestOpContext roc = RestOpContext
- .create(mi.inner(), this)
- .beanStore(beanStore)
- .type(builder.opContextClass)
- .build();
-
- String httpMethod = roc.getHttpMethod();
-
- // RRPC is a special case where a
method returns an interface that we
- // can perform REST calls against.
- // We override the CallMethod.invoke()
method to insert our logic.
- if ("RRPC".equals(httpMethod)) {
-
- RestOpContext roc2 =
RestOpContext
- .create(mi.inner(),
this)
- .dotAll()
-
.beanStore(rootBeanStore)
-
.type(RrpcRestOpContext.class)
- .build();
- x
- .add("GET", roc2)
- .add("POST", roc2);
-
- } else {
- x.add(roc);
- }
- } catch (Throwable e) {
- throw new RestServletException(e,
"Problem occurred trying to initialize methods on class {0}",
rci.inner().getName());
- }
- }
- }
-
- x = BeanStore
- .of(beanStore, resource)
- .addBean(RestOperationsBuilder.class, x)
- .beanCreateMethodFinder(RestOperationsBuilder.class,
resource)
- .find("createRestOperationsBuilder")
- .withDefault(x)
- .run();
-
- return x;
- }
-
- /**
* Creates the builder for the children of this resource.
*
* @param resource
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 d46d5c0..6df09eb 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
@@ -145,6 +145,7 @@ public class RestContextBuilder extends ContextBuilder
implements ServletConfig
private RestOpArgList.Builder restOpArgs, hookMethodArgs;
private DebugEnablement.Builder debugEnablement;
private MethodList startCallMethods, endCallMethods, postInitMethods,
postInitChildFirstMethods, destroyMethods, preCallMethods, postCallMethods;
+ private RestOperations.Builder restOperations;
String
allowedHeaderParams = env("RestContext.allowedHeaderParams",
"Accept,Content-Type"),
@@ -3069,6 +3070,107 @@ public class RestContextBuilder extends ContextBuilder
implements ServletConfig
return v.get();
}
+
//-----------------------------------------------------------------------------------------------------------------
+ // restOperations
+
//-----------------------------------------------------------------------------------------------------------------
+
+ /**
+ * Returns the list of rest operations.
+ *
+ * @param restContext The rest context.
+ * @return The list of rest operations.
+ * @throws RestServletException If a problem occurred instantiating one
of the child rest contexts.
+ */
+ public final RestOperations.Builder restOperations(RestContext
restContext) throws RestServletException {
+ if (restOperations == null)
+ restOperations = createRestOperations(beanStore(),
resource(), restContext);
+ return restOperations;
+ }
+
+ /**
+ * Creates the set of {@link RestOpContext} objects that represent the
methods on this resource.
+ *
+ * @param restContext The rest context.
+ * @param beanStore
+ * The factory used for creating beans and retrieving injected
beans.
+ * @param resource
+ * The REST servlet or bean that this context defines.
+ * @return The default response headers for this REST object.
+ * @throws RestServletException If a problem occurred instantiating one
of the child rest contexts.
+ */
+ protected RestOperations.Builder createRestOperations(BeanStore
beanStore, Supplier<?> resource, RestContext restContext) throws
RestServletException {
+
+ Value<RestOperations.Builder> v =
Value.of(RestOperations.create());
+ Object r = resource.get();
+
+ ClassInfo rci = ClassInfo.of(r);
+
+ for (MethodInfo mi : rci.getPublicMethods()) {
+ AnnotationList al =
mi.getAnnotationGroupList(RestOp.class);
+
+ // Also include methods on @Rest-annotated interfaces.
+ if (al.size() == 0) {
+ for (Method mi2 : mi.getMatching()) {
+ Class<?> ci2 = mi2.getDeclaringClass();
+ if (ci2.isInterface() &&
ci2.getAnnotation(Rest.class) != null) {
+
al.add(AnnotationInfo.of(MethodInfo.of(mi2), RestOpAnnotation.DEFAULT));
+ }
+ }
+ }
+ if (al.size() > 0) {
+ try {
+ if (mi.isNotPublic())
+ throw new
RestServletException("@RestOp method {0}.{1} must be defined as public.",
rci.inner().getName(), mi.getSimpleName());
+
+ RestOpContext roc = RestOpContext
+ .create(mi.inner(), restContext)
+ .beanStore(beanStore)
+ .type(opContextClass)
+ .build();
+
+ String httpMethod = roc.getHttpMethod();
+
+ // RRPC is a special case where a
method returns an interface that we
+ // can perform REST calls against.
+ // We override the CallMethod.invoke()
method to insert our logic.
+ if ("RRPC".equals(httpMethod)) {
+
+ RestOpContext roc2 =
RestOpContext
+ .create(mi.inner(),
restContext)
+ .dotAll()
+
.beanStore(restContext.getRootBeanStore())
+
.type(RrpcRestOpContext.class)
+ .build();
+ v.get()
+ .add("GET", roc2)
+ .add("POST", roc2);
+
+ } else {
+ v.get().add(roc);
+ }
+ } catch (Throwable e) {
+ throw new RestServletException(e,
"Problem occurred trying to initialize methods on class {0}",
rci.inner().getName());
+ }
+ }
+ }
+
+ BeanStore
+ .of(beanStore, r)
+ .addBean(RestOperations.Builder.class, v.get())
+ .beanCreateMethodFinder(RestOperations.Builder.class, r)
+ .find("createRestOperationsBuilder")
+ .run(x -> v.set(x));
+
+ BeanStore
+ .of(beanStore, r)
+ .addBean(RestOperations.Builder.class, v.get())
+ .beanCreateMethodFinder(RestOperations.class, r)
+ .find("createRestOperations")
+ .run(x -> v.get().impl(x));
+
+ return v.get();
+ }
+
private int TODO;
//-----------------------------------------------------------------------------------------------------------------
@@ -4213,7 +4315,7 @@ public class RestContextBuilder extends ContextBuilder
implements ServletConfig
* <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>{@link RestOperations.Builder} - The builder for the object.
* <li>Any beans found in the specified bean store.
* <li>Any {@link Optional} beans that may or may not be found in
the specified bean store.
* </ul>
diff --git
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestOperations.java
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestOperations.java
index 9255fdbf..340a92c 100644
---
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestOperations.java
+++
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestOperations.java
@@ -13,10 +13,13 @@
package org.apache.juneau.rest;
import static org.apache.juneau.internal.ClassUtils.*;
+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.response.*;
import org.apache.juneau.rest.annotation.*;
@@ -25,34 +28,154 @@ import org.apache.juneau.rest.annotation.*;
*/
public class RestOperations {
+
//-----------------------------------------------------------------------------------------------------------------
+ // Static
+
//-----------------------------------------------------------------------------------------------------------------
+
/**
* Represents a null value for the {@link Rest#restOperationsClass()}
annotation.
*/
@SuppressWarnings("javadoc")
public final class Null extends RestOperations {
- public Null(RestOperationsBuilder builder) throws Exception {
+ public Null(Builder builder) throws Exception {
super(builder);
}
}
- private final Map<String,List<RestOpContext>> map;
- private List<RestOpContext> list;
-
/**
* Creates a new builder.
*
* @return A new builder.
*/
- public static RestOperationsBuilder create() {
- return new RestOperationsBuilder();
+ public static Builder create() {
+ return new Builder();
}
+
//-----------------------------------------------------------------------------------------------------------------
+ // Builder
+
//-----------------------------------------------------------------------------------------------------------------
+
+ /**
+ * Builder class.
+ */
+ public static class Builder {
+
+ TreeMap<String,TreeSet<RestOpContext>> map = new TreeMap<>();
+ Set<RestOpContext> set = ASet.of();
+
+ private BeanStore beanStore;
+ private Class<? extends RestOperations> type;
+ private RestOperations impl;
+
+ /**
+ * Instantiates a {@link RestOperations} object based on the
contents of this builder.
+ *
+ * @return A new {@link RestOperations} object.
+ */
+ public RestOperations build() {
+ try {
+ if (impl != null)
+ return impl;
+ Class<? extends RestOperations> ic =
firstNonNull(type, getDefaultImplClass());
+ return
BeanStore.of(beanStore).addBeans(Builder.class, this).createBean(ic);
+ } catch (Exception e) {
+ throw toHttpException(e,
InternalServerError.class);
+ }
+ }
+
+ /**
+ * Specifies the default implementation class if not specified
via {@link #type(Class)}.
+ *
+ * @return The default implementation class if not specified
via {@link #type(Class)}.
+ */
+ protected Class<? extends RestOperations> getDefaultImplClass()
{
+ return RestOperations.class;
+ }
+
+ /**
+ * Adds a method context to this builder.
+ *
+ * @param value The REST method context to add.
+ * @return Adds a method context to this builder.
+ */
+ public Builder add(RestOpContext value) {
+ return add(value.getHttpMethod(), value);
+ }
+
+ /**
+ * Adds a method context to this builder.
+ *
+ * @param httpMethodName The HTTP method name.
+ * @param value The REST method context to add.
+ * @return Adds a method context to this builder.
+ */
+ public Builder add(String httpMethodName, RestOpContext value) {
+ httpMethodName = httpMethodName.toUpperCase();
+ if (! map.containsKey(httpMethodName))
+ map.put(httpMethodName, new TreeSet<>());
+ map.get(httpMethodName).add(value);
+ set.add(value);
+ return this;
+ }
+
+ /**
+ * Specifies a {@link RestOperations} implementation subclass
to use.
+ *
+ * <p>
+ * When specified, the {@link #build()} method will create an
instance of that class instead of the default {@link RestOperations}.
+ *
+ * <p>
+ * The subclass must have a public constructor that takes in
any of the following arguments:
+ * <ul>
+ * <li>{@link Builder} - This object.
+ * <li>Any beans found in the specified {@link
#beanStore(BeanStore) bean store}.
+ * <li>Any {@link Optional} beans that may or may not be
found in the specified {@link #beanStore(BeanStore) bean store}.
+ * </ul>
+ *
+ * @param value The implementation class to build.
+ * @return This object.
+ */
+ public Builder type(Class<? extends RestOperations> value) {
+ type = value;
+ return this;
+ }
+
+ /**
+ * Specifies a {@link BeanStore} to use when resolving
constructor arguments.
+ *
+ * @param value The bean store to use for resolving constructor
arguments.
+ * @return This object.
+ */
+ public Builder beanStore(BeanStore value) {
+ beanStore = value;
+ return this;
+ }
+
+ /**
+ * Specifies an already-instantiated bean for the {@link
#build()} method to return.
+ *
+ * @param value The value for this setting.
+ * @return This object.
+ */
+ public Builder impl(RestOperations value) {
+ impl = value;
+ return this;
+ }
+ }
+
+
//-----------------------------------------------------------------------------------------------------------------
+ // Instance
+
//-----------------------------------------------------------------------------------------------------------------
+
+ private final Map<String,List<RestOpContext>> map;
+ private List<RestOpContext> list;
+
/**
* Constructor.
*
* @param builder The builder containing the settings for this object.
*/
- public RestOperations(RestOperationsBuilder builder) {
+ public RestOperations(Builder builder) {
AMap<String,List<RestOpContext>> m = AMap.create();
for (Map.Entry<String,TreeSet<RestOpContext>> 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/RestOperationsBuilder.java
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestOperationsBuilder.java
deleted file mode 100644
index 40e7907..0000000
---
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestOperationsBuilder.java
+++ /dev/null
@@ -1,116 +0,0 @@
-//
***************************************************************************************************************************
-// * Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file *
-// * distributed with this work for additional information regarding copyright
ownership. The ASF licenses this file *
-// * to you under the Apache License, Version 2.0 (the "License"); you may not
use this file except in compliance *
-// * with the License. You may obtain a copy of the License at
*
-// *
*
-// * http://www.apache.org/licenses/LICENSE-2.0
*
-// *
*
-// * Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an *
-// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
express or implied. See the License for the *
-// * specific language governing permissions and limitations under the
License. *
-//
***************************************************************************************************************************
-package org.apache.juneau.rest;
-
-import 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.response.*;
-
-/**
- * Builder for {@link RestOperations} object.
- */
-public class RestOperationsBuilder {
-
- TreeMap<String,TreeSet<RestOpContext>> map = new TreeMap<>();
- Set<RestOpContext> set = ASet.of();
-
- private BeanStore beanStore;
- private Class<? extends RestOperations> implClass;
-
- /**
- * Instantiates a {@link RestOperations} object based on the contents
of this builder.
- *
- * @return A new {@link RestOperations} object.
- */
- public RestOperations build() {
- try {
- Class<? extends RestOperations> ic =
firstNonNull(implClass, getDefaultImplClass());
- return
BeanStore.of(beanStore).addBeans(RestOperationsBuilder.class,
this).createBean(ic);
- } catch (Exception e) {
- throw toHttpException(e, InternalServerError.class);
- }
- }
-
- /**
- * Specifies the default implementation class if not specified via
{@link #implClass(Class)}.
- *
- * @return The default implementation class if not specified via {@link
#implClass(Class)}.
- */
- protected Class<? extends RestOperations> getDefaultImplClass() {
- return RestOperations.class;
- }
-
- /**
- * Adds a method context to this builder.
- *
- * @param mc The REST method context to add.
- * @return Adds a method context to this builder.
- */
- public RestOperationsBuilder add(RestOpContext mc) {
- return add(mc.getHttpMethod(), mc);
- }
-
- /**
- * Adds a method context to this builder.
- *
- * @param httpMethodName The HTTP method name.
- * @param mc The REST method context to add.
- * @return Adds a method context to this builder.
- */
- public RestOperationsBuilder add(String httpMethodName, RestOpContext
mc) {
- httpMethodName = httpMethodName.toUpperCase();
- if (! map.containsKey(httpMethodName))
- map.put(httpMethodName, new TreeSet<>());
- map.get(httpMethodName).add(mc);
- set.add(mc);
- return this;
- }
-
- /**
- * Specifies a {@link RestOperations} implementation subclass to use.
- *
- * <p>
- * When specified, the {@link #build()} method will create an instance
of that class instead of the default {@link RestOperations}.
- *
- * <p>
- * The subclass must have a public constructor that takes in any of the
following arguments:
- * <ul>
- * <li>{@link RestOperationsBuilder} - This object.
- * <li>Any beans found in the specified {@link
#beanStore(BeanStore) bean store}.
- * <li>Any {@link Optional} beans that may or may not be found in
the specified {@link #beanStore(BeanStore) bean store}.
- * </ul>
- *
- * @param implClass The implementation class to build.
- * @return This object (for method chaining).
- */
- public RestOperationsBuilder implClass(Class<? extends RestOperations>
implClass) {
- this.implClass = implClass;
- return this;
- }
-
- /**
- * Specifies a {@link BeanStore} to use when resolving constructor
arguments.
- *
- * @param beanStore The bean store to use for resolving constructor
arguments.
- * @return This object (for method chaining).
- */
- public RestOperationsBuilder beanStore(BeanStore beanStore) {
- this.beanStore = beanStore;
- return this;
- }
-}
\ No newline at end of file