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 3305b27 Context API refactoring.
3305b27 is described below
commit 3305b270c896ee3f42bc10f6229a5ab6a2eae0c5
Author: JamesBognar <[email protected]>
AuthorDate: Thu Sep 9 17:28:06 2021 -0400
Context API refactoring.
---
.../java/org/apache/juneau/ContextBeanCreator.java | 150 ++++++++++++++
.../org/apache/juneau/httppart/HttpPartParser.java | 38 ++++
.../apache/juneau/httppart/HttpPartSerializer.java | 39 ++++
.../org/apache/juneau/rest/RequestHttpPart.java | 2 +-
.../java/org/apache/juneau/rest/RestContext.java | 230 +++------------------
.../org/apache/juneau/rest/RestContextBuilder.java | 135 +++++-------
.../java/org/apache/juneau/rest/RestOpContext.java | 63 +++---
.../apache/juneau/rest/RestOpContextBuilder.java | 48 +++++
.../java/org/apache/juneau/rest/RestRequest.java | 6 +-
.../org/apache/juneau/rest/annotation/Rest.java | 10 +-
.../juneau/rest/annotation/RestAnnotation.java | 8 +-
.../juneau/rest/logging/RestLoggerRuleBuilder.java | 2 +-
12 files changed, 382 insertions(+), 349 deletions(-)
diff --git
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/ContextBeanCreator.java
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/ContextBeanCreator.java
new file mode 100644
index 0000000..b61130e
--- /dev/null
+++
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/ContextBeanCreator.java
@@ -0,0 +1,150 @@
+//
***************************************************************************************************************************
+// * 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;
+
+import static org.apache.juneau.internal.ExceptionUtils.*;
+import static java.util.Optional.*;
+
+import java.util.*;
+
+/**
+ * Utility class for instantiating a Context bean.
+ *
+ * <p>
+ * Contains either a pre-existing Context bean, or a builder for that bean.
+ * If it's a builder, then annotations can be applied to it.
+ *
+ * @param <T> The bean type.
+ */
+public class ContextBeanCreator<T> {
+
+ /**
+ * Creator.
+ *
+ * @param type The bean type.
+ * @return A new creator object.
+ */
+ public static <T> ContextBeanCreator<T> create(Class<T> type) {
+ return new ContextBeanCreator<>(type);
+ }
+
+ private Class<T> type;
+ private T value;
+ private ContextBuilder builder;
+
+ /**
+ * Constructor.
+ *
+ * @param type The bean type.
+ */
+ protected ContextBeanCreator(Class<T> type) {
+ this.type = type;
+ }
+
+ /**
+ * Copy constructor.
+ *
+ * @param copyFrom The creator to copy from.
+ */
+ protected ContextBeanCreator(ContextBeanCreator<T> copyFrom) {
+ this.type = copyFrom.type;
+ this.value = copyFrom.value;
+ this.builder = copyFrom.builder == null ? null :
copyFrom.builder.copy();
+ }
+
+ /**
+ * Sets an already instantiated object on this creator.
+ *
+ * @param value The bean to set.
+ * @return This object.
+ */
+ public ContextBeanCreator<T> set(T value) {
+ this.value = value;
+ return this;
+ }
+
+ /**
+ * Sets the implementation type of the bean.
+ *
+ * <p>
+ * The class type must extend from {@link Context} and have a builder
create method.
+ *
+ * @param value The bean type.
+ * @return This object.
+ */
+ @SuppressWarnings("unchecked")
+ public ContextBeanCreator<T> set(Class<? extends T> value) {
+ builder = Context.createBuilder((Class<? extends Context>)
value);
+ if (builder == null)
+ throw runtimeException("Creator for class {0} not
found." + value.getName());
+ return this;
+ }
+
+ /**
+ * Returns access to the inner builder if the builder exists and is of
the specified type.
+ *
+ * @param c The builder class type.
+ * @return An optional containing the builder if it exists.
+ */
+ @SuppressWarnings("unchecked")
+ public <T2 extends ContextBuilder> Optional<T2> builder(Class<T2> c) {
+ return ofNullable(c.isInstance(builder) ? (T2)builder : null);
+ }
+
+ /**
+ * Returns true if any of the annotations/appliers can be applied to
the inner builder (if it has one).
+ *
+ * @param work The work to check.
+ * @return This object.
+ */
+ public boolean canApply(List<AnnotationWork> work) {
+ if (builder != null)
+ return (builder.canApply(work));
+ return false;
+ }
+
+ /**
+ * Applies the specified annotations to all applicable serializer
builders in this group.
+ *
+ * @param work The annotations to apply.
+ * @return This object (for method chaining).
+ */
+ public ContextBeanCreator<T> apply(List<AnnotationWork> work) {
+ if (builder != null)
+ builder.apply(work);
+ return this;
+ }
+
+ /**
+ * Creates a new copy of this creator.
+ *
+ * @return A new copy of this creator.
+ */
+ public ContextBeanCreator<T> copy() {
+ return new ContextBeanCreator<>(this);
+ }
+
+ /**
+ * Returns the built bean.
+ *
+ * @return The built bean.
+ */
+ @SuppressWarnings("unchecked")
+ public T create() {
+ if (value != null)
+ return value;
+ if (builder != null)
+ return (T)builder.build();
+ return null;
+ }
+}
diff --git
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/httppart/HttpPartParser.java
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/httppart/HttpPartParser.java
index a4c8e39..66dfac5 100644
---
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/httppart/HttpPartParser.java
+++
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/httppart/HttpPartParser.java
@@ -43,6 +43,44 @@ public interface HttpPartParser {
public static interface Null extends HttpPartParser {}
/**
+ * Instantiates a creator for a part parser.
+ * @return A new creator.
+ */
+ public static Creator creator() {
+ return new Creator();
+ }
+
+ /**
+ * A creator for a part parser.
+ */
+ public static class Creator extends ContextBeanCreator<HttpPartParser> {
+ Creator() {
+ super(HttpPartParser.class);
+ }
+
+ Creator(Creator creator) {
+ super(creator);
+ }
+
+ @Override
+ public Creator set(HttpPartParser value) {
+ super.set(value);
+ return this;
+ }
+
+ @Override
+ public Creator set(Class<? extends HttpPartParser> value) {
+ super.set(value);
+ return this;
+ }
+
+ @Override
+ public Creator copy() {
+ return new Creator(this);
+ }
+ }
+
+ /**
* Creates a new parser session.
*
* @param args The runtime arguments for the session.
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 f6475a6..f9c6298 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
@@ -55,6 +55,45 @@ public interface HttpPartSerializer {
public static interface Null extends HttpPartSerializer {}
/**
+ * Instantiates a creator for a part serializer.
+ * @return A new creator.
+ */
+ public static Creator creator() {
+ return new Creator();
+ }
+
+ /**
+ * A creator for a part serializer.
+ */
+ public static class Creator extends
ContextBeanCreator<HttpPartSerializer> {
+
+ Creator() {
+ super(HttpPartSerializer.class);
+ }
+
+ Creator(Creator builder) {
+ super(builder);
+ }
+
+ @Override
+ public Creator set(HttpPartSerializer value) {
+ super.set(value);
+ return this;
+ }
+
+ @Override
+ public Creator set(Class<? extends HttpPartSerializer> value) {
+ super.set(value);
+ return this;
+ }
+
+ @Override
+ public Creator copy() {
+ return new Creator(this);
+ }
+ }
+
+ /**
* Creates a new serializer session.
*
* @param args The runtime arguments for the session.
diff --git
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RequestHttpPart.java
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RequestHttpPart.java
index 23c6dc6..f55e6a3 100644
---
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RequestHttpPart.java
+++
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RequestHttpPart.java
@@ -74,7 +74,7 @@ public abstract class RequestHttpPart {
* Specifies the part parser to use for this part.
*
* <p>
- * If not specified, uses the part parser defined on the client by
calling {@link RestContextBuilder#partParser(Class)}.
+ * If not specified, uses the part parser defined on the client by
calling {@link RestContextBuilder#getPartParser()}.
*
* @param value
* The new part parser to use for this part.
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 e223c19..035c11b 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
@@ -66,7 +66,6 @@ import org.apache.juneau.http.response.*;
import org.apache.juneau.rest.util.*;
import org.apache.juneau.rest.vars.*;
import org.apache.juneau.svl.*;
-import org.apache.juneau.uon.*;
import org.apache.juneau.utils.*;
/**
@@ -372,151 +371,6 @@ public class RestContext extends BeanContext {
public static final String REST_messages = PREFIX + ".messages.lo";
/**
- * Configuration property: HTTP part parser.
- *
- * <h5 class='section'>Property:</h5>
- * <ul class='spaced-list'>
- * <li><b>ID:</b> {@link
org.apache.juneau.rest.RestContext#REST_partParser REST_partParser}
- * <li><b>Name:</b> <js>"RestContext.partParser.o"</js>
- * <li><b>Data type:</b> <c>{@link
org.apache.juneau.httppart.HttpPartParser}|Class<{@link
org.apache.juneau.httppart.HttpPartParser}></c>
- * <li><b>Default:</b> {@link
org.apache.juneau.oapi.OpenApiParser}
- * <li><b>Session property:</b> <jk>false</jk>
- * <li><b>Annotations:</b>
- * <ul>
- * <li class='ja'>{@link
org.apache.juneau.rest.annotation.Rest#partParser()}
- * </ul>
- * <li><b>Methods:</b>
- * <ul>
- * <li class='jm'>{@link
org.apache.juneau.rest.RestContextBuilder#partParser(Class)}
- * <li class='jm'>{@link
org.apache.juneau.rest.RestContextBuilder#partParser(HttpPartParser)}
- * </ul>
- * </ul>
- *
- * <h5 class='section'>Description:</h5>
- * <p>
- * Specifies the {@link HttpPartParser} to use for parsing headers,
query/form parameters, and URI parts.
- *
- * <p>
- * The default value is {@link OpenApiParser} which allows for both
plain-text and URL-Encoded-Object-Notation values.
- * <br>If your parts contain text that can be confused with UON (e.g.
<js>"(foo)"</js>), you can switch to
- * {@link SimplePartParser} which treats everything as plain text.
- *
- * <h5 class='section'>Example:</h5>
- * <p class='bcode w800'>
- * <jc>// Option #1 - Defined via annotation.</jc>
- * <ja>@Rest</ja>(partParser=SimplePartParser.<jk>class</jk>)
- * <jk>public class</jk> MyResource {
- *
- * <jc>// Option #2 - Defined via builder passed in
through resource constructor.</jc>
- * <jk>public</jk> MyResource(RestContextBuilder
<jv>builder</jv>) <jk>throws</jk> Exception {
- *
- * <jc>// Using method on builder.</jc>
- *
<jv>builder</jv>.partParser(SimplePartParser.<jk>class</jk>);
- *
- * <jc>// Same, but using property.</jc>
- *
<jv>builder</jv>.set(<jsf>REST_partParser</jsf>,
SimplePartParser.<jk>class</jk>);
- * }
- *
- * <jc>// Option #3 - 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>.partParser(SimplePartParser.<jk>class</jk>);
- * }
- *
- * <ja>@RestPost</ja>(...)
- * <jk>public</jk> Object
myMethod(<ja>@Header</ja>(<js>"My-Header"</js>) MyParsedHeader <jv>h</jv>,
<ja>@Query</ja>(<js>"myquery"</js>) MyParsedQuery <jv>q</jv>) {
- * <jc>// Do something with your parsed parts.</jc>
- * }
- * }
- * </p>
- *
- * <ul class='notes'>
- * <li>
- * When defined as a class, properties/transforms defined
on the resource/method are inherited.
- * <li>
- * When defined as an instance, properties/transforms
defined on the resource/method are NOT inherited.
- * </ul>
- */
- public static final String REST_partParser = PREFIX + ".partParser.o";
-
- /**
- * Configuration property: HTTP part serializer.
- *
- * <h5 class='section'>Property:</h5>
- * <ul class='spaced-list'>
- * <li><b>ID:</b> {@link
org.apache.juneau.rest.RestContext#REST_partSerializer REST_partSerializer}
- * <li><b>Name:</b> <js>"RestContext.partSerializer.o"</js>
- * <li><b>Data type:</b>
- * <ul>
- * <li>{@link
org.apache.juneau.httppart.HttpPartSerializer}
- * <li><c>Class<{@link
org.apache.juneau.httppart.HttpPartSerializer}></c>
- * </ul>
- * <li><b>Default:</b> {@link
org.apache.juneau.oapi.OpenApiSerializer}
- * <li><b>Session property:</b> <jk>false</jk>
- * <li><b>Annotations:</b>
- * <ul>
- * <li class='ja'>{@link
org.apache.juneau.rest.annotation.Rest#partSerializer()}
- * </ul>
- * <li><b>Methods:</b>
- * <ul>
- * <li class='jm'>{@link
org.apache.juneau.rest.RestContextBuilder#partSerializer(Class)}
- * <li class='jm'>{@link
org.apache.juneau.rest.RestContextBuilder#partSerializer(HttpPartSerializer)}
- * </ul>
- * </ul>
- *
- * <h5 class='section'>Description:</h5>
- * <p>
- * Specifies the {@link HttpPartSerializer} to use for serializing
headers, query/form parameters, and URI parts.
- *
- * <p>
- * The default value is {@link OpenApiSerializer} which serializes
based on OpenAPI rules, but defaults to UON notation for beans and maps, and
- * plain text for everything else.
- * <br>Other options include:
- * <ul>
- * <li class='jc'>{@link SimplePartSerializer} - Always serializes
to plain text.
- * <li class='jc'>{@link UonSerializer} - Always serializers to
UON.
- * </ul>
- *
- * <h5 class='section'>Example:</h5>
- * <p class='bcode w800'>
- * <jc>// Option #1 - Defined via annotation.</jc>
- *
<ja>@Rest</ja>(partSerializer=SimplePartSerializer.<jk>class</jk>)
- * <jk>public class</jk> MyResource {
- *
- * <jc>// Option #2 - Defined via builder passed in
through resource constructor.</jc>
- * <jk>public</jk> MyResource(RestContextBuilder
<jv>builder</jv>) <jk>throws</jk> Exception {
- *
- * <jc>// Using method on builder.</jc>
- *
<jv>builder</jv>.partSerializer(SimplePartSerializer.<jk>class</jk>);
- *
- * <jc>// Same, but using property.</jc>
- *
<jv>builder</jv>.set(<jsf>REST_partSerializer</jsf>,
SimplePartSerializer.<jk>class</jk>);
- * }
- *
- * <jc>// Option #3 - 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>.partSerializer(SimplePartSerializer.<jk>class</jk>);
- * }
- *
- * <ja>@RestPost</ja>(...)
- * <jk>public</jk> Object myMethod(RestResponse
<jv>res</jv>) {
- * <jc>// Set a header to a POJO.</jc>
- * <jv>res</jv>.setHeader(<js>"My-Header"</js>,
<jk>new</jk> MyPojo());
- * }
- * }
- * </p>
- *
- * <ul class='notes'>
- * <li>
- * When defined as a class, properties/transforms defined
on the resource/method are inherited.
- * <li>
- * When defined as an instance, properties/transforms
defined on the resource/method are NOT inherited.
- * </ul>
- */
- public static final String REST_partSerializer = PREFIX +
".partSerializer.o";
-
- /**
* Configuration property: Render response stack traces in responses.
*
* <h5 class='section'>Property:</h5>
@@ -900,10 +754,10 @@ public class RestContext extends BeanContext {
callLogger = createCallLogger(r, builder, bf, l, ts);
bf.addBean(RestLogger.class, callLogger);
- partSerializer = createPartSerializer(r, cp, bf);
+ partSerializer = createPartSerializer(r, builder, bf);
bf.addBean(HttpPartSerializer.class, partSerializer);
- partParser = createPartParser(r, cp, bf);
+ partParser = createPartParser(r, builder, bf);
bf.addBean(HttpPartParser.class, partParser);
jsonSchemaGenerator = createJsonSchemaGenerator(r, cp,
bf);
@@ -1583,9 +1437,9 @@ public class RestContext extends BeanContext {
* Instantiates based on the following logic:
* <ul>
* <li>Returns the resource class itself is an instance of {@link
HttpPartSerializer}.
- * <li>Looks for {@link #REST_partSerializer} value set via any of
the following:
+ * <li>Looks for part serializer set via any of the following:
* <ul>
- * <li>{@link
RestContextBuilder#partSerializer(Class)}/{@link
RestContextBuilder#partSerializer(HttpPartSerializer)}
+ * <li>{@link
RestContextBuilder#getPartSerializer()}
* <li>{@link Rest#partSerializer()}.
* </ul>
* <li>Looks for a static or non-static
<c>createPartSerializer()</> method that returns <c>{@link
HttpPartSerializer}</c> on the
@@ -1599,46 +1453,32 @@ public class RestContext extends BeanContext {
* <li>Instantiates an {@link OpenApiSerializer}.
* </ul>
*
- * <ul class='seealso'>
- * <li class='jf'>{@link #REST_partSerializer}
- * </ul>
- *
* @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 HTTP part serializer for this REST resource.
* @throws Exception If serializer could not be instantiated.
*/
- protected HttpPartSerializer createPartSerializer(Object resource,
ContextProperties properties, BeanStore beanStore) throws Exception {
+ protected HttpPartSerializer createPartSerializer(Object resource,
RestContextBuilder builder, BeanStore beanStore) throws Exception {
- HttpPartSerializer x = null;
+ HttpPartSerializer.Creator x = builder.partSerializer;
- if (resource instanceof HttpPartSerializer)
- x = (HttpPartSerializer)resource;
-
- if (x == null)
- x = properties.getInstance(REST_partSerializer,
HttpPartSerializer.class, beanStore).orElse(null);
-
- if (x == null)
- x =
beanStore.getBean(HttpPartSerializer.class).orElse(null);
-
- if (x == null)
- x =
OpenApiSerializer.create().apply(properties).build();
+ if (beanStore.hasBean(HttpPartSerializer.class))
+
x.set(beanStore.getBean(HttpPartSerializer.class).orElse(null));
x = BeanStore
.of(beanStore, resource)
- .addBean(HttpPartSerializer.class, x)
- .beanCreateMethodFinder(HttpPartSerializer.class,
resource)
+ .addBean(HttpPartSerializer.Creator.class, x)
+
.beanCreateMethodFinder(HttpPartSerializer.Creator.class, resource)
.find("createPartSerializer")
.withDefault(x)
.run();
- return x;
+ return x.create();
}
/**
@@ -1648,9 +1488,9 @@ public class RestContext extends BeanContext {
* Instantiates based on the following logic:
* <ul>
* <li>Returns the resource class itself is an instance of {@link
HttpPartParser}.
- * <li>Looks for {@link #REST_partParser} value set via any of the
following:
+ * <li>Looks for part parser value set via any of the following:
* <ul>
- * <li>{@link
RestContextBuilder#partParser(Class)}/{@link
RestContextBuilder#partParser(HttpPartParser)}
+ * <li>{@link RestContextBuilder#getPartParser()}
* <li>{@link Rest#partParser()}.
* </ul>
* <li>Looks for a static or non-static <c>createPartParser()</>
method that returns <c>{@link HttpPartParser}</c> on the
@@ -1664,46 +1504,32 @@ public class RestContext extends BeanContext {
* <li>Instantiates an {@link OpenApiSerializer}.
* </ul>
*
- * <ul class='seealso'>
- * <li class='jf'>{@link #REST_partParser}
- * </ul>
- *
* @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 HTTP part parser for this REST resource.
* @throws Exception If parser could not be instantiated.
*/
- protected HttpPartParser createPartParser(Object resource,
ContextProperties properties, BeanStore beanStore) throws Exception {
-
- HttpPartParser x = null;
+ protected HttpPartParser createPartParser(Object resource,
RestContextBuilder builder, BeanStore beanStore) throws Exception {
- if (resource instanceof HttpPartParser)
- x = (HttpPartParser)resource;
-
- if (x == null)
- x = properties.getInstance(REST_partParser,
HttpPartParser.class, beanStore).orElse(null);
-
- if (x == null)
- x =
beanStore.getBean(HttpPartParser.class).orElse(null);
+ HttpPartParser.Creator x = builder.partParser;
- if (x == null)
- x = OpenApiParser.create().apply(properties).build();
+ if (beanStore.hasBean(HttpPartParser.class))
+
x.set(beanStore.getBean(HttpPartParser.class).orElse(null));
x = BeanStore
.of(beanStore, resource)
- .addBean(HttpPartParser.class, x)
- .beanCreateMethodFinder(HttpPartParser.class, resource)
+ .addBean(HttpPartParser.Creator.class, x)
+ .beanCreateMethodFinder(HttpPartParser.Creator.class,
resource)
.find("createPartParser")
.withDefault(x)
.run();
- return x;
+ return x.create();
}
/**
@@ -3381,10 +3207,6 @@ public class RestContext extends BeanContext {
/**
* Returns the HTTP-part parser associated with this resource.
*
- * <ul class='seealso'>
- * <li class='jf'>{@link RestContext#REST_partParser}
- * </ul>
- *
* @return
* The HTTP-part parser associated with this resource.
* <br>Never <jk>null</jk>.
@@ -3396,10 +3218,6 @@ public class RestContext extends BeanContext {
/**
* Returns the HTTP-part serializer associated with this resource.
*
- * <ul class='seealso'>
- * <li class='jf'>{@link RestContext#REST_partSerializer}
- * </ul>
- *
* @return
* The HTTP-part serializer associated with this resource.
* <br>Never <jk>null</jk>.
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 2673203..1a262aa 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
@@ -52,6 +52,7 @@ import org.apache.juneau.rest.vars.*;
import org.apache.juneau.serializer.*;
import org.apache.juneau.svl.*;
import org.apache.juneau.svl.vars.*;
+import org.apache.juneau.uon.*;
import org.apache.juneau.utils.*;
/**
@@ -144,6 +145,8 @@ public class RestContextBuilder extends BeanContextBuilder
implements ServletCon
EncoderGroup.Builder encoders =
EncoderGroup.create().add(IdentityEncoder.INSTANCE);
SerializerGroup.Builder serializers = SerializerGroup.create();
ParserGroup.Builder parsers = ParserGroup.create();
+ HttpPartSerializer.Creator partSerializer =
HttpPartSerializer.creator().set(OpenApiSerializer.class);
+ HttpPartParser.Creator partParser =
HttpPartParser.creator().set(OpenApiParser.class);
Enablement debugDefault, debug;
@@ -215,10 +218,6 @@ public class RestContextBuilder extends BeanContextBuilder
implements ServletCon
ClassInfo rci = ClassInfo.of(resourceClass);
- // Default values.
- partSerializer(OpenApiSerializer.class);
- partParser(OpenApiParser.class);
-
// Pass-through default values.
if (parentContext.isPresent()) {
RestContext pc = parentContext.get();
@@ -559,6 +558,48 @@ public class RestContextBuilder extends BeanContextBuilder
implements ServletCon
}
/**
+ * Returns the HTTP part parser creator containing the part parser for
parsing HTTP parts into POJOs.
+ *
+ * <p>
+ * The default value is {@link OpenApiParser} which allows for both
plain-text and URL-Encoded-Object-Notation values.
+ * <br>If your parts contain text that can be confused with UON (e.g.
<js>"(foo)"</js>), you can switch to
+ * {@link SimplePartParser} which treats everything as plain text.
+ *
+ * <p>
+ * When specified as a class, annotations on this class are applied to
the parser.
+ * Otherwise when specified as an already-instantiated {@link
HttpPartParser}, annotations will not be applied.
+ *
+ * @return The HTTP part parser creator.
+ */
+ public HttpPartParser.Creator getPartParser() {
+ return partParser;
+ }
+
+ /**
+ * Returns the HTTP part serializer creator containing the part
serializer for serializing POJOs to HTTP parts.
+ *
+ * <p>
+ * The default value is {@link OpenApiSerializer} which serializes
based on OpenAPI rules, but defaults to UON notation for beans and maps, and
+ * plain text for everything else.
+ *
+ * <p>
+ * <br>Other options include:
+ * <ul>
+ * <li class='jc'>{@link SimplePartSerializer} - Always serializes
to plain text.
+ * <li class='jc'>{@link UonSerializer} - Always serializers to
UON.
+ * </ul>
+ *
+ * <p>
+ * When specified as a class, annotations on this class are applied to
the serializer.
+ * Otherwise when specified as an already-instantiated {@link
HttpPartSerializer}, annotations will not be applied.
+ *
+ * @return The HTTP part serializer creator.
+ */
+ public HttpPartSerializer.Creator getPartSerializer() {
+ return partSerializer;
+ }
+
+ /**
* Returns the encoder group builder containing the encoders for
compressing/decompressing input and output streams.
*
* <p>
@@ -1775,90 +1816,6 @@ public class RestContextBuilder extends
BeanContextBuilder implements ServletCon
}
/**
- * <i><l>RestContext</l> configuration property: </i> HTTP part
parser.
- *
- * <p>
- * Specifies the {@link HttpPartParser} to use for parsing headers,
query/form parameters, and URI parts.
- *
- * <ul class='seealso'>
- * <li class='jf'>{@link RestContext#REST_partParser}
- * </ul>
- *
- * @param value
- * The new value for this setting.
- * <br>The default is {@link OpenApiParser}.
- * @return This object (for method chaining).
- */
- @FluentSetter
- public RestContextBuilder partParser(Class<? extends HttpPartParser>
value) {
- if (value != HttpPartParser.Null.class)
- set(REST_partParser, value);
- return this;
- }
-
- /**
- * <i><l>RestContext</l> configuration property: </i> HTTP part
parser.
- *
- * <p>
- * Same as {@link #partParser(Class)} except input is a pre-constructed
instance.
- *
- * <ul class='seealso'>
- * <li class='jf'>{@link RestContext#REST_partParser}
- * </ul>
- *
- * @param value
- * The new value for this setting.
- * <br>The default is {@link OpenApiParser}.
- * @return This object (for method chaining).
- */
- @FluentSetter
- public RestContextBuilder partParser(HttpPartParser value) {
- return set(REST_partParser, value);
- }
-
- /**
- * <i><l>RestContext</l> configuration property: </i> HTTP part
serializer.
- *
- * <p>
- * Specifies the {@link HttpPartSerializer} to use for serializing
headers, query/form parameters, and URI parts.
- *
- * <ul class='seealso'>
- * <li class='jf'>{@link RestContext#REST_partSerializer}
- * </ul>
- *
- * @param value
- * The new value for this setting.
- * <br>The default is {@link OpenApiSerializer}.
- * @return This object (for method chaining).
- */
- @FluentSetter
- public RestContextBuilder partSerializer(Class<? extends
HttpPartSerializer> value) {
- if (value != HttpPartSerializer.Null.class)
- set(REST_partSerializer, value);
- return this;
- }
-
- /**
- * <i><l>RestContext</l> configuration property: </i> HTTP part
serializer.
- *
- * <p>
- * Same as {@link #partSerializer(Class)} except input is a
pre-constructed instance.
- *
- * <ul class='seealso'>
- * <li class='jf'>{@link RestContext#REST_partSerializer}
- * </ul>
- *
- * @param value
- * The new value for this setting.
- * <br>The default is {@link OpenApiSerializer}.
- * @return This object (for method chaining).
- */
- @FluentSetter
- public RestContextBuilder partSerializer(HttpPartSerializer value) {
- return set(REST_partSerializer, value);
- }
-
- /**
* Resource path.
*
* <p>
@@ -2823,6 +2780,8 @@ public class RestContextBuilder extends
BeanContextBuilder implements ServletCon
super.apply(work);
serializers.apply(work);
parsers.apply(work);
+ partSerializer.apply(work);
+ partParser.apply(work);
return this;
}
diff --git
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestOpContext.java
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestOpContext.java
index 7776c8a..a3a1e5b 100644
---
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestOpContext.java
+++
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestOpContext.java
@@ -18,7 +18,6 @@ import static org.apache.juneau.internal.StringUtils.*;
import static org.apache.juneau.internal.StringUtils.firstNonEmpty;
import static org.apache.juneau.http.HttpHeaders.*;
import static org.apache.juneau.httppart.HttpPartType.*;
-import static org.apache.juneau.rest.RestContext.*;
import static org.apache.juneau.rest.util.RestUtils.*;
import static org.apache.juneau.rest.HttpRuntimeException.*;
import static java.util.Collections.*;
@@ -154,10 +153,10 @@ public class RestOpContext extends BeanContext implements
Comparable<RestOpConte
parsers = createParsers(r, builder, bs);
bs.addBean(ParserGroup.class, parsers);
- partSerializer = createPartSerializer(r, cp, bs);
+ partSerializer = createPartSerializer(r, builder, bs);
bs.addBean(HttpPartSerializer.class, partSerializer);
- partParser = createPartParser(r, cp, bs);
+ partParser = createPartParser(r, builder, bs);
bs.addBean(HttpPartParser.class, partParser);
converters = createConverters(r, builder, bs).asArray();
@@ -526,9 +525,9 @@ public class RestOpContext extends BeanContext implements
Comparable<RestOpConte
* Instantiates based on the following logic:
* <ul>
* <li>Returns the resource class itself is an instance of {@link
HttpPartSerializer}.
- * <li>Looks for {@link RestContext#REST_partSerializer} value set
via any of the following:
+ * <li>Looks for part serializer set via any of the following:
* <ul>
- * <li>{@link
RestContextBuilder#partSerializer(Class)}/{@link
RestContextBuilder#partSerializer(HttpPartSerializer)}
+ * <li>{@link
RestContextBuilder#getPartSerializer()}
* <li>{@link Rest#partSerializer()}.
* </ul>
* <li>Looks for a static or non-static
<c>createPartSerializer()</> method that returns <c>{@link
HttpPartSerializer}</c> on the
@@ -543,38 +542,33 @@ public class RestOpContext extends BeanContext implements
Comparable<RestOpConte
* </ul>
*
* @param resource The REST resource object.
- * @param properties The property store of this method.
+ * @param builder The builder for this object.
* @param beanStore The bean store to use for retrieving and creating
beans.
* @return The HTTP part serializer for this REST resource.
* @throws Exception If serializer could not be instantiated.
- * @see RestContext#REST_partSerializer
*/
- protected HttpPartSerializer createPartSerializer(Object resource,
ContextProperties properties, BeanStore beanStore) throws Exception {
+ protected HttpPartSerializer createPartSerializer(Object resource,
RestOpContextBuilder builder, BeanStore beanStore) throws Exception {
- HttpPartSerializer x = null;
+ HttpPartSerializer g =
beanStore.getBean(HttpPartSerializer.class).orElse(null);
- if (resource instanceof HttpPartSerializer)
- x = (HttpPartSerializer)resource;
-
- if (x == null)
- x = properties.getInstance(REST_partSerializer,
HttpPartSerializer.class, beanStore).orElse(null);
+ if (g != null)
+ return g;
- if (x == null)
- x =
beanStore.getBean(HttpPartSerializer.class).orElse(null);
+ HttpPartSerializer.Creator x = builder.partSerializer;
if (x == null)
- x =
OpenApiSerializer.create().apply(properties).build();
+ x = builder.restContext.builder.partSerializer;
x = BeanStore
.of(beanStore, resource)
- .addBean(HttpPartSerializer.class, x)
- .beanCreateMethodFinder(HttpPartSerializer.class,
resource)
+ .addBean(HttpPartSerializer.Creator.class, x)
+
.beanCreateMethodFinder(HttpPartSerializer.Creator.class, resource)
.find("createPartSerializer", Method.class)
.thenFind("createPartSerializer")
.withDefault(x)
.run();
- return x;
+ return x.create();
}
/**
@@ -584,9 +578,9 @@ public class RestOpContext extends BeanContext implements
Comparable<RestOpConte
* Instantiates based on the following logic:
* <ul>
* <li>Returns the resource class itself is an instance of {@link
HttpPartParser}.
- * <li>Looks for {@link RestContext#REST_partParser} value set via
any of the following:
+ * <li>Looks for part parser set via any of the following:
* <ul>
- * <li>{@link
RestContextBuilder#partParser(Class)}/{@link
RestContextBuilder#partParser(HttpPartParser)}
+ * <li>{@link RestContextBuilder#getPartParser()}
* <li>{@link Rest#partParser()}.
* </ul>
* <li>Looks for a static or non-static <c>createPartParser()</>
method that returns <c>{@link HttpPartParser}</c> on the
@@ -601,38 +595,33 @@ public class RestOpContext extends BeanContext implements
Comparable<RestOpConte
* </ul>
*
* @param resource The REST resource object.
- * @param properties The property store of this method.
+ * @param builder The builder for this object.
* @param beanStore The bean store to use for retrieving and creating
beans.
* @return The HTTP part parser for this REST resource.
* @throws Exception If parser could not be instantiated.
- * @see RestContext#REST_partParser
*/
- protected HttpPartParser createPartParser(Object resource,
ContextProperties properties, BeanStore beanStore) throws Exception {
+ protected HttpPartParser createPartParser(Object resource,
RestOpContextBuilder builder, BeanStore beanStore) throws Exception {
- HttpPartParser x = null;
+ HttpPartParser g =
beanStore.getBean(HttpPartParser.class).orElse(null);
- if (resource instanceof HttpPartParser)
- x = (HttpPartParser)resource;
-
- if (x == null)
- x = properties.getInstance(REST_partParser,
HttpPartParser.class, beanStore).orElse(null);
+ if (g != null)
+ return g;
- if (x == null)
- x =
beanStore.getBean(HttpPartParser.class).orElse(null);
+ HttpPartParser.Creator x = builder.partParser;
if (x == null)
- x = OpenApiParser.create().apply(properties).build();
+ x = builder.restContext.builder.partParser;
x = BeanStore
.of(beanStore, resource)
- .addBean(HttpPartParser.class, x)
- .beanCreateMethodFinder(HttpPartParser.class, resource)
+ .addBean(HttpPartParser.Creator.class, x)
+ .beanCreateMethodFinder(HttpPartParser.Creator.class,
resource)
.find("createPartParser", Method.class)
.thenFind("createPartParser")
.withDefault(x)
.run();
- return x;
+ return x.create();
}
/**
diff --git
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestOpContextBuilder.java
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestOpContextBuilder.java
index e7b8137..11e8326 100644
---
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestOpContextBuilder.java
+++
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestOpContextBuilder.java
@@ -26,13 +26,17 @@ import org.apache.juneau.http.header.*;
import org.apache.juneau.http.part.*;
import org.apache.juneau.http.remote.*;
import org.apache.juneau.http.response.*;
+import org.apache.juneau.httppart.*;
import org.apache.juneau.internal.*;
+import org.apache.juneau.oapi.*;
import org.apache.juneau.parser.*;
import org.apache.juneau.reflect.*;
import org.apache.juneau.rest.annotation.*;
import org.apache.juneau.rest.converters.*;
import org.apache.juneau.serializer.*;
import org.apache.juneau.svl.*;
+import org.apache.juneau.uon.*;
+
import java.lang.reflect.Method;
import java.nio.charset.*;
@@ -58,6 +62,8 @@ public class RestOpContextBuilder extends BeanContextBuilder {
EncoderGroup.Builder encoders;
SerializerGroup.Builder serializers;
ParserGroup.Builder parsers;
+ HttpPartSerializer.Creator partSerializer;
+ HttpPartParser.Creator partParser;
Charset defaultCharset;
Long maxInput;
@@ -115,6 +121,10 @@ public class RestOpContextBuilder extends
BeanContextBuilder {
getSerializers().apply(al);
if (context.builder.parsers.canApply(al))
getParsers().apply(al);
+ if (context.builder.partSerializer.canApply(al))
+ getPartSerializer().apply(al);
+ if (context.builder.partParser.canApply(al))
+ getPartParser().apply(al);
} catch (Exception e) {
throw toHttpException(e, InternalServerError.class);
@@ -191,6 +201,44 @@ public class RestOpContextBuilder extends
BeanContextBuilder {
}
/**
+ * Returns the HTTP part parser creator containing the part parser for
parsing HTTP parts into POJOs.
+ *
+ * <p>
+ * The default value is {@link OpenApiParser} which allows for both
plain-text and URL-Encoded-Object-Notation values.
+ * <br>If your parts contain text that can be confused with UON (e.g.
<js>"(foo)"</js>), you can switch to
+ * {@link SimplePartParser} which treats everything as plain text.
+ *
+ * @return The HTTP part parser creator.
+ */
+ public HttpPartParser.Creator getPartParser() {
+ if (partParser == null)
+ partParser = restContext.builder.partParser.copy();
+ return partParser;
+ }
+
+ /**
+ * Returns the HTTP part serializer creator containing the part
serializer for serializing POJOs to HTTP parts.
+ *
+ * <p>
+ * The default value is {@link OpenApiSerializer} which serializes
based on OpenAPI rules, but defaults to UON notation for beans and maps, and
+ * plain text for everything else.
+ *
+ * <p>
+ * <br>Other options include:
+ * <ul>
+ * <li class='jc'>{@link SimplePartSerializer} - Always serializes
to plain text.
+ * <li class='jc'>{@link UonSerializer} - Always serializers to
UON.
+ * </ul>
+ *
+ * @return The HTTP part serializer creator.
+ */
+ public HttpPartSerializer.Creator getPartSerializer() {
+ if (partSerializer == null)
+ partSerializer =
restContext.builder.partSerializer.copy();
+ return partSerializer;
+ }
+
+ /**
* Returns the parser group builder containing the parsers for
converting HTTP request bodies into POJOs.
*
* <p>
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 48c55e1..1a3a7e2 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
@@ -356,7 +356,7 @@ public final class RestRequest {
* <li>
* This object is modifiable.
* <li>
- * Values are converted from strings using the registered
{@link RestContext#REST_partParser part-parser} on the resource class.
+ * Values are converted from strings using the registered
part parser on the resource class.
* <li>
* The {@link RequestHeaders} object can also be passed as
a parameter on the method.
* <li>
@@ -1011,7 +1011,7 @@ public final class RestRequest {
* <li>
* This object is modifiable.
* <li>
- * Values are converted from strings using the registered
{@link RestContext#REST_partParser part-parser} on the resource class.
+ * Values are converted from strings using the registered
part parser on the resource class.
* <li>
* The {@link RequestAttributes} object can also be passed
as a parameter on the method.
* <li>
@@ -1148,7 +1148,7 @@ public final class RestRequest {
* <li>
* This object is modifiable.
* <li>
- * Values are converted from strings using the registered
{@link RestContext#REST_partParser part-parser} on the resource class.
+ * Values are converted from strings using the registered
part parser on the resource class.
* <li>
* The {@link RequestFormParams} object can also be passed
as a parameter on the method.
* <li>
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 63182cf..6f82b12 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
@@ -824,10 +824,6 @@ public @interface Rest {
*
* <p>
* Specifies the {@link HttpPartParser} to use for parsing headers,
query/form parameters, and URI parts.
- *
- * <ul class='seealso'>
- * <li class='jf'>{@link RestContext#REST_partParser}
- * </ul>
*/
Class<? extends HttpPartParser> partParser() default
HttpPartParser.Null.class;
@@ -836,10 +832,6 @@ public @interface Rest {
*
* <p>
* Specifies the {@link HttpPartSerializer} to use for serializing
headers, query/form parameters, and URI parts.
- *
- * <ul class='seealso'>
- * <li class='jf'>{@link RestContext#REST_partSerializer}
- * </ul>
*/
Class<? extends HttpPartSerializer> partSerializer() default
HttpPartSerializer.Null.class;
@@ -1141,7 +1133,7 @@ public @interface Rest {
* }
* </p>
*
- * <ul class='seealso'>Builder
+ * <ul class='seealso'>
* <li class='jm'>{@link
RestOpContextBuilder#rolesDeclared(String...)}
* </ul>
*/
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 6adbaf6..16a97a2 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
@@ -1043,8 +1043,8 @@ public class RestAnnotation {
classes(a.serializers()).ifPresent(x ->
b.getSerializers().add(x));
classes(a.parsers()).ifPresent(x ->
b.getParsers().add(x));
- type(a.partSerializer()).ifPresent(x ->
b.set(REST_partSerializer, x));
- type(a.partParser()).ifPresent(x ->
b.set(REST_partParser, x));
+ type(a.partSerializer()).ifPresent(x ->
b.getPartSerializer().set(x));
+ type(a.partParser()).ifPresent(x ->
b.getPartParser().set(x));
strings(a.produces()).map(MediaType::of).forEach(x ->
b.produces(x));
strings(a.consumes()).map(MediaType::of).forEach(x ->
b.consumes(x));
strings(a.defaultRequestAttributes()).map(x ->
BasicNamedAttribute.ofPair(x)).forEach(x -> b.defaultRequestAttributes(x));
@@ -1101,8 +1101,8 @@ public class RestAnnotation {
public void apply(AnnotationInfo<Rest> ai, RestOpContextBuilder
b) {
Rest a = ai.getAnnotation();
- type(a.partSerializer()).ifPresent(x ->
b.set(REST_partSerializer, x));
- type(a.partParser()).ifPresent(x ->
b.set(REST_partParser, x));
+// type(a.partSerializer()).ifPresent(x ->
b.set(REST_partSerializer, x));
+// type(a.partParser()).ifPresent(x ->
b.set(REST_partParser, x));
strings(a.produces()).map(MediaType::of).forEach(x ->
b.produces(x));
strings(a.consumes()).map(MediaType::of).forEach(x ->
b.consumes(x));
b.converters(a.converters());
diff --git
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/logging/RestLoggerRuleBuilder.java
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/logging/RestLoggerRuleBuilder.java
index 57e752c..d76d515 100644
---
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/logging/RestLoggerRuleBuilder.java
+++
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/logging/RestLoggerRuleBuilder.java
@@ -21,7 +21,7 @@ import org.apache.juneau.*;
import org.apache.juneau.rest.*;
/**
- * Builder for {@link RestLoggerRule} objects.
+ * Creator for {@link RestLoggerRule} objects.
*
* <p>
* See the {@link BasicRestLogger} for usage.