This is an automated email from the ASF dual-hosted git repository. jamesbognar pushed a commit to branch jbFixRestNpe in repository https://gitbox.apache.org/repos/asf/juneau.git
commit 848c9e20563e75908623c9e01e4d570873943e5c Author: JamesBognar <[email protected]> AuthorDate: Sat Jul 9 10:07:04 2022 -0400 Add @Query(def) annotation. --- .../apache/juneau/http/annotation/FormData.java | 7 ++ .../juneau/http/annotation/FormDataAnnotation.java | 33 ++++++- .../org/apache/juneau/http/annotation/Header.java | 7 ++ .../juneau/http/annotation/HeaderAnnotation.java | 33 ++++++- .../org/apache/juneau/http/annotation/Path.java | 7 ++ .../juneau/http/annotation/PathAnnotation.java | 33 ++++++- .../org/apache/juneau/http/annotation/Query.java | 7 ++ .../juneau/http/annotation/QueryAnnotation.java | 38 +++++-- .../org/apache/juneau/rest/arg/FormDataArg.java | 5 +- .../java/org/apache/juneau/rest/arg/HeaderArg.java | 5 +- .../java/org/apache/juneau/rest/arg/PathArg.java | 5 +- .../java/org/apache/juneau/rest/arg/QueryArg.java | 8 +- .../juneau/rest/httppart/RequestFormParam.java | 13 +++ .../apache/juneau/rest/httppart/RequestHeader.java | 14 ++- .../juneau/rest/httppart/RequestPathParam.java | 14 ++- .../juneau/rest/httppart/RequestQueryParam.java | 14 ++- .../http/annotation/FormDataAnnotation_Test.java | 5 + .../http/annotation/HeaderAnnotation_Test.java | 5 + .../http/annotation/PathAnnotation_Test.java | 5 + .../http/annotation/QueryAnnotation_Test.java | 5 + .../juneau/rest/annotation/FormData_Test.java | 108 ++++++++++++++++++++ .../apache/juneau/rest/annotation/Header_Test.java | 110 +++++++++++++++++++++ .../apache/juneau/rest/annotation/Query_Test.java | 103 +++++++++++++++++++ 23 files changed, 560 insertions(+), 24 deletions(-) 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 38171ac22..ddc248e9c 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 @@ -122,6 +122,13 @@ import org.apache.juneau.oapi.*; @ContextApply(FormDataAnnotation.Applier.class) public @interface FormData { + /** + * Default value for this parameter. + * + * @return The annotation value. + */ + String def() default ""; + /** * FORM parameter name. * diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/FormDataAnnotation.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/FormDataAnnotation.java index 171f5ecc4..90aa0ff37 100644 --- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/FormDataAnnotation.java +++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/FormDataAnnotation.java @@ -96,6 +96,18 @@ public class FormDataAnnotation { return n; } + /** + * Finds the default value from the specified list of annotations. + * + * @param pi The parameter. + * @return The last matching default value, or {@link Value#empty()} if not found. + */ + public static Value<String> findDef(ParamInfo pi) { + Value<String> n = Value.empty(); + pi.forEachAnnotation(FormData.class, x -> isNotEmpty(x.def()), x -> n.set(x.def())); + return n; + } + //----------------------------------------------------------------------------------------------------------------- // Builder //----------------------------------------------------------------------------------------------------------------- @@ -112,7 +124,7 @@ public class FormDataAnnotation { Class<? extends HttpPartParser> parser = HttpPartParser.Void.class; Class<? extends HttpPartSerializer> serializer = HttpPartSerializer.Void.class; Schema schema = SchemaAnnotation.DEFAULT; - String name="", value=""; + String def="", name="", value=""; /** * Constructor. @@ -130,6 +142,17 @@ public class FormDataAnnotation { return new Impl(this); } + /** + * Sets the {@link FormData#def} property on this annotation. + * + * @param value The new value for this property. + * @return This object. + */ + public Builder def(String value) { + this.def = value; + return this; + } + /** * Sets the {@link FormData#name} property on this annotation. * @@ -228,11 +251,12 @@ public class FormDataAnnotation { private final Class<? extends HttpPartParser> parser; private final Class<? extends HttpPartSerializer> serializer; - private final String name, value; + private final String name, value, def; private final Schema schema; Impl(Builder b) { super(b); + this.def = b.def; this.name = b.name; this.parser = b.parser; this.schema = b.schema; @@ -241,6 +265,11 @@ public class FormDataAnnotation { postConstruct(); } + @Override /* FormData */ + public String def() { + return def; + } + @Override /* FormData */ public String name() { return name; 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 5292cc8bb..0057df7d7 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 @@ -88,6 +88,13 @@ import org.apache.juneau.oapi.*; @ContextApply(HeaderAnnotation.Applier.class) public @interface Header { + /** + * Default value for this parameter. + * + * @return The annotation value. + */ + String def() default ""; + /** * HTTP header name. * <p> diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/HeaderAnnotation.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/HeaderAnnotation.java index 8d4154542..1358a0d30 100644 --- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/HeaderAnnotation.java +++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/HeaderAnnotation.java @@ -97,6 +97,18 @@ public class HeaderAnnotation { return n; } + /** + * Finds the default value from the specified list of annotations. + * + * @param pi The parameter. + * @return The last matching default value, or {@link Value#empty()} if not found. + */ + public static Value<String> findDef(ParamInfo pi) { + Value<String> n = Value.empty(); + pi.forEachAnnotation(Header.class, x -> isNotEmpty(x.def()), x -> n.set(x.def())); + return n; + } + //----------------------------------------------------------------------------------------------------------------- // Builder //----------------------------------------------------------------------------------------------------------------- @@ -113,7 +125,7 @@ public class HeaderAnnotation { Class<? extends HttpPartParser> parser = HttpPartParser.Void.class; Class<? extends HttpPartSerializer> serializer = HttpPartSerializer.Void.class; Schema schema = SchemaAnnotation.DEFAULT; - String name="", value=""; + String name="", value="", def=""; /** * Constructor. @@ -131,6 +143,17 @@ public class HeaderAnnotation { return new Impl(this); } + /** + * Sets the {@link Header#def} property on this annotation. + * + * @param value The new value for this property. + * @return This object. + */ + public Builder def(String value) { + this.def = value; + return this; + } + /** * Sets the {@link Header#name} property on this annotation. * @@ -229,11 +252,12 @@ public class HeaderAnnotation { private final Class<? extends HttpPartParser> parser; private final Class<? extends HttpPartSerializer> serializer; - private final String name, value; + private final String name, value, def; private final Schema schema; Impl(Builder b) { super(b); + this.def = b.def; this.name = b.name; this.parser = b.parser; this.schema = b.schema; @@ -242,6 +266,11 @@ public class HeaderAnnotation { postConstruct(); } + @Override /* Header */ + public String def() { + return def; + } + @Override /* Header */ public String name() { return name; 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 d78dd307f..e87eed997 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 @@ -85,6 +85,13 @@ import org.apache.juneau.oapi.*; @ContextApply(PathAnnotation.Applier.class) public @interface Path { + /** + * Default value for this parameter. + * + * @return The annotation value. + */ + String def() default ""; + /** * URL path variable name. * diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/PathAnnotation.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/PathAnnotation.java index 32c92609d..44d06f760 100644 --- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/PathAnnotation.java +++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/PathAnnotation.java @@ -96,6 +96,18 @@ public class PathAnnotation { return n; } + /** + * Finds the default value from the specified list of annotations. + * + * @param pi The parameter. + * @return The last matching default value, or {@link Value#empty()} if not found. + */ + public static Value<String> findDef(ParamInfo pi) { + Value<String> n = Value.empty(); + pi.forEachAnnotation(Path.class, x -> isNotEmpty(x.def()), x -> n.set(x.def())); + return n; + } + //----------------------------------------------------------------------------------------------------------------- // Builder //----------------------------------------------------------------------------------------------------------------- @@ -112,7 +124,7 @@ public class PathAnnotation { Class<? extends HttpPartParser> parser = HttpPartParser.Void.class; Class<? extends HttpPartSerializer> serializer = HttpPartSerializer.Void.class; Schema schema = SchemaAnnotation.DEFAULT; - String name="", value=""; + String name="", value="", def=""; /** * Constructor. @@ -141,6 +153,17 @@ public class PathAnnotation { return this; } + /** + * Sets the {@link Path#name} property on this annotation. + * + * @param value The new value for this property. + * @return This object. + */ + public Builder def(String value) { + this.def = value; + return this; + } + /** * Sets the {@link Path#parser} property on this annotation. * @@ -228,11 +251,12 @@ public class PathAnnotation { private final Class<? extends HttpPartParser> parser; private final Class<? extends HttpPartSerializer> serializer; - private final String name, value; + private final String name, value, def; private final Schema schema; Impl(Builder b) { super(b); + this.def = b.def; this.name = b.name; this.parser = b.parser; this.schema = b.schema; @@ -246,6 +270,11 @@ public class PathAnnotation { return name; } + @Override /* Path */ + public String def() { + return def; + } + @Override /* Path */ public Class<? extends HttpPartParser> parser() { return parser; 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 01bf7fa41..05f1f4dd2 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 @@ -96,6 +96,13 @@ import org.apache.juneau.oapi.*; @ContextApply(QueryAnnotation.Applier.class) public @interface Query { + /** + * Default value for this parameter. + * + * @return The annotation value. + */ + String def() default ""; + /** * URL query parameter name. * diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/QueryAnnotation.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/QueryAnnotation.java index f9fa1d108..3959b1972 100644 --- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/QueryAnnotation.java +++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/QueryAnnotation.java @@ -81,10 +81,7 @@ public class QueryAnnotation { } /** - * Finds the name from the specified lists of annotations. - * - * <p> - * The last matching name found is returned. + * Finds the name from the specified list of annotations. * * @param pi The parameter. * @return The last matching name, or {@link Value#empty()} if not found. @@ -96,6 +93,18 @@ public class QueryAnnotation { return n; } + /** + * Finds the default value from the specified list of annotations. + * + * @param pi The parameter. + * @return The last matching default value, or {@link Value#empty()} if not found. + */ + public static Value<String> findDef(ParamInfo pi) { + Value<String> n = Value.empty(); + pi.forEachAnnotation(Query.class, x -> isNotEmpty(x.def()), x -> n.set(x.def())); + return n; + } + //----------------------------------------------------------------------------------------------------------------- // Builder //----------------------------------------------------------------------------------------------------------------- @@ -112,7 +121,7 @@ public class QueryAnnotation { Class<? extends HttpPartParser> parser = HttpPartParser.Void.class; Class<? extends HttpPartSerializer> serializer = HttpPartSerializer.Void.class; Schema schema = SchemaAnnotation.DEFAULT; - String name="", value=""; + String name="", value="", def=""; /** * Constructor. @@ -130,6 +139,17 @@ public class QueryAnnotation { return new Impl(this); } + /** + * Sets the {@link Query#def} property on this annotation. + * + * @param value The new value for this property. + * @return This object. + */ + public Builder def(String value) { + this.def = value; + return this; + } + /** * Sets the {@link Query#name} property on this annotation. * @@ -228,7 +248,7 @@ public class QueryAnnotation { private final Class<? extends HttpPartParser> parser; private final Class<? extends HttpPartSerializer> serializer; - private final String name, value; + private final String name, value, def; private final Schema schema; Impl(Builder b) { @@ -238,6 +258,7 @@ public class QueryAnnotation { this.schema = b.schema; this.serializer = b.serializer; this.value = b.value; + this.def = b.def; postConstruct(); } @@ -265,6 +286,11 @@ public class QueryAnnotation { public String value() { return value; } + + @Override /* Query */ + public String def() { + return def; + } } //----------------------------------------------------------------------------------------------------------------- diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/arg/FormDataArg.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/arg/FormDataArg.java index 20b8f3bd8..29c1655c1 100644 --- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/arg/FormDataArg.java +++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/arg/FormDataArg.java @@ -57,7 +57,7 @@ public class FormDataArg implements RestOpArg { private final boolean multi; private final HttpPartParser partParser; private final HttpPartSchema schema; - private final String name; + private final String name, def; private final ClassInfo type; /** @@ -81,6 +81,7 @@ public class FormDataArg implements RestOpArg { */ protected FormDataArg(ParamInfo pi, AnnotationWorkList annotations) { this.name = findName(pi).orElseThrow(()->new ArgException(pi, "@FormData used without name or value")); + this.def = findDef(pi).orElse(null); this.type = pi.getParameterType(); this.schema = HttpPartSchema.create(FormData.class, pi); Class<? extends HttpPartParser> pp = schema.getParser(); @@ -113,6 +114,6 @@ public class FormDataArg implements RestOpArg { return req.getBeanSession().convertToType(m, cm); } - return rh.getLast(name).parser(ps).schema(schema).as(type.innerType()).orElse(null); + return rh.getLast(name).parser(ps).schema(schema).def(def).as(type.innerType()).orElse(null); } } diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/arg/HeaderArg.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/arg/HeaderArg.java index e7d0ad0d1..4a1f211ad 100644 --- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/arg/HeaderArg.java +++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/arg/HeaderArg.java @@ -98,7 +98,7 @@ public class HeaderArg implements RestOpArg { private final HttpPartParser partParser; private final HttpPartSchema schema; private final boolean multi; - private final String name; + private final String name, def; private final ClassInfo type; /** @@ -122,6 +122,7 @@ public class HeaderArg implements RestOpArg { */ protected HeaderArg(ParamInfo pi, AnnotationWorkList annotations) { this.name = findName(pi).orElseThrow(() -> new ArgException(pi, "@Header used without name or value")); + this.def = findDef(pi).orElse(null); this.type = pi.getParameterType(); this.schema = HttpPartSchema.create(Header.class, pi); Class<? extends HttpPartParser> pp = schema.getParser(); @@ -154,6 +155,6 @@ public class HeaderArg implements RestOpArg { return req.getBeanSession().convertToType(m, cm); } - return rh.getLast(name).parser(ps).schema(schema).as(type.innerType()).orElse(null); + return rh.getLast(name).parser(ps).schema(schema).def(def).as(type.innerType()).orElse(null); } } diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/arg/PathArg.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/arg/PathArg.java index 3433e9ebd..69b80d384 100644 --- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/arg/PathArg.java +++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/arg/PathArg.java @@ -50,7 +50,7 @@ import org.apache.juneau.rest.util.*; public class PathArg implements RestOpArg { private final HttpPartParser partParser; private final HttpPartSchema schema; - private final String name; + private final String name, def; private final Type type; /** @@ -76,6 +76,7 @@ public class PathArg implements RestOpArg { */ protected PathArg(ParamInfo paramInfo, AnnotationWorkList annotations, UrlPathMatcher pathMatcher) { this.name = getName(paramInfo, pathMatcher); + this.def = findDef(paramInfo).orElse(null); this.type = paramInfo.getParameterType().innerType(); this.schema = HttpPartSchema.create(Path.class, paramInfo); Class<? extends HttpPartParser> pp = schema.getParser(); @@ -119,6 +120,6 @@ public class PathArg implements RestOpArg { return req.getBeanSession().convertToType(m, type); } HttpPartParserSession ps = partParser == null ? req.getPartParserSession() : partParser.getPartSession(); - return req.getPathParams().get(name).parser(ps).schema(schema).as(type).orElse(null); + return req.getPathParams().get(name).parser(ps).schema(schema).def(def).as(type).orElse(null); } } diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/arg/QueryArg.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/arg/QueryArg.java index a8938ed2c..2e143726f 100644 --- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/arg/QueryArg.java +++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/arg/QueryArg.java @@ -14,6 +14,7 @@ package org.apache.juneau.rest.arg; import static org.apache.juneau.internal.CollectionUtils.*; import static org.apache.juneau.internal.StringUtils.*; +import static org.apache.juneau.http.annotation.QueryAnnotation.*; import java.util.*; @@ -56,7 +57,7 @@ public class QueryArg implements RestOpArg { private final boolean multi; private final HttpPartParser partParser; private final HttpPartSchema schema; - private final String name; + private final String name, def; private final ClassInfo type; /** @@ -79,7 +80,8 @@ public class QueryArg implements RestOpArg { * @param annotations The annotations to apply to any new part parsers. */ protected QueryArg(ParamInfo pi, AnnotationWorkList annotations) { - this.name = QueryAnnotation.findName(pi).orElseThrow(() -> new ArgException(pi, "@Query used without name or value")); + this.name = findName(pi).orElseThrow(() -> new ArgException(pi, "@Query used without name or value")); + this.def = findDef(pi).orElse(null); this.type = pi.getParameterType(); this.schema = HttpPartSchema.create(Query.class, pi); Class<? extends HttpPartParser> pp = schema.getParser(); @@ -112,6 +114,6 @@ public class QueryArg implements RestOpArg { return req.getBeanSession().convertToType(m, cm); } - return rh.getLast(name).parser(ps).schema(schema).as(type.innerType()).orElse(null); + return rh.getLast(name).parser(ps).schema(schema).def(def).as(type.innerType()).orElse(null); } } diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/httppart/RequestFormParam.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/httppart/RequestFormParam.java index 1e8b914ee..b790a71dc 100644 --- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/httppart/RequestFormParam.java +++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/httppart/RequestFormParam.java @@ -135,6 +135,19 @@ public class RequestFormParam extends RequestHttpPart implements NameValuePair { return value; } + + /** + * Sets a default value for this part. + * + * @param def The default value. + * @return This object. + */ + public RequestFormParam def(String def) { + if (getValue() == null) + value = def; + return this; + } + //------------------------------------------------------------------------------------------------------------------ // Assertions //------------------------------------------------------------------------------------------------------------------ diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/httppart/RequestHeader.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/httppart/RequestHeader.java index 45459778e..ad147958c 100644 --- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/httppart/RequestHeader.java +++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/httppart/RequestHeader.java @@ -95,7 +95,7 @@ import org.apache.juneau.rest.*; */ public class RequestHeader extends RequestHttpPart implements Header { - private final String value; + private String value; /** * Constructor. @@ -109,6 +109,18 @@ public class RequestHeader extends RequestHttpPart implements Header { this.value = value; } + /** + * Sets a default value for this part. + * + * @param def The default value. + * @return This object. + */ + public RequestHeader def(String def) { + if (value == null) + value = def; + return this; + } + //------------------------------------------------------------------------------------------------------------------ // Retrievers //------------------------------------------------------------------------------------------------------------------ diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/httppart/RequestPathParam.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/httppart/RequestPathParam.java index 838e390a2..74289917c 100644 --- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/httppart/RequestPathParam.java +++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/httppart/RequestPathParam.java @@ -90,7 +90,7 @@ import org.apache.juneau.rest.*; */ public class RequestPathParam extends RequestHttpPart implements NameValuePair { - private final String value; + private String value; /** * Constructor. @@ -104,6 +104,18 @@ public class RequestPathParam extends RequestHttpPart implements NameValuePair { this.value = value; } + /** + * Sets a default value for this part. + * + * @param def The default value. + * @return This object. + */ + public RequestPathParam def(String def) { + if (value == null) + value = def; + return this; + } + //------------------------------------------------------------------------------------------------------------------ // Retrievers //------------------------------------------------------------------------------------------------------------------ diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/httppart/RequestQueryParam.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/httppart/RequestQueryParam.java index b094192d1..5c1b8e09c 100644 --- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/httppart/RequestQueryParam.java +++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/httppart/RequestQueryParam.java @@ -90,7 +90,7 @@ import org.apache.juneau.rest.*; */ public class RequestQueryParam extends RequestHttpPart implements NameValuePair { - private final String value; + private String value; /** * Constructor. @@ -104,6 +104,18 @@ public class RequestQueryParam extends RequestHttpPart implements NameValuePair this.value = value; } + /** + * Sets a default value for this part. + * + * @param def The default value. + * @return This object. + */ + public RequestQueryParam def(String def) { + if (value == null) + value = def; + return this; + } + //------------------------------------------------------------------------------------------------------------------ // Retrievers //------------------------------------------------------------------------------------------------------------------ diff --git a/juneau-utest/src/test/java/org/apache/juneau/http/annotation/FormDataAnnotation_Test.java b/juneau-utest/src/test/java/org/apache/juneau/http/annotation/FormDataAnnotation_Test.java index 8919f36e8..78c9ab788 100644 --- a/juneau-utest/src/test/java/org/apache/juneau/http/annotation/FormDataAnnotation_Test.java +++ b/juneau-utest/src/test/java/org/apache/juneau/http/annotation/FormDataAnnotation_Test.java @@ -32,6 +32,7 @@ public class FormDataAnnotation_Test { //------------------------------------------------------------------------------------------------------------------ FormData a1 = FormDataAnnotation.create() + .def("def") .name("name") .on("on") .onClass(X1.class) @@ -41,6 +42,7 @@ public class FormDataAnnotation_Test { .build(); FormData a2 = FormDataAnnotation.create() + .def("def") .name("name") .on("on") .onClass(X1.class) @@ -53,6 +55,7 @@ public class FormDataAnnotation_Test { public void a01_basic() { assertObject(a1).asJson().isMatches("" + "{" + + "def:'def'," + "name:'name'," + "on:['on']," + "onClass:['org.apache.juneau.http.annotation.FormDataAnnotation_Test$X1']," @@ -112,6 +115,7 @@ public class FormDataAnnotation_Test { //------------------------------------------------------------------------------------------------------------------ @FormData( + def="def", name="name", on="on", onClass=X1.class, @@ -123,6 +127,7 @@ public class FormDataAnnotation_Test { FormData d1 = D1.class.getAnnotationsByType(FormData.class)[0]; @FormData( + def="def", name="name", on="on", onClass=X1.class, diff --git a/juneau-utest/src/test/java/org/apache/juneau/http/annotation/HeaderAnnotation_Test.java b/juneau-utest/src/test/java/org/apache/juneau/http/annotation/HeaderAnnotation_Test.java index 09c779f21..371c436c0 100644 --- a/juneau-utest/src/test/java/org/apache/juneau/http/annotation/HeaderAnnotation_Test.java +++ b/juneau-utest/src/test/java/org/apache/juneau/http/annotation/HeaderAnnotation_Test.java @@ -32,6 +32,7 @@ public class HeaderAnnotation_Test { //------------------------------------------------------------------------------------------------------------------ Header a1 = HeaderAnnotation.create() + .def("def") .name("name") .on("on") .onClass(X1.class) @@ -41,6 +42,7 @@ public class HeaderAnnotation_Test { .build(); Header a2 = HeaderAnnotation.create() + .def("def") .name("name") .on("on") .onClass(X1.class) @@ -53,6 +55,7 @@ public class HeaderAnnotation_Test { public void a01_basic() { assertObject(a1).asJson().isMatches("" + "{" + + "def:'def'," + "name:'name'," + "on:['on']," + "onClass:['"+CNAME+"$X1']," @@ -112,6 +115,7 @@ public class HeaderAnnotation_Test { //------------------------------------------------------------------------------------------------------------------ @Header( + def="def", name="name", on="on", onClass=X1.class, @@ -123,6 +127,7 @@ public class HeaderAnnotation_Test { Header d1 = D1.class.getAnnotationsByType(Header.class)[0]; @Header( + def="def", name="name", on="on", onClass=X1.class, diff --git a/juneau-utest/src/test/java/org/apache/juneau/http/annotation/PathAnnotation_Test.java b/juneau-utest/src/test/java/org/apache/juneau/http/annotation/PathAnnotation_Test.java index 0f1506f38..797475461 100644 --- a/juneau-utest/src/test/java/org/apache/juneau/http/annotation/PathAnnotation_Test.java +++ b/juneau-utest/src/test/java/org/apache/juneau/http/annotation/PathAnnotation_Test.java @@ -32,6 +32,7 @@ public class PathAnnotation_Test { //------------------------------------------------------------------------------------------------------------------ Path a1 = PathAnnotation.create() + .def("def") .name("name") .on("on") .onClass(X1.class) @@ -41,6 +42,7 @@ public class PathAnnotation_Test { .build(); Path a2 = PathAnnotation.create() + .def("def") .name("name") .on("on") .onClass(X1.class) @@ -53,6 +55,7 @@ public class PathAnnotation_Test { public void a01_basic() { assertObject(a1).asJson().isMatches("" + "{" + + "def:'def'," + "name:'name'," + "on:['on']," + "onClass:['"+CNAME+"$X1']," @@ -112,6 +115,7 @@ public class PathAnnotation_Test { //------------------------------------------------------------------------------------------------------------------ @Path( + def="def", name="name", on="on", onClass=X1.class, @@ -123,6 +127,7 @@ public class PathAnnotation_Test { Path d1 = D1.class.getAnnotationsByType(Path.class)[0]; @Path( + def="def", name="name", on="on", onClass=X1.class, diff --git a/juneau-utest/src/test/java/org/apache/juneau/http/annotation/QueryAnnotation_Test.java b/juneau-utest/src/test/java/org/apache/juneau/http/annotation/QueryAnnotation_Test.java index 40afced92..7256e7cb4 100644 --- a/juneau-utest/src/test/java/org/apache/juneau/http/annotation/QueryAnnotation_Test.java +++ b/juneau-utest/src/test/java/org/apache/juneau/http/annotation/QueryAnnotation_Test.java @@ -32,6 +32,7 @@ public class QueryAnnotation_Test { //------------------------------------------------------------------------------------------------------------------ Query a1 = QueryAnnotation.create() + .def("def") .name("name") .on("on") .onClass(X1.class) @@ -41,6 +42,7 @@ public class QueryAnnotation_Test { .build(); Query a2 = QueryAnnotation.create() + .def("def") .name("name") .on("on") .onClass(X1.class) @@ -53,6 +55,7 @@ public class QueryAnnotation_Test { public void a01_basic() { assertObject(a1).asJson().isMatches("" + "{" + + "def:'def'," + "name:'name'," + "on:['on']," + "onClass:['"+CNAME+"$X1']," @@ -112,6 +115,7 @@ public class QueryAnnotation_Test { //------------------------------------------------------------------------------------------------------------------ @Query( + def="def", name="name", on="on", onClass=X1.class, @@ -123,6 +127,7 @@ public class QueryAnnotation_Test { Query d1 = D1.class.getAnnotationsByType(Query.class)[0]; @Query( + def="def", name="name", on="on", onClass=X1.class, diff --git a/juneau-utest/src/test/java/org/apache/juneau/rest/annotation/FormData_Test.java b/juneau-utest/src/test/java/org/apache/juneau/rest/annotation/FormData_Test.java index 80f614739..d5a572046 100644 --- a/juneau-utest/src/test/java/org/apache/juneau/rest/annotation/FormData_Test.java +++ b/juneau-utest/src/test/java/org/apache/juneau/rest/annotation/FormData_Test.java @@ -211,4 +211,112 @@ public class FormData_Test { .assertCode().is(200) .assertContent().is("null"); } + + //------------------------------------------------------------------------------------------------------------------ + // Default form data parameter. + //------------------------------------------------------------------------------------------------------------------ + + @Rest(serializers=SimpleJsonSerializer.class) + public static class F { + @RestPost + public Object a1(@FormData(name="f1",def="1") Integer f1) throws Exception { + assertNotNull(f1); + return f1; + } + @RestPost + public Object a2(@FormData(name="f1",def="1") Optional<Integer> f1) throws Exception { + assertNotNull(f1); + return f1; + } + @RestPost + public Object b1(@FormData(name="f1",def="a=2,b=bar") ABean f1) throws Exception { + assertNotNull(f1); + return f1; + } + @RestPost + public Object b2(@FormData(name="f1",def="a=2,b=bar") Optional<ABean> f1) throws Exception { + assertNotNull(f1); + return f1; + } + @RestPost + public Object c1(@FormData(name="f1",def="@((a=2,b=bar))") List<ABean> f1) throws Exception { + assertNotNull(f1); + return f1; + } + @RestPost + public Object c2(@FormData(name="f1",def="@((a=2,b=bar))") Optional<List<ABean>> f1) throws Exception { + assertNotNull(f1); + return f1; + } + @RestPost + public Object d(@FormData(name="f1",def="@((a=2,b=bar))") List<Optional<ABean>> f1) throws Exception { + return f1; + } + } + + @Test + public void f01_defaultParams() throws Exception { + RestClient f = MockRestClient.create(F.class).accept("application/json").contentType("application/x-www-form-urlencoded").build(); + + f.post("/a1", "f1=123") + .run() + .assertCode().is(200) + .assertContent().is("123"); + f.post("/a1", "") + .run() + .assertCode().is(200) + .assertContent().is("1"); + f.post("/a2", "f1=123") + .run() + .assertCode().is(200) + .assertContent().is("123"); + f.post("/a2", "") + .run() + .assertCode().is(200) + .assertContent().is("1"); + + f.post("/b1", "f1=a=1,b=foo") + .run() + .assertCode().is(200) + .assertContent().is("{a:1,b:'foo'}"); + f.post("/b1", "") + .run() + .assertCode().is(200) + .assertContent().is("{a:2,b:'bar'}"); + f.post("/b2", "f1=a=1,b=foo") + .run() + .assertCode().is(200) + .assertContent().is("{a:1,b:'foo'}"); + f.post("/b2", "") + .run() + .assertCode().is(200) + .assertContent().is("{a:2,b:'bar'}"); + + f.post("/c1", "f1=@((a=1,b=foo))") + .run() + .assertCode().is(200) + .assertContent().is("[{a:1,b:'foo'}]"); + f.post("/c1", "null") + .run() + .assertCode().is(200) + .assertContent().is("[{a:2,b:'bar'}]"); + f.post("/c2", "f1=@((a=1,b=foo))") + .run() + .assertCode().is(200) + .assertContent().is("[{a:1,b:'foo'}]"); + f.post("/c2", "null") + .run() + .assertCode().is(200) + .assertContent().is("[{a:2,b:'bar'}]"); + + + f.post("/d", "f1=@((a=1,b=foo))") + .run() + .assertCode().is(200) + .assertContent().is("[{a:1,b:'foo'}]"); + f.post("/d", "null") + .run() + .assertCode().is(200) + .assertContent().is("[{a:2,b:'bar'}]"); + } } diff --git a/juneau-utest/src/test/java/org/apache/juneau/rest/annotation/Header_Test.java b/juneau-utest/src/test/java/org/apache/juneau/rest/annotation/Header_Test.java index 9d589f3bb..082f789e6 100644 --- a/juneau-utest/src/test/java/org/apache/juneau/rest/annotation/Header_Test.java +++ b/juneau-utest/src/test/java/org/apache/juneau/rest/annotation/Header_Test.java @@ -210,4 +210,114 @@ public class Header_Test { e.get("/a").header("H1",7).header("H2",8).header("H3",9).run().assertContent().is("{h1:'7',h2:'8',h3:'9'}"); e.get("/a").header("h1",7).header("h2",8).header("h3",9).run().assertContent().is("{h1:'7',h2:'8',h3:'9'}"); } + + //------------------------------------------------------------------------------------------------------------------ + // Default parameters + //------------------------------------------------------------------------------------------------------------------ + + @Rest(serializers=SimpleJsonSerializer.class) + public static class F { + @RestGet + public Object a1(@Header(name="f1", def="1") Integer f1) throws Exception { + assertNotNull(f1); + return f1; + } + @RestGet + public Object a2(@Header(name="f1", def="1") Optional<Integer> f1) throws Exception { + assertNotNull(f1); + return f1.get(); + } + @RestGet + public Object b1(@Header(name="f1", def="a=1,b=foo") ABean f1) throws Exception { + assertNotNull(f1); + return f1; + } + @RestGet + public Object b2(@Header(name="f1", def="a=1,b=foo") Optional<ABean> f1) throws Exception { + assertNotNull(f1); + return f1.get(); + } + @RestGet + public Object c1(@Header(name="f1", def="@((a=1,b=foo))") List<ABean> f1) throws Exception { + assertNotNull(f1); + return f1; + } + @RestGet + public Object c2(@Header(name="f1", def="@((a=1,b=foo))") Optional<List<ABean>> f1) throws Exception { + assertNotNull(f1); + return f1.get(); + } + @RestGet + public Object d(@Header(name="f1", def="@((a=1,b=foo))") List<Optional<ABean>> f1) throws Exception { + return f1; + } + } + + @Test + public void f01_defaultHeaders() throws Exception { + RestClient f = MockRestClient.buildJson(F.class); + f.get("/a1") + .header("f1","123") + .run() + .assertCode().is(200) + .assertContent().is("123"); + f.get("/a1") + .run() + .assertCode().is(200) + .assertContent().is("1"); + f.get("/a2") + .header("f1","123") + .run() + .assertCode().is(200) + .assertContent().is("123"); + f.get("/a2") + .run() + .assertCode().is(200) + .assertContent().is("1"); + f.get("/b1") + .header("f1","a=2,b=bar") + .run() + .assertCode().is(200) + .assertContent().is("{a:2,b:'bar'}"); + f.get("/b1") + .run() + .assertCode().is(200) + .assertContent().is("{a:1,b:'foo'}"); + f.get("/b2") + .header("f1","a=2,b=bar") + .run() + .assertCode().is(200) + .assertContent().is("{a:2,b:'bar'}"); + f.get("/b2") + .run() + .assertCode().is(200) + .assertContent().is("{a:1,b:'foo'}"); + f.get("/c1") + .header("f1","@((a=2,b=bar))") + .run() + .assertCode().is(200) + .assertContent().is("[{a:2,b:'bar'}]"); + f.get("/c1") + .run() + .assertCode().is(200) + .assertContent().is("[{a:1,b:'foo'}]"); + f.get("/c2") + .header("f1","@((a=2,b=bar))") + .run() + .assertCode().is(200) + .assertContent().is("[{a:2,b:'bar'}]"); + f.get("/c2") + .run() + .assertCode().is(200) + .assertContent().is("[{a:1,b:'foo'}]"); + f.get("/d") + .header("f1","@((a=2,b=bar))") + .run() + .assertCode().is(200) + .assertContent().is("[{a:2,b:'bar'}]"); + f.get("/d") + .run() + .assertCode().is(200) + .assertContent().is("[{a:1,b:'foo'}]"); + } } diff --git a/juneau-utest/src/test/java/org/apache/juneau/rest/annotation/Query_Test.java b/juneau-utest/src/test/java/org/apache/juneau/rest/annotation/Query_Test.java index 82b5b9df6..170332cc2 100644 --- a/juneau-utest/src/test/java/org/apache/juneau/rest/annotation/Query_Test.java +++ b/juneau-utest/src/test/java/org/apache/juneau/rest/annotation/Query_Test.java @@ -288,4 +288,107 @@ public class Query_Test { .assertCode().is(200) .assertContent().is("null"); } + + //------------------------------------------------------------------------------------------------------------------ + // Default parameters + //------------------------------------------------------------------------------------------------------------------ + + @Rest(serializers=SimpleJsonSerializer.class) + public static class F { + @RestGet + public Object a1(@Query(name="f1", def="1") Integer f1) throws Exception { + assertNotNull(f1); + return f1; + } + @RestGet + public Object a2(@Query(name="f1", def="1") Optional<Integer> f1) throws Exception { + assertNotNull(f1); + return f1.get(); + } + @RestGet + public Object b1(@Query(name="f1", def="a=1,b=foo") ABean f1) throws Exception { + assertNotNull(f1); + return f1; + } + @RestGet + public Object b2(@Query(name="f1", def="a=1,b=foo") Optional<ABean> f1) throws Exception { + assertNotNull(f1); + return f1.get(); + } + @RestGet + public Object c1(@Query(name="f1", def="@((a=1,b=foo))") List<ABean> f1) throws Exception { + assertNotNull(f1); + return f1; + } + @RestGet + public Object c2(@Query(name="f1", def="@((a=1,b=foo))") Optional<List<ABean>> f1) throws Exception { + assertNotNull(f1); + return f1.get(); + } + @RestGet + public Object d(@Query(name="f1", def="@((a=1,b=foo))") List<Optional<ABean>> f1) throws Exception { + return f1; + } + } + + @Test + public void f01_defaultParams() throws Exception { + RestClient f = MockRestClient.buildJson(F.class); + f.get("/a1?f1=123") + .run() + .assertCode().is(200) + .assertContent().is("123"); + f.get("/a1") + .run() + .assertCode().is(200) + .assertContent().is("1"); + f.get("/a2?f1=123") + .run() + .assertCode().is(200) + .assertContent().is("123"); + f.get("/a2") + .run() + .assertCode().is(200) + .assertContent().is("1"); + f.get("/b1?f1=a=2,b=bar") + .run() + .assertCode().is(200) + .assertContent().is("{a:2,b:'bar'}"); + f.get("/b1") + .run() + .assertCode().is(200) + .assertContent().is("{a:1,b:'foo'}"); + f.get("/b2?f1=a=2,b=bar") + .run() + .assertCode().is(200) + .assertContent().is("{a:2,b:'bar'}"); + f.get("/b2") + .run() + .assertCode().is(200) + .assertContent().is("{a:1,b:'foo'}"); + f.get("/c1?f1=@((a=2,b=bar))") + .run() + .assertCode().is(200) + .assertContent().is("[{a:2,b:'bar'}]"); + f.get("/c1") + .run() + .assertCode().is(200) + .assertContent().is("[{a:1,b:'foo'}]"); + f.get("/c2?f1=@((a=2,b=bar))") + .run() + .assertCode().is(200) + .assertContent().is("[{a:2,b:'bar'}]"); + f.get("/c2") + .run() + .assertCode().is(200) + .assertContent().is("[{a:1,b:'foo'}]"); + f.get("/d?f1=@((a=2,b=bar))") + .run() + .assertCode().is(200) + .assertContent().is("[{a:2,b:'bar'}]"); + f.get("/d") + .run() + .assertCode().is(200) + .assertContent().is("[{a:1,b:'foo'}]"); + } }
