You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@juneau.apache.org by ja...@apache.org on 2018/07/20 13:21:48 UTC

[juneau] branch master updated: Support @RequestBean as @RestMethod parameter.

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 a56d59d  Support @RequestBean as @RestMethod parameter.
a56d59d is described below

commit a56d59ded6c27c964331290f98e9358f7606acd7
Author: JamesBognar <ja...@apache.org>
AuthorDate: Fri Jul 20 09:21:32 2018 -0400

    Support @RequestBean as @RestMethod parameter.
---
 juneau-core/juneau-marshall/TODO.txt               |  13 +-
 .../org/apache/juneau/http/annotation/Body.java    |   1 -
 .../apache/juneau/http/annotation/FormData.java    |   3 +-
 .../org/apache/juneau/http/annotation/Header.java  |   1 -
 .../org/apache/juneau/http/annotation/Path.java    |   1 -
 .../org/apache/juneau/http/annotation/Query.java   |   1 -
 .../annotation}/RequestBean.java                   |  22 ++-
 .../apache/juneau/httppart/HttpPartSerializer.java |   1 -
 .../apache/juneau/httppart/RequestBeanMeta.java    | 188 +++++++++++++++++++++
 .../juneau/httppart/RequestBeanPropertyMeta.java   | 144 ++++++++++++++++
 .../apache/juneau/internal/ReflectionUtils.java    |  11 ++
 .../apache/juneau/remoteable/RemoteMethodArg.java  |   5 +-
 .../juneau/remoteable/RemoteMethodBeanArg.java     |  55 +-----
 .../juneau/remoteable/RemoteableMethodMeta.java    |   5 +-
 juneau-doc/src/main/javadoc/overview.html          |  53 +++++-
 .../org/apache/juneau/rest/client/RestClient.java  |  25 +--
 .../java/org/apache/juneau/rest/RestContext.java   |   4 +
 .../org/apache/juneau/rest/RestParamDefaults.java  |  14 ++
 .../java/org/apache/juneau/rest/RestRequest.java   |  58 +++++++
 .../apache/juneau/rest/annotation/HookEvent.java   |   2 +-
 20 files changed, 515 insertions(+), 92 deletions(-)

diff --git a/juneau-core/juneau-marshall/TODO.txt b/juneau-core/juneau-marshall/TODO.txt
index 31d37b1..ea19c52 100644
--- a/juneau-core/juneau-marshall/TODO.txt
+++ b/juneau-core/juneau-marshall/TODO.txt
@@ -11,12 +11,7 @@
 * specific language governing permissions and limitations under the License.                                              *
 ***************************************************************************************************************************
 
-Document properties in config file.
-
-REST example showing how to use NLS.
-REST example showing how to customize look-and-feel.
-REST example showing static resources.
-Add doc link to @Example class.
-
-
-
+Test @Header("*") using maps/beans and related annotations.
+Simplify @Body annotation by merging @Schema into it.
+Test RestRequest.getRequestBean() and @RequestBean as an annotation.
+Document RestRequest.getRequestBean().
\ No newline at end of file
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/Body.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/Body.java
index f6ef27e..1d6c2c2 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/Body.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/Body.java
@@ -22,7 +22,6 @@ import org.apache.juneau.*;
 import org.apache.juneau.httppart.*;
 import org.apache.juneau.json.*;
 import org.apache.juneau.jsonschema.*;
-import org.apache.juneau.remoteable.*;
 import org.apache.juneau.serializer.*;
 
 /**
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/FormData.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/FormData.java
index 78a736f..556c420 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/FormData.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/FormData.java
@@ -21,7 +21,6 @@ import java.util.*;
 
 import org.apache.juneau.*;
 import org.apache.juneau.httppart.*;
-import org.apache.juneau.remoteable.*;
 import org.apache.juneau.urlencoding.*;
 
 /**
@@ -109,7 +108,7 @@ import org.apache.juneau.urlencoding.*;
  * </ul>
  *
  * <h5 class='topic'>Client-side REST</h5>
-* Annotation applied to Java method arguments of interface proxies to denote that they are FORM post parameters on the
+ * Annotation applied to Java method arguments of interface proxies to denote that they are FORM post parameters on the
  * request.
  *
  * <h5 class='section'>Example:</h5>
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/Header.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/Header.java
index 20fcb25..7b71cae 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/Header.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/Header.java
@@ -20,7 +20,6 @@ import java.util.*;
 
 import org.apache.juneau.*;
 import org.apache.juneau.httppart.*;
-import org.apache.juneau.remoteable.*;
 import org.apache.juneau.urlencoding.*;
 
 /**
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/Path.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/Path.java
index 8317155..850246c 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/Path.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/Path.java
@@ -19,7 +19,6 @@ import java.lang.annotation.*;
 
 import org.apache.juneau.*;
 import org.apache.juneau.httppart.*;
-import org.apache.juneau.remoteable.*;
 import org.apache.juneau.urlencoding.*;
 
 /**
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/Query.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/Query.java
index 0f06781..b06f5bf 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/Query.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/Query.java
@@ -21,7 +21,6 @@ import java.util.*;
 
 import org.apache.juneau.*;
 import org.apache.juneau.httppart.*;
-import org.apache.juneau.remoteable.*;
 import org.apache.juneau.urlencoding.*;
 
 /**
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/remoteable/RequestBean.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/RequestBean.java
similarity index 85%
rename from juneau-core/juneau-marshall/src/main/java/org/apache/juneau/remoteable/RequestBean.java
rename to juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/RequestBean.java
index 249b83d..c94b4ee 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/remoteable/RequestBean.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/RequestBean.java
@@ -10,7 +10,7 @@
 // * "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.remoteable;
+package org.apache.juneau.http.annotation;
 
 import static java.lang.annotation.ElementType.*;
 import static java.lang.annotation.RetentionPolicy.*;
@@ -21,8 +21,21 @@ import org.apache.juneau.httppart.*;
 import org.apache.juneau.urlencoding.*;
 
 /**
- * Annotation applied to Java method arguments of interface proxies to denote a bean with remoteable annotations.
+ * Request bean annotation.
+ *
+ * <p>
+ * Can be used in the following locations:
+ * <ul>
+ * 	<li>Java method arguments and argument-types of client-side <ja>@Remoteable</ja>-annotated REST interface proxies.
+ * 	<li>Java method arguments and argument-types of server-side <ja>@RestMethod</ja>-annotated REST Java methods.
+ * </ul>
  *
+ * <h5 class='topic'>Server-side REST</h5>
+ * TODO
+ *
+ * <h5 class='topic'>Client-side REST</h5>
+ * Annotation applied to Java method arguments of interface proxies to denote a bean with remoteable annotations.
+
  * <h5 class='section'>Example:</h5>
  * <p class='bcode w800'>
  * 	<ja>@Remoteable</ja>(path=<js>"/myproxy"</js>)
@@ -103,4 +116,9 @@ public @interface RequestBean {
 	 * This annotation is provided to allow values to be custom serialized.
 	 */
 	Class<? extends HttpPartSerializer> serializer() default HttpPartSerializer.Null.class;
