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 f4afbf8 REST refactoring.
f4afbf8 is described below
commit f4afbf88cc514ca719371cef6883bee9ba13c877
Author: JamesBognar <[email protected]>
AuthorDate: Thu Jan 21 18:37:30 2021 -0500
REST refactoring.
---
.../rest/annotation/RestMethodAnnotation_Test.java | 5 ++
.../juneau/rest/annotation/Rest_Context_Test.java | 2 +-
.../java/org/apache/juneau/rest/RestContext.java | 12 +++--
.../org/apache/juneau/rest/RestContextBuilder.java | 7 ++-
.../org/apache/juneau/rest/RestMethodContext.java | 58 ++++++++++++++++++----
.../juneau/rest/RestMethodContextBuilder.java | 49 ++++++++++++++----
.../apache/juneau/rest/RrpcRestMethodContext.java | 6 +--
.../apache/juneau/rest/annotation/RestMethod.java | 15 ++++++
.../rest/annotation/RestMethodAnnotation.java | 20 ++++++++
9 files changed, 141 insertions(+), 33 deletions(-)
diff --git
a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/RestMethodAnnotation_Test.java
b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/RestMethodAnnotation_Test.java
index 5ecf817..3e46c26 100644
---
a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/RestMethodAnnotation_Test.java
+++
b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/RestMethodAnnotation_Test.java
@@ -36,6 +36,7 @@ public class RestMethodAnnotation_Test {
RestMethod a1 = RestMethodAnnotation.create()
.clientVersion("clientVersion")
.consumes("consumes")
+ .context(RestMethodContext.class)
.converters(RestConverter.class)
.debug("debug")
.defaultAccept("defaultAccept")
@@ -68,6 +69,7 @@ public class RestMethodAnnotation_Test {
RestMethod a2 = RestMethodAnnotation.create()
.clientVersion("clientVersion")
.consumes("consumes")
+ .context(RestMethodContext.class)
.converters(RestConverter.class)
.debug("debug")
.defaultAccept("defaultAccept")
@@ -103,6 +105,7 @@ public class RestMethodAnnotation_Test {
+ "{"
+ "clientVersion:'clientVersion',"
+ "consumes:['consumes'],"
+ +
"context:'org.apache.juneau.rest.RestMethodContext',"
+
"converters:['org.apache.juneau.rest.RestConverter'],"
+ "debug:'debug',"
+ "defaultAccept:'defaultAccept',"
@@ -178,6 +181,7 @@ public class RestMethodAnnotation_Test {
@RestMethod(
clientVersion="clientVersion",
consumes="consumes",
+ context=RestMethodContext.class,
converters=RestConverter.class,
debug="debug",
defaultAccept="defaultAccept",
@@ -212,6 +216,7 @@ public class RestMethodAnnotation_Test {
@RestMethod(
clientVersion="clientVersion",
consumes="consumes",
+ context=RestMethodContext.class,
converters=RestConverter.class,
debug="debug",
defaultAccept="defaultAccept",
diff --git
a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/Rest_Context_Test.java
b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/Rest_Context_Test.java
index e09b6ce..cba61b1 100644
---
a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/Rest_Context_Test.java
+++
b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/Rest_Context_Test.java
@@ -91,7 +91,7 @@ public class Rest_Context_Test {
@Test
public void a05_invalidConstructor() throws Exception {
- assertThrown(()->client(A5.class)).contains("Invalid class
specified for REST_context");
+ assertThrown(()->client(A5.class)).contains("Could not create
instance");
}
//------------------------------------------------------------------------------------------------------------------
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 4863d25..5c3212a 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
@@ -4575,7 +4575,7 @@ public class RestContext extends BeanContext {
if (mi.isNotPublic())
throw new
RestServletException("@RestMethod method {0}.{1} must be defined as public.",
rci.inner().getName(), mi.getSimpleName());
- RestMethodContextBuilder rmcb = new
RestMethodContextBuilder(resource, mi.inner(), this);
+ RestMethodContextBuilder rmcb = new
RestMethodContextBuilder(mi.inner(), this);
RestMethodContext rmc = rmcb.build();
String httpMethod = rmc.getHttpMethod();
@@ -4584,11 +4584,13 @@ public class RestContext extends BeanContext {
// We override the CallMethod.invoke()
method to insert our logic.
if ("RRPC".equals(httpMethod)) {
- RestMethodContextBuilder smb =
new RestMethodContextBuilder(resource, mi.inner(), this);
- smb.dotAll();
+ RestMethodContext smb = new
RestMethodContextBuilder(mi.inner(), this)
+ .dotAll()
+
.context(RrpcRestMethodContext.class)
+ .build();
x
- .add("GET",
smb.build(RrpcRestMethodContext.class))
- .add("POST",
smb.build(RrpcRestMethodContext.class));
+ .add("GET", smb)
+ .add("POST", smb);
} else {
x.add(rmc);
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 9079e9d..5b60ff0 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
@@ -185,10 +185,9 @@ public class RestContextBuilder extends BeanContextBuilder
implements ServletCon
try {
PropertyStore ps = getPropertyStore();
Class<? extends RestContext> c =
ps.getClassProperty(REST_context, RestContext.class, RestContext.class);
- ConstructorInfo ci =
ClassInfo.of(c).getConstructor(Visibility.PUBLIC, RestContextBuilder.class);
- if (ci == null)
- throw new InternalServerError("Invalid class
specified for REST_context. Must extend from RestContext and provide a public
constructor of the form T(RestContextBuilder).");
- return ci.invoke(this);
+ BeanFactory bf = new BeanFactory(beanFactory, resource);
+ bf.addBean(RestContextBuilder.class, this);
+ return bf.createBean(c);
} catch (Exception e) {
throw toHttpException(e, InternalServerError.class);
}
diff --git
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestMethodContext.java
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestMethodContext.java
index 0a68e4d..1f1d218 100644
---
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestMethodContext.java
+++
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestMethodContext.java
@@ -65,6 +65,14 @@ import org.apache.juneau.utils.*;
@ConfigurableContext(nocache=true)
public class RestMethodContext extends BeanContext implements
Comparable<RestMethodContext> {
+ /** Represents a null value for the {@link RestMethod#context()}
annotation.*/
+ @SuppressWarnings("javadoc")
+ public static final class Null extends RestMethodContext {
+ public Null(RestMethodContextBuilder builder) throws Exception {
+ super(builder);
+ }
+ }
+
//-------------------------------------------------------------------------------------------------------------------
// Configurable properties
//-------------------------------------------------------------------------------------------------------------------
@@ -157,6 +165,37 @@ public class RestMethodContext extends BeanContext
implements Comparable<RestMet
public static final String RESTMETHOD_clientVersion = PREFIX +
".clientVersion.s";
/**
+ * Configuration property: REST method context class.
+ *
+ * <ul class='spaced-list'>
+ * <li><b>ID:</b> {@link
org.apache.juneau.rest.RestMethodContext#RESTMETHOD_context RESTMETHOD_context}
+ * <li><b>Name:</b> <js>"RestMethodContext.context.c"</js>
+ * <li><b>Data type:</b> <c>Class<? extends {@link
org.apache.juneau.rest.RestMethodContext}></c>
+ * <li><b>Default:</b> {@link
org.apache.juneau.rest.RestMethodContext}
+ * <li><b>Session property:</b> <jk>false</jk>
+ * <li><b>Annotations:</b>
+ * <ul>
+ * <li class='ja'>{@link
org.apache.juneau.rest.annotation.RestMethod#context()}
+ * </ul>
+ * <li><b>Methods:</b>
+ * <ul>
+ * <li class='jm'>{@link
org.apache.juneau.rest.RestMethodContextBuilder#context(Class)}
+ * </ul>
+ * </ul>
+ *
+ * <h5 class='section'>Description:</h5>
+ * <p>
+ * Allows you to extend the {@link RestMethodContext} class to modify
how any of the functions are implemented.
+ *
+ * <p>
+ * The subclass must provide the following:
+ * <ul>
+ * <li>A public constructor that takes in one parameter that
should be passed to the super constructor: {@link RestMethodContextBuilder}.
+ * </ul>
+ */
+ public static final String RESTMETHOD_context = PREFIX + ".context.c";
+
+ /**
* Configuration property: Debug mode.
*
* <h5 class='section'>Property:</h5>
@@ -638,16 +677,17 @@ public class RestMethodContext extends BeanContext
implements Comparable<RestMet
/**
* Context constructor.
*
- * @param ps The property store with settings.
+ * @param builder The builder for this object.
* @throws ServletException If context could not be created.
*/
- public RestMethodContext(PropertyStore ps) throws ServletException {
- super(ps);
+ public RestMethodContext(RestMethodContextBuilder builder) throws
ServletException {
+ super(builder.getPropertyStore());
try {
- context =
getInstanceProperty("RestMethodContext.restContext.o", RestContext.class);
- method =
getInstanceProperty("RestMethodContext.restMethod.o", Method.class);
- boolean dotAll =
getBooleanProperty("RestMethodContext.dotAll.b", false);
+ context = builder.restContext;
+ method = builder.restMethod;
+
+ PropertyStore ps = getPropertyStore();
methodInvoker = new MethodInvoker(method,
context.getMethodExecStats(method));
mi = MethodInfo.of(method).accessible();
@@ -681,7 +721,7 @@ public class RestMethodContext extends BeanContext
implements Comparable<RestMet
requiredMatchers = matchers.stream().filter(x ->
x.required()).toArray(RestMatcher[]::new);
optionalMatchers = matchers.stream().filter(x -> !
x.required()).toArray(RestMatcher[]::new);
- pathMatchers = createPathMatchers(r, beanFactory,
dotAll).asArray();
+ pathMatchers = createPathMatchers(r,
beanFactory).asArray();
beanFactory.addBean(UrlPathMatcher[].class,
pathMatchers);
beanFactory.addBean(UrlPathMatcher.class,
pathMatchers.length > 0 ? pathMatchers[0] : null);
@@ -1223,14 +1263,14 @@ public class RestMethodContext extends BeanContext
implements Comparable<RestMet
*
* @param resource The REST resource object.
* @param beanFactory The bean factory to use for retrieving and
creating beans.
- * @param dotAll If {@link RestMethodContextBuilder#dotAll()} was
specified.
* @return The HTTP part parser for this REST resource.
* @throws Exception If parser could not be instantiated.
* @seealso #RESTMETHOD_paths
*/
- protected UrlPathMatcherList createPathMatchers(Object resource,
BeanFactory beanFactory, boolean dotAll) throws Exception {
+ protected UrlPathMatcherList createPathMatchers(Object resource,
BeanFactory beanFactory) throws Exception {
UrlPathMatcherList x = UrlPathMatcherList.create();
+ boolean dotAll =
getBooleanProperty("RestMethodContext.dotAll.b", false);
for (String p : getArrayProperty(RESTMETHOD_path,
String.class)) {
if (dotAll && ! p.endsWith("/*"))
diff --git
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestMethodContextBuilder.java
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestMethodContextBuilder.java
index bd3dbda..02824cd 100644
---
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestMethodContextBuilder.java
+++
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestMethodContextBuilder.java
@@ -13,17 +13,18 @@
package org.apache.juneau.rest;
import static java.util.Arrays.*;
+import static org.apache.juneau.rest.HttpRuntimeException.*;
import static org.apache.juneau.rest.RestMethodContext.*;
import java.lang.annotation.*;
import java.util.*;
import java.util.function.*;
-import javax.servlet.*;
-
import org.apache.http.*;
import org.apache.juneau.*;
+import org.apache.juneau.cp.*;
import org.apache.juneau.http.*;
+import org.apache.juneau.http.exception.*;
import org.apache.juneau.internal.*;
import org.apache.juneau.reflect.*;
import org.apache.juneau.rest.annotation.*;
@@ -35,22 +36,29 @@ import java.lang.reflect.Method;
*/
public class RestMethodContextBuilder extends BeanContextBuilder {
- @Override
+ RestContext restContext;
+ Method restMethod;
+
+ @Override /* BeanContextBuilder */
public RestMethodContext build() {
try {
- return new RestMethodContext(getPropertyStore());
- } catch (ServletException e) {
- throw new RuntimeException(e);
+ PropertyStore ps = getPropertyStore();
+ Class<? extends RestMethodContext> c =
ps.getClassProperty(RESTMETHOD_context, RestMethodContext.class,
RestMethodContext.class);
+ BeanFactory bf = new
BeanFactory(restContext.rootBeanFactory, restContext.getResource());
+ bf.addBean(RestMethodContextBuilder.class, this);
+ return bf.createBean(c);
+ } catch (Exception e) {
+ throw toHttpException(e, InternalServerError.class);
}
}
- RestMethodContextBuilder(Object servlet, java.lang.reflect.Method
method, RestContext context) throws RestServletException {
- set("RestMethodContext.restContext.o", context);
- set("RestMethodContext.restMethod.o", method);
- set("RestMethodContext.restObject.o", context.getResource());
// Added to force a new cache hash.
+ RestMethodContextBuilder(java.lang.reflect.Method method, RestContext
context) throws RestServletException {
+
+ this.restContext = context;
+ this.restMethod = method;
String sig = method.getDeclaringClass().getName() + '.' +
method.getName();
- MethodInfo mi = MethodInfo.of(servlet.getClass(), method);
+ MethodInfo mi = MethodInfo.of(context.getResource().getClass(),
method);
try {
@@ -113,6 +121,25 @@ public class RestMethodContextBuilder extends
BeanContextBuilder {
}
/**
+ * <i><l>RestMethodContext</l> configuration property: </i> REST
method context class.
+ *
+ * Allows you to extend the {@link RestMethodContext} class to modify
how any of the methods are implemented.
+ *
+ * <p>
+ * The subclass must provide the following:
+ * <ul>
+ * <li>A public constructor that takes in one parameter that
should be passed to the super constructor: {@link RestMethodContextBuilder}.
+ * </ul>
+ *
+ * @param value The new value for this setting.
+ * @return This object (for method chaining).
+ */
+ @FluentSetter
+ public RestMethodContextBuilder context(Class<? extends
RestMethodContext> value) {
+ return set(RESTMETHOD_context, value);
+ }
+
+ /**
* <i><l>RestMethodContext</l> configuration property: </i> Debug
mode.
*
* <p>
diff --git
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RrpcRestMethodContext.java
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RrpcRestMethodContext.java
index accaafe..8d0c591 100644
---
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RrpcRestMethodContext.java
+++
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RrpcRestMethodContext.java
@@ -35,11 +35,11 @@ public class RrpcRestMethodContext extends
RestMethodContext {
/**
* Constructor.
*
- * @param ps The property store containing the settings for this
context.
+ * @param builder The builder for this method context.
* @throws ServletException Problem with metadata was detected.
*/
- public RrpcRestMethodContext(PropertyStore ps) throws ServletException {
- super(ps);
+ public RrpcRestMethodContext(RestMethodContextBuilder builder) throws
ServletException {
+ super(builder);
ClassMeta<?> interfaceClass =
getClassMeta(mi.inner().getGenericReturnType());
meta = new RrpcInterfaceMeta(interfaceClass.getInnerClass(),
null);
diff --git
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestMethod.java
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestMethod.java
index b88cccb..7f0ed4a 100644
---
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestMethod.java
+++
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestMethod.java
@@ -117,6 +117,21 @@ public @interface RestMethod {
String[] consumes() default {};
/**
+ * Allows you to extend the {@link RestContext} class to modify how any
of the methods are implemented.
+ *
+ * <p>
+ * The subclass must provide the following:
+ * <ul>
+ * <li>A public constructor that takes in one parameter that
should be passed to the super constructor: {@link RestMethodContextBuilder}.
+ * </ul>
+ *
+ * <ul class='seealso'>
+ * <li class='jm'>{@link RestMethodContextBuilder#context(Class)}
+ * </ul>
+ */
+ Class<? extends RestMethodContext> context() default
RestMethodContext.Null.class;
+
+ /**
* Class-level response converters.
*
* <p>
diff --git
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestMethodAnnotation.java
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestMethodAnnotation.java
index e7f899f..db221bf 100644
---
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestMethodAnnotation.java
+++
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestMethodAnnotation.java
@@ -61,6 +61,7 @@ public class RestMethodAnnotation {
Class<? extends RestConverter>[] converters = new Class[0];
Class<? extends RestGuard>[] guards = new Class[0];
Class<? extends RestMatcher>[] matchers = new Class[0];
+ Class<? extends RestMethodContext> context =
RestMethodContext.Null.class;
Class<?>[] encoders=new Class<?>[0], parsers=new Class<?>[0],
serializers=new Class<?>[0];
int priority = 0;
MethodSwagger swagger = MethodSwaggerAnnotation.DEFAULT;
@@ -106,6 +107,17 @@ public class RestMethodAnnotation {
}
/**
+ * Sets the {@link RestMethod#context()} property on this
annotation.
+ *
+ * @param value The new value for this property.
+ * @return This object (for method chaining).
+ */
+ public Builder context(Class<? extends RestMethodContext>
value) {
+ this.context = value;
+ return this;
+ }
+
+ /**
* Sets the {@link RestMethod#converters()} property on this
annotation.
*
* @param value The new value for this property.
@@ -413,6 +425,7 @@ public class RestMethodAnnotation {
private final Class<? extends RestConverter>[] converters;
private final Class<? extends RestGuard>[] guards;
private final Class<? extends RestMatcher>[] matchers;
+ private final Class<? extends RestMethodContext> context;
private final Class<?>[] encoders, parsers, serializers;
private final int priority;
private final MethodSwagger swagger;
@@ -423,6 +436,7 @@ public class RestMethodAnnotation {
super(b);
this.clientVersion = b.clientVersion;
this.consumes = copyOf(b.consumes);
+ this.context = b.context;
this.converters = copyOf(b.converters);
this.debug = b.debug;
this.defaultAccept = b.defaultAccept;
@@ -463,6 +477,11 @@ public class RestMethodAnnotation {
}
@Override /* RestMethod */
+ public Class<? extends RestMethodContext> context() {
+ return context;
+ }
+
+ @Override /* RestMethod */
public Class<? extends RestConverter>[] converters() {
return converters;
}
@@ -615,6 +634,7 @@ public class RestMethodAnnotation {
psb.set(REST_serializers,
merge(ConverterUtils.toType(psb.peek(REST_serializers), Object[].class),
a.serializers()));
psb.set(REST_parsers,
merge(ConverterUtils.toType(psb.peek(REST_parsers), Object[].class),
a.parsers()));
psb.set(REST_encoders,
merge(ConverterUtils.toType(psb.peek(REST_encoders), Object[].class),
a.encoders()));
+ psb.setIf(a.context() != RestMethodContext.Null.class,
RESTMETHOD_context, a.context());
psb.setIfNotEmpty(REST_produces,
stringList(a.produces()));
psb.setIfNotEmpty(REST_consumes,
stringList(a.consumes()));
stringStream(a.defaultRequestHeaders()).map(x ->
BasicHeader.ofPair(x)).forEach(x ->
psb.appendTo(RESTMETHOD_defaultRequestHeaders, x));