How do I get the JAX-RS @Path of a different resource during a POST?

前端 未结 4 1816
走了就别回头了
走了就别回头了 2021-02-02 15:09

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

相关标签:
4条回答
  • 2021-02-02 15:55

    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:

    URI newUserUri = uriInfo.getBaseUriBuilder().path(OneUserResource.class).path("/" + user.getId()).build();
    return Response.created(newUserUri).build();
    
    0 讨论(0)
  • 2021-02-02 15:56

    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:

    @POST
    @Consumes({MediaType.APPLICATION-XML, MediaType.APPLICATION-JSON})
    public Response createUser(final User user, @Context UriInfo uriInfo) {
        // persist the user here
        URI uri = uriInfo.getAbsolutePathBuilder().path(user.getId()).build();
        return Response.created(uri).build();
    }
    
    0 讨论(0)
  • 2021-02-02 16:12

    With the strict REST concept you can make it as one root resource

    @POST   /users        -> CREATE a single user
    @GET    /users        -> READ all users
    @PUT    /users        -> UPDATE (REPLACE) all users @@?
    @DELETE /users        -> DELETE all users @@?
    
    @POST   /users/{id}   -> CREATE a single user's some other child; @@?
    @GET    /users/{id}   -> READ a single user
    @PUT    /users/{id}   -> UPDATE a single user
    @DELETE /users/{id}   -> DELETE a single user
    
    @Path("/users")
    @Stateless
    public class UsersResouce {
    
        // /users
        @POST
        @Consumes({MediaType.APPLICATION-XML, MediaType.APPLICATION-JSON})
        public Response createUser(final User user) {
            // persist the user here
            return Response.created("/" + user.getId()).build();
        }
    
        // /users
        @GET
        @Produces({MediaType.APPLICATION-XML, MediaType.APPLICATION-JSON})
        public Response readUsers() {
            //return all users
        }
    
        // /users/{id}
        @GET
        @Path("/{user_id: \\d+}")
        @Produces({MediaType.APPLICATION-XML, MediaType.APPLICATION-JSON})
        public Response readUser(
            @PathParam("user_id") final Long userId) {
    
            final User persisted = userBean.find(userId);
    
            if (persisted == null) {
                return Response.status(Status.NOT_FOUND).build();
            }
    
            return Response.ok().entity(persisted).build();
        }
    
        // /users/{id}
        @Consumes({MediaType.APPLICATION-XML, MediaType.APPLICATION-JSON})
        @PUT
        @Path("/{user_id: \\d+}")
        public Response updateUser(
            @PathParam("user_id") final Long userId,
            final User mergeable) {
    
            final User persisted = userBean.find(userId);
    
            if (persisted == null) {
                userBean.persist(mergeable);
            } else {
                persist.setName(mergeable.getName());
                userBean.merge(persisted);
            }
    
            return Response.status(Status.NO_CONTENT).build();
        }
    
        // /users/{id}
        @DELETE
        @Path("/{user_id: \\d+}")
        public Response deleteUser(
            @PathParam("user_id") final Long userId) {
    
            userBean.delete(userId);
    
            return Response.status(Status.NO_CONTENT).build();
        }
    
        @EJB
        private UserBean userBean;
    }
    
    0 讨论(0)
  • 2021-02-02 16:15

    As of JAX-RS 2.0, the most correct way (As far as I know) is to use the builder method like so:

        String uri = uriInfo.getBaseUriBuilder()
          .path(ODataV4Endpoint.class)
          .path(ODataV4Endpoint.class, "serviceEndpointJSONCatalog")
          .resolveTemplate("endpointId", endpointId).build().toString();
    

    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.

    0 讨论(0)
提交回复
热议问题