+
+	/**
+	 * TODO
+	 */
+	Class<? extends HttpPartParser> parser() default HttpPartParser.Null.class;
 }
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/httppart/HttpPartSerializer.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/httppart/HttpPartSerializer.java
index 046db35..88062c5 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/httppart/HttpPartSerializer.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/httppart/HttpPartSerializer.java
@@ -14,7 +14,6 @@ package org.apache.juneau.httppart;
 
 import org.apache.juneau.*;
 import org.apache.juneau.http.annotation.*;
-import org.apache.juneau.remoteable.*;
 import org.apache.juneau.serializer.*;
 
 /**
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/httppart/RequestBeanMeta.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/httppart/RequestBeanMeta.java
new file mode 100644
index 0000000..04b369b
--- /dev/null
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/httppart/RequestBeanMeta.java
@@ -0,0 +1,188 @@
+// ***************************************************************************************************************************
+// * 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.httppart;
+
+import static org.apache.juneau.internal.ReflectionUtils.*;
+
+import java.lang.annotation.*;
+import java.lang.reflect.*;
+import java.util.*;
+
+import org.apache.juneau.*;
+import org.apache.juneau.http.annotation.*;
+import org.apache.juneau.internal.*;
+
+/**
+ * Represents the metadata gathered from a parameter or class annotated with {@link RequestBean}.
+ */
+public class RequestBeanMeta {
+
+	/**
+	 * Create metadata from specified parameter.
+	 *
+	 * @param m The method containing the parameter or parameter type annotated with {@link RequestBean}.
+	 * @param i The parameter index.
+	 * @param ps
+	 * 	Configuration information used to instantiate part serializers and part parsers.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return Metadata about the parameter, or <jk>null</jk> if parameter or parameter type not annotated with {@link RequestBean}.
+	 */
+	public static RequestBeanMeta create(Method m, int i, PropertyStore ps) {
+		if (! hasAnnotation(RequestBean.class, m, i))
+			return null;
+		return new RequestBeanMeta.Builder(ps).apply(m, i).build();
+	}
+
+	/**
+	 * Create metadata from specified class.
+	 *
+	 * @param c The class annotated with {@link RequestBean}.
+	 * @param ps
+	 * 	Configuration information used to instantiate part serializers and part parsers.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return Metadata about the class, or <jk>null</jk> if class not annotated with {@link RequestBean}.
+	 */
+	public static RequestBeanMeta create(Class<?> c, PropertyStore ps) {
+		if (! hasAnnotation(RequestBean.class, c))
+			return null;
+		return new RequestBeanMeta.Builder(ps).apply(c).build();
+	}
+
+	//-----------------------------------------------------------------------------------------------------------------
+	// Instance
+	//-----------------------------------------------------------------------------------------------------------------
+
+	private final ClassMeta<?> cm;
+	private final Map<String,RequestBeanPropertyMeta> properties, propertiesByGetter;
+	private final HttpPartSerializer serializer;
+	private final HttpPartParser parser;
+
+	RequestBeanMeta(Builder b) {
+		this.cm = b.cm;
+		this.serializer = ClassUtils.newInstance(HttpPartSerializer.class, b.serializer, true, b.ps);
+		this.parser = ClassUtils.newInstance(HttpPartParser.class, b.parser, true, b.ps);
+		Map<String,RequestBeanPropertyMeta> properties = new LinkedHashMap<>(), propertiesByGetter = new LinkedHashMap<>();
+		for (Map.Entry<String,RequestBeanPropertyMeta.Builder> e : b.properties.entrySet()) {
+			RequestBeanPropertyMeta pm = e.getValue().build(serializer, parser);
+			properties.put(e.getKey(), pm);
+			propertiesByGetter.put(pm.getGetter(), pm);
+
+		}
+		this.properties = Collections.unmodifiableMap(properties);
+		this.propertiesByGetter = Collections.unmodifiableMap(propertiesByGetter);
+	}
+
+	static class Builder {
+		ClassMeta<?> cm;
+		PropertyStore ps;
+		Class<? extends HttpPartSerializer> serializer;
+		Class<? extends HttpPartParser> parser;
+		Map<String,RequestBeanPropertyMeta.Builder> properties = new LinkedHashMap<>();
+
+		Builder(PropertyStore ps) {
+			this.ps = ps;
+		}
+
+		Builder apply(Method m, int i) {
+			return apply(m.getParameterTypes()[i]).apply(getAnnotation(RequestBean.class, m, i));
+		}
+
+		Builder apply(Class<?> c) {
+			apply(getAnnotation(RequestBean.class, c));
+			this.cm = BeanContext.DEFAULT.getClassMeta(c);
+			BeanMeta<?> bm = BeanContext.DEFAULT.getBeanMeta(c);
+			for (BeanPropertyMeta bp : bm.getPropertyMetas()) {
+				String n = bp.getName();
+				Annotation a = bp.getAnnotation(Path.class);
+				String g = bp.getGetter().getName();
+				if (a != null) {
+					HttpPartSchemaBuilder s = HttpPartSchema.create().apply(a);
+					getProperty(n, HttpPartType.PATH).apply(s).getter(g);
+				}
+				a = bp.getAnnotation(Header.class);
+				if (a != null) {
+					HttpPartSchemaBuilder s = HttpPartSchema.create().apply(a);
+					getProperty(n, HttpPartType.HEADER).apply(s).getter(g);
+				}
+				a = bp.getAnnotation(Query.class);
+				if (a != null) {
+					HttpPartSchemaBuilder s = HttpPartSchema.create().apply(a);
+					getProperty(n, HttpPartType.QUERY).apply(s).getter(g);
+				}
+				a = bp.getAnnotation(FormData.class);
+				if (a != null) {
+					HttpPartSchemaBuilder s = HttpPartSchema.create().apply(a);
+					getProperty(n, HttpPartType.FORMDATA).apply(s).getter(g);
+				}
+				a = bp.getAnnotation(Body.class);
+				if (a != null) {
+					HttpPartSchemaBuilder s = HttpPartSchema.create().apply(a);
+					getProperty(n, HttpPartType.BODY).apply(s).getter(g);
+				}
+			}
+			return this;
+		}
+
+		Builder apply(RequestBean rb) {
+			if (rb != null) {
+				if (rb.serializer() != HttpPartSerializer.Null.class)
+					serializer = rb.serializer();
+				if (rb.parser() != HttpPartParser.Null.class)
+					parser = rb.parser();
+			}
+			return this;
+		}
+
+		RequestBeanMeta build() {
+			return new RequestBeanMeta(this);
+		}
+
+		private RequestBeanPropertyMeta.Builder getProperty(String name, HttpPartType partType) {
+			RequestBeanPropertyMeta.Builder b = properties.get(name);
+			if (b == null) {
+				b = RequestBeanPropertyMeta.create().name(name).partType(partType);
+				properties.put(name, b);
+			}
+			return b;
+		}
+	}
+
+	/**
+	 * Returns metadata about the bean property with the specified property name.
+	 *
+	 * @param name The bean property name.
+	 * @return Metadata about the bean property, or <jk>null</jk> if none found.
+	 */
+	public RequestBeanPropertyMeta getProperty(String name) {
+		return properties.get(name);
+	}
+
+	/**
+	 * Returns metadata about the bean property with the specified method getter name.
+	 *
+	 * @param name The bean method getter name.
+	 * @return Metadata about the bean property, or <jk>null</jk> if none found.
+	 */
+	public RequestBeanPropertyMeta getPropertyByGetter(String name) {
+		return propertiesByGetter.get(name);
+	}
+
+	/**
+	 * Returns metadata about the class.
+	 *
+	 * @return Metadata about the class.
+	 */
+	public ClassMeta<?> getClassMeta() {
+		return cm;
+	}
+}
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/httppart/RequestBeanPropertyMeta.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/httppart/RequestBeanPropertyMeta.java
new file mode 100644
index 0000000..1ab0426
--- /dev/null
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/httppart/RequestBeanPropertyMeta.java
@@ -0,0 +1,144 @@
+// ***************************************************************************************************************************
+// * 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.httppart;
+
+import org.apache.juneau.*;
+import org.apache.juneau.http.annotation.*;
+import org.apache.juneau.internal.*;
+
+/**
+ * Represents the metadata gathered from a getter method of a class annotated with {@link RequestBean}.
+ */
+public class RequestBeanPropertyMeta {
+
+	static RequestBeanPropertyMeta.Builder create() {
+		return new Builder();
+	}
+
+	//-----------------------------------------------------------------------------------------------------------------
+	// Instance
+	//-----------------------------------------------------------------------------------------------------------------
+
+	private final String partName, getter;
+	private final HttpPartType partType;
+	private final HttpPartSerializer serializer;
+	private final HttpPartParser parser;
+	private final HttpPartSchema schema;
+
+	RequestBeanPropertyMeta(Builder b, HttpPartSerializer serializer, HttpPartParser parser) {
+		this.partType = b.partType;
+		this.schema = b.schema.build();
+		this.partName = StringUtils.firstNonEmpty(schema.getName(), b.name);
+		this.getter = b.getter;
+		this.serializer = schema.getSerializer() == null ? serializer : ClassUtils.newInstance(HttpPartSerializer.class, schema.getSerializer(), true, b.ps);
+		this.parser = schema.getParser() == null ? parser : ClassUtils.newInstance(HttpPartParser.class, schema.getParser(), true, b.ps);
+	}
+
+	static class Builder {
+		HttpPartType partType;
+		HttpPartSchemaBuilder schema;
+		String name, getter;
+		PropertyStore ps = PropertyStore.DEFAULT;
+
+		Builder name(String value) {
+			name = value;
+			return this;
+		}
+
+		Builder getter(String value) {
+			getter = value;
+			return this;
+		}
+
+		Builder partType(HttpPartType value) {
+			partType = value;
+			return this;
+		}
+
+		Builder schema(HttpPartSchemaBuilder value) {
+			schema = value;
+			return this;
+		}
+
+		Builder apply(HttpPartSchemaBuilder s) {
+			schema = s;
+			return this;
+		}
+
+		RequestBeanPropertyMeta build(HttpPartSerializer serializer, HttpPartParser parser) {
+			return new RequestBeanPropertyMeta(this, serializer, parser);
+		}
+	}
+
+	/**
+	 * Returns the HTTP part name for this property (e.g. query parameter name).
+	 *
+	 * @return The HTTP part name, or <jk>null</jk> if it doesn't have a part name.
+	 */
+	public String getPartName() {
+		return partName;
+	}
+
+	/**
+	 * Returns the name of the Java method getter that defines this property.
+	 *
+	 * @return
+	 * 	The name of the Java method getter that defines this property.
+	 * 	<br>Never <jk>null</jk>.
+	 */
+	public String getGetter() {
+		return getter;
+	}
+
+	/**
+	 * Returns the HTTP part type for this property (e.g. query parameter, header, etc...).
+	 *
+	 * @return
+	 * 	The HTTP part type for this property.
+	 * 	<br>Never <jk>null</jk>.
+	 */
+	public HttpPartType getPartType() {
+		return partType;
+	}
+
+	/**
+	 * Returns the serializer to use for serializing the bean property value.
+	 *
+	 * @param _default The default serializer to use if not defined on the annotation.
+	 * @return The serializer to use for serializing the bean property value.
+	 */
+	public HttpPartSerializer getSerializer(HttpPartSerializer _default) {
+		return serializer == null ? _default : serializer;
+	}
+
+	/**
+	 * Returns the parser to use for parsing the bean property value.
+	 *
+	 * @param _default The default parsing to use if not defined on the annotation.
+	 * @return The parsing to use for serializing the bean property value.
+	 */
+	public HttpPartParser getParser(HttpPartParser _default) {
+		return parser == null ? _default : parser;
+	}
+
+	/**
+	 * Returns the schema information gathered from annotations on the method and return type.
+	 *
+	 * @return
+	 * 	The schema information gathered from annotations on the method and return type.
+	 * 	<br>Never <jk>null</jk>.
+	 */
+	public HttpPartSchema getSchema() {
+		return schema;
+	}
+}
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/ReflectionUtils.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/ReflectionUtils.java
index 0464c3f..213fb54 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/ReflectionUtils.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/ReflectionUtils.java
@@ -48,6 +48,17 @@ public final class ReflectionUtils {
 	}
 
 	/**
+	 * Returns <jk>true</jk> if the {@link #getAnnotation(Class, Class)} returns a value.
+	 *
+	 * @param a The annotation to check for.
+	 * @param c The class to check.
+	 * @return <jk>true</jk> if the {@link #getAnnotation(Class, Class)} returns a value.
+	 */
+	public static boolean hasAnnotation(Class<? extends Annotation> a, Class<?> c) {
+		return getAnnotation(a, c) != null;
+	}
+
+	/**
 	 * Returns the specified annotation if it exists on the specified parameter or parameter type class.
 	 *
 	 * @param a The annotation to check for.
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/remoteable/RemoteMethodArg.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/remoteable/RemoteMethodArg.java
index 5725950..ae08a68 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/remoteable/RemoteMethodArg.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/remoteable/RemoteMethodArg.java
@@ -96,10 +96,11 @@ public final class RemoteMethodArg {
 	/**
 	 * Returns the HTTP part serializer to use for serializing this part.
 	 *
+	 * @param _default The default serializer to use if the serializer was not defined via annotations.
 	 * @return The HTTP part serializer, or <jk>null</jk> if not specified.
 	 */
