JUNEAU-177 Allow REST methods at specific paths to be overridden by
methods in child classes.
diff --git a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/RestMethodPathTest.java b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/RestMethodPathTest.java
index f944245..4a89ea5 100644
--- a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/RestMethodPathTest.java
+++ b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/RestMethodPathTest.java
@@ -84,4 +84,30 @@
a.get("/x/foo").execute().assertBody("g");
a.get("/x/foo/x").execute().assertBody("h");
}
+
+ //=================================================================================================================
+ // Overridden URL patterns
+ //=================================================================================================================
+
+ @Rest
+ public static class B1 {
+ @RestMethod(name=GET, path="/foo")
+ public String b01a() {
+ return "a";
+ }
+ }
+
+ @Rest
+ public static class B2 extends B1 {
+ @RestMethod(name=GET, path="/foo")
+ public String b02a() { // Overrides method on parent.
+ return "b";
+ }
+ }
+ static MockRest b2 = MockRest.build(B2.class, null);
+
+ @Test
+ public void b01_pathOverriddenByChild() throws Exception {
+ b2.get("/foo").execute().assertBody("b");
+ }
}
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestCallRouter.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestCallRouter.java
index 6aa2fe3..45ef6c4 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestCallRouter.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestCallRouter.java
@@ -40,7 +40,6 @@
*/
static final class Builder {
private List<RestMethodContext> childMethods = new ArrayList<>();
- private Set<String> collisions = new HashSet<>();
private String httpMethodName;
Builder(String httpMethodName) {
@@ -51,13 +50,7 @@
return httpMethodName;
}
- Builder add(RestMethodContext m) throws RestServletException {
- if (! m.hasGuardsOrMatchers()) {
- String p = m.getHttpMethod() + ":" + m.getPathPattern();
- if (collisions.contains(p))
- throw new RestServletException("Duplicate Java methods assigned to the same method/pattern: ''{0}''", p);
- collisions.add(p);
- }
+ Builder add(RestMethodContext m) {
childMethods.add(m);
return this;
}
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 cbf42b1..3984786 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
@@ -3936,7 +3936,7 @@
}
}
- private static void addToRouter(Map<String, RestCallRouter.Builder> routers, String httpMethodName, RestMethodContext cm) throws RestServletException {
+ private static void addToRouter(Map<String, RestCallRouter.Builder> routers, String httpMethodName, RestMethodContext cm) {
if (! routers.containsKey(httpMethodName))
routers.put(httpMethodName, new RestCallRouter.Builder(httpMethodName));
routers.get(httpMethodName).add(cm);
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestMethodContext.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestMethodContext.java
index fc20866..e0144a1 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestMethodContext.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestMethodContext.java
@@ -580,6 +580,7 @@
final ResponseBeanMeta responseMeta;
final Enablement debug;
+ final int hierarchyDepth;
@SuppressWarnings("deprecation")
RestMethodContext(RestMethodContextBuilder b) throws ServletException {
@@ -593,6 +594,14 @@
// Need this to access methods in anonymous inner classes.
mi.setAccessible();
+ int hd = 0;
+ Class<?> sc = b.method.getDeclaringClass().getSuperclass();
+ while (sc != null) {
+ hd++;
+ sc = sc.getSuperclass();
+ }
+ hierarchyDepth = hd;
+
PropertyStore ps = getPropertyStore();
ResourceResolver rr = context.getResourceResolver();
Object r = context.getResource();
@@ -960,6 +969,10 @@
if (c != 0)
return c;
+ c = compare(o.hierarchyDepth, hierarchyDepth);
+ if (c != 0)
+ return c;
+
c = compare(o.requiredMatchers.length, requiredMatchers.length);
if (c != 0)
return c;
@@ -972,6 +985,10 @@
if (c != 0)
return c;
+ c = compare(method.getName(), o.method.getName());
+ if (c != 0)
+ return c;
+
return 0;
}