2012-02-23 3 views
13

Ho due classi REST per un semplice servizio Web (Jersey e GlassFish) che coinvolge risorse utente: una per operare su tutti gli utenti (ad esempio, una factory per @POSTing) e un'altra su singoli utenti (ad esempio, @GET, @PUT , @ELIMINA). Sono a:Come si ottiene JAX-RS @Path di una risorsa diversa durante un POST?

@Stateless @Path("users") public class AllUsersResource {...} 
@Stateless @Path("user") public class OneUserResource {...} 

rispettivamente. Quando postando AllUsersResource voglio tornare alla posizione (via Response.created(uri).build()) del nuovo utente, ad esempio,

http://localhost:8080/.../user/152 

La mia domanda è come fare questo. AllUsersResource inietta @Context UriInfo uriInfo, ma questo non mi fornisce informazioni @Path per OneUserResource, solo quella della chiamata corrente ("utenti"). Il modo in cui ho finalmente capito di lavoro era semplicemente quello di utilizzare la riflessione, ma sono preoccupato che è fragile e sporco:

OneUserResource.class.getAnnotation(Path.class).value(); 

Ricerca StackOverflow le uniche altre cose che ho trovato a provare sono stati i seguenti, ma senza successo:

  • com.sun.jersey.api.core.ResourceContext
  • javax.ws.rs.core.UriInfo.getMatchedResources()
  • @ javax.inject.Inject OneUserResource oneUserRes;

Qualsiasi aiuto sarebbe fantastico!

risposta

8

Ho trovato un paio di metodi javax.ws.rs.core.UriBuilder che hanno fatto il trucco, che volevo condividere nel caso in cui altri avessero questa domanda. Sono: UriBuilder.fromResource (OneUserResource.class) e javax.ws.rs.core.UriBuilder.path (Class). Ho usato queste ultime in una chiamata one-shot:

URI newUserUri = uriInfo.getBaseUriBuilder().path(OneUserResource.class).path("/" + user.getId()).build(); 
return Response.created(newUserUri).build(); 
+0

Il problema con entrambi questi metodi è che entrambi richiedono ** classi di risorse ** root per funzionare. Non funzioneranno se li usi da una sotto-risorsa (viene lanciato 'IllegalArgumentException'). Quindi, se hai usato una sotto risorsa che gestiva la richiesta POST; e volevi restituire un '201' con l'header' Location', sei ancora sfortunato :( – curioustechizen

5

Con il rigoroso concetto di REST si può fare come risorsa una radice

@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; 
} 
13

È possibile utilizzare UriBuilder.fromresource(), ma questo funziona solo se la classe Resource fornita è una risorsa root (questo è chiaramente menzionato nel javadocs). Ho trovato un modo per ottenere questo risultato anche se ci si trova in una classe di sottocorrente:

@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(); 
} 
+1

questo restituire 'http: // localhost: 8080/project/users/152' invece di' http:// localhost: 8080/project/user/152' mentre il secondo è ciò che è necessario per SO –