-	public HttpPartSerializer getSerializer() {
-		return serializer;
+	public HttpPartSerializer getSerializer(HttpPartSerializer _default) {
+		return serializer == null ? _default : serializer;
 	}
 
 	/**
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/remoteable/RemoteMethodBeanArg.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/remoteable/RemoteMethodBeanArg.java
index c682a29..99b5bb0 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/remoteable/RemoteMethodBeanArg.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/remoteable/RemoteMethodBeanArg.java
@@ -13,14 +13,7 @@
 package org.apache.juneau.remoteable;
 
 import static org.apache.juneau.internal.ClassUtils.*;
-import static org.apache.juneau.internal.ReflectionUtils.*;
-import static org.apache.juneau.httppart.HttpPartType.*;
 
-import java.lang.annotation.*;
-import java.lang.reflect.*;
-import java.util.*;
-
-import org.apache.juneau.*;
 import org.apache.juneau.http.annotation.*;
 import org.apache.juneau.httppart.*;
 
@@ -35,13 +28,13 @@ import org.apache.juneau.httppart.*;
 public final class RemoteMethodBeanArg {
 
 	private final int index;
+	private final RequestBeanMeta meta;
 	private final HttpPartSerializer serializer;
-	private final Map<String,RemoteMethodArg> properties;
 
-	private RemoteMethodBeanArg(int index, Class<? extends HttpPartSerializer> serializer, Map<String,RemoteMethodArg> properties) {
+	RemoteMethodBeanArg(int index, Class<? extends HttpPartSerializer> serializer, RequestBeanMeta meta) {
 		this.index = index;
 		this.serializer = newInstance(HttpPartSerializer.class, serializer);
-		this.properties = properties;
+		this.meta = meta;
 	}
 
 	/**
@@ -68,45 +61,7 @@ public final class RemoteMethodBeanArg {
 	 * @param name The bean property name.
 	 * @return Metadata about the bean property, or <jk>null</jk> if not found.
 	 */
-	public RemoteMethodArg getProperty(String name) {
-		return properties.get(name);
-	}
-
-	static RemoteMethodBeanArg create(Method m, int i) {
-		Map<String,RemoteMethodArg> map = new LinkedHashMap<>();
-		if (hasAnnotation(RequestBean.class, m, i)) {
-			RequestBean rb = getAnnotation(RequestBean.class, m, i);
-			BeanMeta<?> bm = BeanContext.DEFAULT.getBeanMeta(m.getParameterTypes()[i]);
-			for (BeanPropertyMeta bp : bm.getPropertyMetas()) {
-				String n = bp.getName();
-				Annotation a = bp.getAnnotation(Path.class);
-				if (a != null) {
-					HttpPartSchema s = HttpPartSchema.create().apply(a).build();
-					map.put(n, new RemoteMethodArg(PATH, s, n));
-				}
-				a = bp.getAnnotation(Header.class);
-				if (a != null) {
-					HttpPartSchema s = HttpPartSchema.create().apply(a).build();
-					map.put(n, new RemoteMethodArg(HEADER, s, n));
-				}
-				a = bp.getAnnotation(Query.class);
-				if (a != null) {
-					HttpPartSchema s = HttpPartSchema.create().apply(a).build();
-					map.put(n, new RemoteMethodArg(QUERY, s, n));
-				}
-				a = bp.getAnnotation(FormData.class);
-				if (a != null) {
-					HttpPartSchema s = HttpPartSchema.create().apply(a).build();
-					map.put(n, new RemoteMethodArg(FORMDATA, s, n));
-				}
-				a = bp.getAnnotation(Body.class);
-				if (a != null) {
-					HttpPartSchema s = HttpPartSchema.create().apply(a).build();
-					map.put(n, new RemoteMethodArg(BODY, s, n));
-				}
-			}
-			return new RemoteMethodBeanArg(i, rb.serializer(), map);
-		}
-		return null;
+	public RequestBeanPropertyMeta getProperty(String name) {
+		return meta.getProperty(name);
 	}
 }
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/remoteable/RemoteableMethodMeta.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/remoteable/RemoteableMethodMeta.java
index ca3a71a..bc4a08b 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/remoteable/RemoteableMethodMeta.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/remoteable/RemoteableMethodMeta.java
@@ -19,6 +19,7 @@ import static org.apache.juneau.httppart.HttpPartType.*;
 import java.lang.reflect.*;
 import java.util.*;
 
+import org.apache.juneau.*;
 import org.apache.juneau.http.annotation.*;
 import org.apache.juneau.httppart.*;
 
@@ -119,10 +120,10 @@ public class RemoteableMethodMeta {
 					else
 						annotated = false;
 				}
-				RemoteMethodBeanArg rmba = RemoteMethodBeanArg.create(m, i);
+				RequestBeanMeta rmba = RequestBeanMeta.create(m, i, PropertyStore.DEFAULT);
 				if (rmba != null) {
 					annotated = true;
-					requestBeanArgs.add(rmba);
+					requestBeanArgs.add(new RemoteMethodBeanArg(i, null, rmba));
 				}
 				if (! annotated) {
 					otherArgs.add(new RemoteMethodArg(i, BODY, null));
diff --git a/juneau-doc/src/main/javadoc/overview.html b/juneau-doc/src/main/javadoc/overview.html
index bbb8127..194f67d 100644
--- a/juneau-doc/src/main/javadoc/overview.html
+++ b/juneau-doc/src/main/javadoc/overview.html
@@ -309,6 +309,7 @@
 		<li><p><a class='doclink' href='#juneau-rest-server.HasQuery'>@HasQuery</a></p>
 		<li><p><a class='doclink' href='#juneau-rest-server.Header'>@Header</a></p>
 		<li><p><a class='doclink' href='#juneau-rest-server.Path'>@Path</a></p>
+		<li><p><a class='doclink' href='#juneau-rest-server.ResponseBean'>@ResponseBean</a></p>
 		<li><p><a class='doclink' href='#juneau-rest-server.SwaggerSchemaPartParsing'>Swagger Schema Part Parsing</a></p>
 		<li><p><a class='doclink' href='#juneau-rest-server.Response'>@Response</a></p>
 		<li><p><a class='doclink' href='#juneau-rest-server.Responses'>@Responses</a></p>
@@ -13218,10 +13219,11 @@
 		</ul>
 	</div>
 	
-	<!-- === 7.14 - @PathRemainer ======================================================================= -->
+	<!-- === 7.14 - @ResponseBean ======================================================================= -->
 	
-	<h3 class='topic' onclick='toggle(this)'><a href='#juneau-rest-server.PathRemainer' id='juneau-rest-server.PathRemainer'>7.14 - @PathRemainer</a></h3>
+	<h3 class='topic' onclick='toggle(this)'><a href='#juneau-rest-server.PathRemainer' id='juneau-rest-server.ResponseBean'>7.14 - @ResponseBean</a></h3>
 	<div class='topic'>
+		TODO
 	</div>	
 
 	<!-- === 7.15 - Swagger Schema Part Parsing ========================================================= -->
@@ -22722,6 +22724,38 @@
 		<h5 class='topic w800'>juneau-marshall</h5>
 		<ul class='spaced-list'>
 			<li>
+				The REST client <ja>@Remoteable</ja> annotations and REST server <ja>@RemoteMethod</ja> annotations which used to be
+				in separate packages in the client and server projects have been combined into a single set of annotations in 
+				the {@link org.apache.juneau.http.annotation} package.
+				<br>This fixes a long-standing problem where it was easy to mix up using client-side annotations in server-side code, and vis-versa.
+				<br>Additionally, much work has been done on these annotations to add support for Swagger-style validations and documentation.
+				<ul class='doctree'>
+					<li class='ja'>{@link org.apache.juneau.http.annotation.Body}
+					<li class='ja'>{@link org.apache.juneau.http.annotation.FormData}
+					<li class='ja'>{@link org.apache.juneau.http.annotation.Header}
+					<li class='ja'>{@link org.apache.juneau.http.annotation.Path}
+					<li class='ja'>{@link org.apache.juneau.http.annotation.Query}
+					<li class='ja'>{@link org.apache.juneau.http.annotation.HasFormData}
+					<li class='ja'>{@link org.apache.juneau.http.annotation.HasQuery}
+					<li class='ja'>{@link org.apache.juneau.http.annotation.RequestBean}
+				</ul>
+				<br>These are used with new Swagger schema/documentation annotations to produce schema-based serialization/parsing/validation 
+					and auto-generated Swagger documentation:
+				<ul class='doctree'>
+					<li class='ja'>{@link org.apache.juneau.http.annotation.Contact}
+					<li class='ja'>{@link org.apache.juneau.http.annotation.ExternalDocs}
+					<li class='ja'>{@link org.apache.juneau.http.annotation.Items}
+					<li class='ja'>{@link org.apache.juneau.http.annotation.License}
+					<li class='ja'>{@link org.apache.juneau.http.annotation.Schema}
+					<li class='ja'>{@link org.apache.juneau.http.annotation.SubItems}
+					<li class='ja'>{@link org.apache.juneau.http.annotation.Tag}
+				</ul>
+			<li>
+				Support for multi-valued parameters as maps or beans on server-side annotations (it was previously supported on client-side):
+				<code><ja>@Query</ja>(<js>"*"</js>)</code>, <code><ja>@FormData</ja>(<js>"*"</js>)</code>, <code><ja>@Header</ja>(<js>"*"</js>)</code>, <code><ja>@Path</ja>(<js>"*"</js>)</code>
+			<li>
+				Support for server-side use of <ja>@ResourceBean</ja> annotation on <ja>@RestMethod</ja> annotations and new {@link org.apache.juneau.rest.RestRequest#getRequestBean(RequestBeanMeta)} method.
+			<li>
 				Fixed bug where <code><ja>@Bean</ja>(typeName)</code> was not being detected on non-bean POJO classes.
 			<li>
 				Fixed bug where HTML-Schema was not being rendered correctly.
@@ -22840,12 +22874,6 @@
 					</ul>
 				</ul>
 			<li>
-				The REST client <ja>@Remoteable</ja> annotations and REST server <ja>@RemoteMethod</ja> annotations which used to be
-				in separate packages in the client and server projects have been combined into a single set of annotations in 
-				the {@link org.apache.juneau.http.annotation} package.
-				<br>This fixes a long-standing problem where it was easy to mix up using client-side annotations in server-side code, and vis-versa.
-				<br>Additionally, much work has been done on these annotations to add support for Swagger-style validations and documentation.
-			<li>
 				The <code>JsonSerializer.Simple</code> class has been moved into the top-level {@link org.apache.juneau.json.SimpleJsonSerializer} class.
 			<li>
 				RDF serializer subclasses have been moved into top-level classes:
@@ -23011,6 +23039,15 @@
 					<li class='ja'>{@link org.apache.juneau.rest.annotation.RestMethod#pojoSwaps()}
 				</ul>
 				<br>One advantage is that you now have control over the precedence of serializers and parsers by where you insert the <code>Inherit</code> class. 
+			<li>
+				<code>RequestPathMatch</code> class has been renamed to {@link org.apache.juneau.rest.RequestPath}.
+			<li>
+				{@link org.apache.juneau.http.annotation.RequestBean @RequestBean} objects can now be used as parameters in <ja>@RestMethod</ja> methods.
+				<br>Includes new methods on {@link org.apache.juneau.rest.RestRequest}:
+				<ul class='doctree'>
+					<li class='jm'>{@link org.apache.juneau.rest.RestRequest#getRequestBean(Class) getRequestBean(Class)}
+					<li class='jm'>{@link org.apache.juneau.rest.RestRequest#getRequestBean(RequestBeanMeta) getRequestBean(RequestBeanMeta)}
+				</ul>
 		</ul>
 	
 		<h5 class='topic w800'>juneau-rest-client</h5>
diff --git a/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestClient.java b/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestClient.java
index a5e34f0..d9f06c6 100644
--- a/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestClient.java
+++ b/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestClient.java
@@ -1034,25 +1034,27 @@ public class RestClient extends BeanContext implements Closeable {
 
 						String url = rmm.getUrl();
 						String httpMethod = rmm.getHttpMethod();
+						HttpPartSerializer s = getPartSerializer();
+
 						try (RestCall rc = doCall(httpMethod, url, httpMethod.equals("POST") || httpMethod.equals("PUT"))) {
 
 							rc.serializer(serializer).parser(parser);
 
 							for (RemoteMethodArg a : rmm.getPathArgs())
-								rc.path(a.getName(), args[a.getIndex()], a.getSerializer(), a.getSchema());
+								rc.path(a.getName(), args[a.getIndex()], a.getSerializer(s), a.getSchema());
 
 							for (RemoteMethodArg a : rmm.getQueryArgs())
-								rc.query(a.getName(), args[a.getIndex()], a.isSkipIfEmpty(), a.getSerializer(), a.getSchema());
+								rc.query(a.getName(), args[a.getIndex()], a.isSkipIfEmpty(), a.getSerializer(s), a.getSchema());
 
 							for (RemoteMethodArg a : rmm.getFormDataArgs())
-								rc.formData(a.getName(), args[a.getIndex()], a.isSkipIfEmpty(), a.getSerializer(), a.getSchema());
+								rc.formData(a.getName(), args[a.getIndex()], a.isSkipIfEmpty(), a.getSerializer(s), a.getSchema());
 
 							for (RemoteMethodArg a : rmm.getHeaderArgs())
-								rc.header(a.getName(), args[a.getIndex()], a.isSkipIfEmpty(), a.getSerializer(), a.getSchema());
+								rc.header(a.getName(), args[a.getIndex()], a.isSkipIfEmpty(), a.getSerializer(s), a.getSchema());
 
 							RemoteMethodArg ba = rmm.getBodyArg();
 							if (ba != null)
-								rc.body(args[ba.getIndex()], ba.getSerializer(), ba.getSchema());
+								rc.body(args[ba.getIndex()], ba.getSerializer(null), ba.getSchema());
 
 							if (rmm.getRequestBeanArgs().length > 0) {
 								BeanSession bs = createBeanSession();
@@ -1062,20 +1064,21 @@ public class RestClient extends BeanContext implements Closeable {
 									for (BeanPropertyValue bpv : bm.getValues(false)) {
 										BeanPropertyMeta pMeta = bpv.getMeta();
 										Object val = bpv.getValue();
-										RemoteMethodArg a = rmba.getProperty(pMeta.getName());
+										RequestBeanPropertyMeta a = rmba.getProperty(pMeta.getName());
 										if (a != null) {
 											HttpPartType pt = a.getPartType();
+											HttpPartSchema schema = a.getSchema();
 											if (pt == PATH)
-												rc.path(a.getName(), val, ObjectUtils.firstNonNull(a.getSerializer(), rmba.getSerializer()), a.getSchema());
+												rc.path(a.getPartName(), val, a.getSerializer(s), schema);
 											if (val != null) {
 												if (pt == QUERY) {
-													rc.query(a.getName(), val, a.isSkipIfEmpty(), ObjectUtils.firstNonNull(a.getSerializer(), rmba.getSerializer()), a.getSchema());
+													rc.query(a.getPartName(), val, schema.isSkipIfEmpty(), a.getSerializer(s), schema);
 												} else if (pt == FORMDATA) {
-													rc.formData(a.getName(), val, a.isSkipIfEmpty(), ObjectUtils.firstNonNull(a.getSerializer(), rmba.getSerializer()), a.getSchema());
+													rc.formData(a.getPartName(), val, schema.isSkipIfEmpty(), a.getSerializer(s), schema);
 												} else if (pt == HEADER) {
-													rc.header(a.getName(), val, a.isSkipIfEmpty(), ObjectUtils.firstNonNull(a.getSerializer(), rmba.getSerializer()), a.getSchema());
+													rc.header(a.getPartName(), val, schema.isSkipIfEmpty(), a.getSerializer(s), schema);
 												} else if (pt == HttpPartType.BODY) {
-													rc.body(val, ObjectUtils.firstNonNull(a.getSerializer(), rmba.getSerializer()), a.getSchema());
+													rc.body(val, a.getSerializer(s), schema);
 												}
 											}
 										}
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 e0df82e..20ddb05 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
@@ -4349,6 +4349,10 @@ public final class RestContext extends BeanContext {
 				s = HttpPartSchema.create(Body.class, method, i);
 				rp[i] = new RestParamDefaults.BodyObject(method, s, t, ps);
 
+			} else if (hasAnnotation(RequestBean.class, method, i)) {
+				RequestBeanMeta rbm = RequestBeanMeta.create(method, i, ps);
+				rp[i] = new RestParamDefaults.RequestBeanObject(method, rbm, t);
+
 			} else if (hasAnnotation(Response.class, method, i)) {
 				s = HttpPartSchema.create(Response.class, method, i);
 				rp[i] = new RestParamDefaults.ResponseObject(method, s, t);
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestParamDefaults.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestParamDefaults.java
index 5b85476..a1635e0 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestParamDefaults.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestParamDefaults.java
@@ -601,6 +601,20 @@ class RestParamDefaults {
 		}
 	}
 
+	static final class RequestBeanObject extends RestMethodParam {
+		private final RequestBeanMeta requestBeanMeta;
+
+		protected RequestBeanObject(Method m, RequestBeanMeta rbm, Type t) {
+			super(OTHER, m, null, t, null);
+			this.requestBeanMeta = rbm;
+		}
+
+		@Override /* RestMethodParam */
+		public Object resolve(RestRequest req, RestResponse res) throws Exception {
+			return req.getRequestBean(requestBeanMeta);
+		}
+	}
+
 	static final class ResponseHeaderObject extends RestMethodParam {
 		final HttpPartSerializer partSerializer;
 		final HttpPartSchema schema;
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestRequest.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestRequest.java
index 6fc9d0d..3e2dfd9 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestRequest.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestRequest.java
@@ -15,11 +15,15 @@ package org.apache.juneau.rest;
 import static java.util.Collections.*;
 import static java.util.logging.Level.*;
 import static org.apache.juneau.html.HtmlDocSerializer.*;
+import static org.apache.juneau.httppart.HttpPartType.*;
 import static org.apache.juneau.internal.IOUtils.*;
+import static org.apache.juneau.remoteable.ReturnValue.*;
 import static org.apache.juneau.serializer.Serializer.*;
 
 import java.io.*;
+import java.lang.reflect.*;
 import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
 import java.net.*;
 import java.nio.charset.*;
 import java.text.*;
@@ -37,6 +41,7 @@ import org.apache.juneau.http.annotation.*;
 import org.apache.juneau.httppart.*;
 import org.apache.juneau.internal.*;
 import org.apache.juneau.parser.*;
+import org.apache.juneau.remoteable.*;
 import org.apache.juneau.rest.annotation.*;
 import org.apache.juneau.rest.exception.*;
 import org.apache.juneau.rest.helper.*;
@@ -1403,6 +1408,59 @@ public final class RestRequest extends HttpServletRequestWrapper {
 		return restJavaMethod.widgets;
 	}
 
+	/**
+	 * TODO
+	 *
+	 * @param c The request bean interface to instantiate.
+	 * @return A new request bean proxy for this REST request.
+	 */
+	public <T> T getRequestBean(Class<T> c) {
+		return getRequestBean(RequestBeanMeta.create(c, getContext().getPropertyStore()));
+	}
+
+	/**
+	 * Same as {@link #getRequestBean(Class)} but used on pre-instantiated {@link RequestBeanMeta} objects.
+	 *
+	 * @param requestBeanMeta The metadata about the request bean interface to create.
+	 * @return A new request bean proxy for this REST request.
+	 */
+	public <T> T getRequestBean(final RequestBeanMeta requestBeanMeta) {
+		try {
+			Class<T> c = (Class<T>)requestBeanMeta.getClassMeta().getInnerClass();
+			final BeanMeta<T> bm = getBeanSession().getBeanMeta(c);
+			return (T)Proxy.newProxyInstance(
+				c.getClassLoader(),
+				new Class[] { c },
+				new InvocationHandler() {
+					@Override /* InvocationHandler */
+					public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
+						RequestBeanPropertyMeta pm = requestBeanMeta.getPropertyByGetter(method.getName());
+						if (pm != null) {
+							HttpPartParser pp = pm.getParser(getPartParser());
+							HttpPartSchema schema = pm.getSchema();
+							String name = pm.getPartName();
+							ClassMeta<?> type = getContext().getBeanContext().getClassMeta(method.getGenericReturnType());
+							HttpPartType pt = pm.getPartType();
+							if (pt == HttpPartType.BODY)
+								return getBody().asType(pm.getParser(null), schema, type);
+							if (pt == HttpPartType.QUERY)
+								return getQuery().get(pp, schema, name, type);
+							if (pt == HttpPartType.FORMDATA)
+								return getFormData().get(pp, schema, name, type);
+							if (pt == HttpPartType.HEADER)
+								return getHeaders().get(pp, schema, name, type);
+							if (pt == HttpPartType.PATH)
+								return getPathMatch().get(pp, schema, name, type);
+						}
+						return null;
+					}
+
+			});
+		} catch (Exception e) {
+			throw new RuntimeException(e);
+		}
+	}
+
 	@Override /* Object */
 	public String toString() {
 		StringBuilder sb = new StringBuilder("\n").append(getDescription()).append("\n");
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/HookEvent.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/HookEvent.java
index 56249bb..00808bf 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/HookEvent.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/HookEvent.java
@@ -164,7 +164,7 @@ public enum HookEvent {
 	 * 			<li>{@link org.apache.juneau.parser.Parser}
 	 * 			<li>{@link Locale}
 	 * 			<li>{@link Swagger}
-	 * 			<li>{@link RequestPathMatch}
+	 * 			<li>{@link RequestPath}
 	 * 			<li>{@link RequestBody}
 	 * 			<li>{@link Config}
 	 * 			<li>{@link UriContext}