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 2020/03/19 16:40:16 UTC
[juneau] branch master updated: JUNEAU-205
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 cd7c561 JUNEAU-205
cd7c561 is described below
commit cd7c5617fd6af1504ef04675961f9f354ff737c3
Author: JamesBognar <ja...@apache.org>
AuthorDate: Thu Mar 19 12:39:58 2020 -0400
JUNEAU-205
Add @Path(required=boolean) annotation to allow path variables to be
optionally matched.
---
.../juneau/http/annotation/AnnotationUtils.java | 14 +++++++
.../org/apache/juneau/http/annotation/Path.java | 47 ++++++++++++++++++++++
.../juneau/httppart/HttpPartSchemaBuilder.java | 8 ++--
juneau-doc/docs/ReleaseNotes/8.1.4.html | 2 +
.../rest/annotation2/PathAnnotationTest.java | 32 +++++++++++++++
5 files changed, 100 insertions(+), 3 deletions(-)
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/AnnotationUtils.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/AnnotationUtils.java
index 337aa24..e944778 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/AnnotationUtils.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/AnnotationUtils.java
@@ -227,6 +227,7 @@ public class AnnotationUtils {
allEmpty(a.description(), a._enum(), a.example(), a.api())
&& allEmpty(a.name(), a.value(), a.type(), a.format(), a.pattern(), a.maximum(), a.minimum(), a.multipleOf())
&& allFalse(a.exclusiveMaximum(), a.exclusiveMinimum(), a.uniqueItems())
+ && allTrue(a.required())
&& allMinusOne(a.maxLength(), a.minLength(), a.maxItems(), a.minItems())
&& empty(a.items());
}
@@ -272,6 +273,19 @@ public class AnnotationUtils {
}
/**
+ * Returns <jk>true</jk> if all the specified booleans are true.
+ *
+ * @param booleans The booleans to test.
+ * @return <jk>true</jk> if all the specified booleans are true.
+ */
+ protected static boolean allTrue(boolean...booleans) {
+ for (boolean b : booleans)
+ if (! b)
+ return false;
+ return true;
+ }
+
+ /**
* Returns <jk>true</jk> if all the specified longs are -1.
*
* @param longs The booleans to test.
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 2dc8a50..c1ac168 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
@@ -221,6 +221,53 @@ public @interface Path {
*/
String[] description() default {};
+ /**
+ * <mk>required</mk> field of the {@doc SwaggerParameterObject}.
+ *
+ * <p>
+ * Determines whether the parameter is mandatory.
+ *
+ * <p>
+ * If validation fails during serialization or parsing, the part serializer/parser will throw a {@link SchemaValidationException}.
+ * <br>On the client-side, this gets converted to a <c>RestCallException</c> which is thrown before the connection is made.
+ * <br>On the server-side, this gets converted to a <c>BadRequest</c> (400).
+ *
+ * <p>
+ * A path can be marked as not-required when the path variable is resolved by a parent resource like so:
+ *
+ * <p class='bcode w800'>
+ * <ja>@Rest</ja>(path=<js>"/parent/{p1}"</js>,children=Child.<jk>class</jk>)
+ * <jk>public class</jk> Parent {
+ * ...
+ * }
+ *
+ * <ja>@Rest</ja>(path="/child")
+ * <jk>public class</jk> Child {
+ *
+ * <ja>@RestMethod</ja>(path="/")
+ * <jk>public</jk> String doGet(<ja>@Path</ja>(name=<js>"p1"</js>,required=<jk>false</jk>) String p1) {
+ * <jc>// p1 will be null when accessed via "/child"</jc>
+ * <jc>// p1 will be non-null when accessed via "/parent/p1/child".</jc>
+ * }
+ * ...
+ * }
+ * </p>
+ *
+ * <p>
+ * This allows the child resource to be mapped to multiple parents that may resolve various different path variables.
+ *
+ * <h5 class='section'>Used for:</h5>
+ * <ul class='spaced-list'>
+ * <li>
+ * Server-side schema-based parsing validation.
+ * <li>
+ * Server-side generated Swagger documentation.
+ * <li>
+ * Client-side schema-based serializing validation.
+ * </ul>
+ */
+ boolean required() default true;
+
//=================================================================================================================
// Attributes specific to parameters other than body
//=================================================================================================================
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/httppart/HttpPartSchemaBuilder.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/httppart/HttpPartSchemaBuilder.java
index 21c75b4..2c3e95e 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/httppart/HttpPartSchemaBuilder.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/httppart/HttpPartSchemaBuilder.java
@@ -263,10 +263,12 @@ public class HttpPartSchemaBuilder {
serializer(a.serializer());
// Path remainder always allows empty value.
- if (startsWith(name, '/'))
+ if (startsWith(name, '/')) {
allowEmptyValue();
- else
- required(true);
+ required(false);
+ } else {
+ required(a.required());
+ }
return this;
}
diff --git a/juneau-doc/docs/ReleaseNotes/8.1.4.html b/juneau-doc/docs/ReleaseNotes/8.1.4.html
index 07852ec..a80fb9b 100644
--- a/juneau-doc/docs/ReleaseNotes/8.1.4.html
+++ b/juneau-doc/docs/ReleaseNotes/8.1.4.html
@@ -309,6 +309,8 @@
<li class='jc'>{@link oajr.RestGuard}
<li class='jc'>{@link oajr.ResponseHandler}
</ul>
+ <li>
+ New {@link oaj.http.annotation.Path#required() @Path(required)} annotation support.
</ul>
<h5 class='topic w800'>juneau-rest-server-springboot</h5>
diff --git a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation2/PathAnnotationTest.java b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation2/PathAnnotationTest.java
index e5708e6..81ab56d 100644
--- a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation2/PathAnnotationTest.java
+++ b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation2/PathAnnotationTest.java
@@ -1103,4 +1103,36 @@ public class PathAnnotationTest {
ParameterInfo x = tc.getParameterInfo("/example/{P}","get","path","P");
assertEquals("{f1:'b'}", x.getExample());
}
+
+
+ //=================================================================================================================
+ // Basic tests
+ //=================================================================================================================
+
+ @Rest(path="/u1/{u1}",children=U2.class)
+ public static class U1 {
+ }
+ @Rest(path="/u2")
+ public static class U2 {
+ @RestMethod(path="/")
+ public String doGet(@Path(name="u1",required=false) String u1) {
+ return u1 == null ? "nil" : u1;
+ }
+ @RestMethod(path="/foo/{bar}")
+ public String doGetFoo(@Path(name="u1", required=false) String u1, @Path(name="bar",required=false) String bar) {
+ return (u1 == null ? "nil" : u1) + "," + (bar == null ? "nil" : bar);
+ }
+ }
+
+ static MockRest u1 = MockRest.build(U1.class, null);
+ static MockRest u2 = MockRest.build(U2.class, null);
+
+ @Test
+ public void u01_nonRequiredPath() throws Exception {
+ u1.get("/u1/foo/u2").execute().assertStatus(200).assertBody("foo");
+ u1.get("/u1/foo/u2/foo/xxx").execute().assertStatus(200).assertBody("foo,xxx");
+ u2.get("/").execute().assertStatus(200).assertBody("nil");
+ u2.get("/foo/xxx").execute().assertStatus(200).assertBody("nil,xxx");
+ }
+
}
\ No newline at end of file