We are building a RESTful JAXRS web service for use with a Jersey HTTP client. We'd like to make heavy use of subresource locators to prevent cluttering code in single large source files. E.g. (minimal example):
@Path("places")
public class PlacesResource {
// Use the following to e.g. GET /places/123
@GET @Path("{id}")
@Produces("application/json")
public Response getPlace(@PathParam("id") int id) {
//...
return Response.ok(null).build();
}
// Use the following to e.g. GET /places/123/comments/42
@Path("{id}")
public PlaceResource place(@PathParam("id") int id) {
Place p = DAO.getInstance().getPlace(id);
return new PlaceResource(p); // singular (a different resource class)
}
}
This works fine. Removing either of these methods makes calls to resources as specified in the leading comments not work. (HTTP response 405: method not allowed)
However, while using this setup the following warning is printed to the Tomcat log:
[http-nio-8084-exec-6] org.glassfish.jersey.internal.Errors.logErrors The following warnings have been detected: WARNING: The resource (or sub resource) Resource{"{id}", 0 child resources, 5 resource methods, 1 sub-resource locator, 4 method handler classes, 0 method handler instances} with path "{id}" contains (sub) resource method(s) and sub resource locator. The resource cannot have both, methods and locator, defined on same path. The locator will be ignored.
It says the locator will be ignored, but it is very much working. What's wrong? By the way, I'd much prefer to be able to use the subresource locator even for path /places/{id}. It should just use the @GET-annotated method in the subresource class; this returns a 405 error code, as stated, though.
Yup, it's illegal. When you add a sub resource, it's responsible for managing its root path as well. So for the path /places/{id} the service wouldn't know which one to use (the method or the sub resource) since they both claim to manage that path. The sub resource locator is indeed ignored, but only for that one ambiguous path (/places/{id}). The path /places/{id}/other stuff is not ambiguous since it doesn't match the GET method's path, so it isn't ignored.
To remove the ambiguity, try modifying the sub resource to only match paths that specify the place ID and other path components. I don't have access to my IDE to test at the moment, but something like this should work:
// Use the following to e.g. GET /places/123/comments/42
@Path("{id}/{otherStuff: [a-zA-Z0-9_/]+}")
public PlaceResource place(@PathParam("id") int id) {
Place p = DAO.getInstance().getPlace(id);
return new PlaceResource(p); // singular (a different resource class)
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With