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!
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
//...
}
}
My suggestion is to have your paths be:
"widgets"
and "widgets/id/{id}"
. Or if you knew you were never going to query by anything other than id, your second one could simply be "widgets/{id}"
.
I would not switch between plural and singular in your path. Since you accessing the same type of resource for both, your root should be the same. The second form just specifies it more -- a vectoring-based approach for getting more specific.
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