I have two REST classes for a simple web service (Jersey and GlassFish) that involves user resources - one to operate on all users (e.g., a factory for @POSTing) and another on individual users (e.g., @GET, @PUT, @DELETE). They are at:
@Stateless @Path("users") public class AllUsersResource {...}
@Stateless @Path("user") public class OneUserResource {...}
respectively. When POSTing to AllUsersResource I want to return the Location (via Response.created(uri).build()
) of the new User, e.g.,
http://localhost:8080/.../user/152
My question is how to do this. AllUsersResource injects @Context UriInfo uriInfo, but that does not get me @Path info for OneUserResource, only that of the current call ("users"). The way I finally got it working was simply to use reflection, but I'm worried it is brittle and unclean:
OneUserResource.class.getAnnotation(Path.class).value();
Searching StackOverflow the only other things I found to try were the following, without success:
- com.sun.jersey.api.core.ResourceContext
- javax.ws.rs.core.UriInfo.getMatchedResources()
- @javax.inject.Inject OneUserResource oneUserRes;
Any help would be terrific!
With the strict REST concept you can make it as one root resource
I found a couple of javax.ws.rs.core.UriBuilder methods that did the trick, which I wanted to share in case others had this question. They are: UriBuilder.fromResource(OneUserResource.class) and javax.ws.rs.core.UriBuilder.path(Class). I used the latter in a one-shot call:
You can use UriBuilder.fromresource(), but this only works if the supplied Resource class is a root resource (this is clearly mentioned in the javadocs). I found a way to achieve this even if you are in a sub-resource class:
As of JAX-RS 2.0, the most correct way (As far as I know) is to use the builder method like so:
FYI, I need to call path twice in my case, once for the path annotation on the class, and the second time for the annotation on the method. I suspected the call to the method would do both, but it does not.
The Path annotation on the endpoint serviceEndpointJSONCatalog declared a parameter, like so: 'endpoint/{endpointId}', so the call to resolveTemplate was needed. Otherwise you would just call path(Class cl, String method).
In my case I created a builder and a symbolic way to reference the methods so the compiler / runtime could check them.