Jersey @Path for plural/single REST nouns in same class
java, jersey, rest
Solution
This part is about what you need:
Personally, I find your mapping strange and confusing. Just keep it like this:
@Path("widgets")
@Produces(MediaType.APPLICATION_XML)
public class WidgetResource {
@GET
public Response getWidgets(@QueryParam("limit")) {
//This method returns the plural noun, a list of widgets
// it's also possible to limit the number returned by
// using a query parameter. You could easily implement
// pagination by adding further query parameters like
// 'offset', 'sortOrder', etc.
//...
}
@GET
@Path("{id}")
public Response getWidgetById(@PathParam("id") long id) {
//This method returns a single widget by id
//...
}
}
It seems natural to append the path to a collection with an ID to fetch an object from the collection. There's really no need to make it `widgets/widget/{id}`. The `widget` part is obvious and unnecessary.
Here's a really neat tutorial on RESTful APIs: "Teach a dog to REST" by apigee I think it's a really good video. The authors make a couple of good points. And here's a link to a longer version of the same presentation
This part is about what you want:
If you really want to keep the plural/singular dualism (which I really don't recomment), you can annotate your code like this: But it's really ugly
@Path("/")
@Produces(MediaType.APPLICATION_XML)
public class WidgetResource {
@GET
@Path("widgets")
public Response getWidgets(@QueryParam("limit")) {
//This method returns the plural noun, a list of widgets
//...}
@GET
@Path("widget/{id}")
public Response getWidgetById(@PathParam("id") long id) {
//This method returns a single widget by id
//...
}
}
Problem
I have a class this is annotated with `@Path` like so: ``` @Path("widgets") @Produces(MediaType.APPLICATION_XML) public class WidgetResource { @GET public Response getWidgets(@QueryParam("limit")) { //This class returns the plural noun, a list of widgets //...} @GET @Path("widget/{id}") public Response getWidgetById(@PathParam("id") long id) { //This class returns a single widget by id //...} ``` When I fire up a test client the localhost/widgets maps as expected, but when the `getWidgetById` method is mapped to `localhost/widgets/widget/{id}`. This is not what I want - I would like to have `localhost/widgets and localhost/widget/{id}` I have tried omitting the `@Path` annotation at the class level, but that prevents Jersey from recognizing this class as a REST Resource (I tried both the `ScanningResourceConfig` and the `ClassNameResourceConfig` - both failed to load the class as a resource unless there was a `@Path` at the class level). I guess a (ugly) workaround would be to split the methods between classes a `WidgetResource` class and a `WidgetsResource` class. I think this is a terrible solution since both of these methods share resources in the same class, but I really need the REST-ful `localhost/widget` (for a single entity) and `localhost/widgets` (for plural). Am I missing something - is there some way for me to have Jersey pick up the class as a Resource class if I just `@Path` annotate the methods (I couldn't get it to work), if not can I force absolute mapping (`@Path(/widget/{id})`) or some relative mapping (`@Path(../widget/id`) - neither of those work in reality - just an analogy of what I'm after. Thanks!