If a @Path is missing the preceding slash it is no longer being implicitly added by jersey.
package io.mattnelson.resources;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
@Path("path")
public class PathResource {
@GET
@Path("child1")
public Object one() {return null; }
@GET
@Path("child2")
public Object two() { return null; }
}
Paths with 1.3.14
INFO [2019-09-10 21:43:14,490] io.dropwizard.jersey.DropwizardResourceConfig: The following paths were found for the configured resources:
GET /path/child1 (io.mattnelson.resources.PathResource)
GET /path/child2 (io.mattnelson.resources.PathResource)
Paths with 2.0.0-rc9
INFO [2019-09-10 21:47:01,015] io.dropwizard.jersey.DropwizardResourceConfig: The following paths were found for the configured resources:
GET /pathchild1 (io.mattnelson.resources.PathResource)
GET /pathchild2 (io.mattnelson.resources.PathResource)
Updating to include slashes results in the same available paths as with 1.3.14.
@Path("path")
public class PathResource {
@GET
@Path("/child1")
public Object one() {return null; }
@GET
@Path("/child2")
public Object two() { return null; }
}
INFO [2019-09-10 21:51:07,313] io.dropwizard.jersey.DropwizardResourceConfig: The following paths were found for the configured resources:
GET /path/child1 (io.mattnelson.resources.PathResource)
GET /path/child2 (io.mattnelson.resources.PathResource)
Possibly related to https://github.com/eclipse-ee4j/jersey/issues/4040 or https://github.com/eclipse-ee4j/jersey/issues/4119
The specification states that slashes are not required.
Paths are relative. For an annotated class the base URI is the application path, see ApplicationPath. For an annotated method the base URI is the effective URI of the containing class. For the purposes of absolutizing a path against the base URI , a leading '/' in a path is ignored and base URIs are treated as if they ended in '/'. E.g.:
@Path("widgets")
public class WidgetsResource {
@GET
String getList() {...}
@GET @Path("{id}")
String getWidget(@PathParam("id") String id) {...}
}
In the above, if the application path is catalogue and the application is deployed at http://example.com/, then GET requests for http://example.com/catalogue/widgets will be handled by the getList method while requests for http://example.com/catalogue/widgets/nnn (where nnn is some value) will be handled by the getWidget method. The same would apply if the value of either @Path annotation started with '/'.
Indeed it's a bit confusing because if we have some code like this below we end up as mentioned :
LOG ( Resources Registered)
INFO [2019-09-15 05:51:42,617] io.dropwizard.jersey.DropwizardResourceConfig: The following paths were found for the configured resources:
GET /hello-world (com.shepherd.dropwizard.resources.HelloWorldResource)
GET /hello-worldchild1 (com.shepherd.dropwizard.resources.HelloWorldResource)
CODE
package com.shepherd.dropwizard.resources;
import com.codahale.metrics.annotation.Timed;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
@Path("/hello-world")
@Produces(MediaType.APPLICATION_JSON)
public class HelloWorldResource {
public HelloWorldResource() {
}
@GET
@Timed
@Path("child1")
public String sayHello() {
return "Hello";
}
@GET
@Timed
public String sayBye() {
return "Bye";
}
}
RESULT
GET /hello-worldchild1 : 404
GET /hello-world/child1 : Hello (200)
GET /hello-world : Bye (200)
@mattnelson Thanks for the clear problem description and reproducible examples!
This issue will be addressed in #2923.