2017-06-13 5 views
0

Ich arbeite mit Dropwizard, die Jersey intern verwendet. Ich habe zwei Methoden auf einem Controller:Jersey 2.x - Widersprüchliche Route Priorität von PUT und GET

PUT /garbage/[id1,id2,...idN] soll einen Pfadparameter nehmen, der eine Liste numerischer IDs darstellt, die zu aktualisierende Ressourcen darstellen. Ich verwende hier eine regex-basierte PathParam hier. Ich habe die Regex in diesem Beispiel missbraucht, weil ich denke, dass es nicht wichtig ist, aber der Punkt ist, dass eine einzelne numerische ID mit der Regex übereinstimmen sollte.

GET /garbage/[id] ruft Daten über ein einzelnes Stück Müll ab.

Jersey scheint trotz des Unterschieds in der Methode verwirrt zu werden. Wenn ich mit etwas frage wie

curl localhost:8080/garbage/1 

Jersey gibt mir einen Fehler 405. Wenn ich den PUT aus dem Bild nehme (zum Beispiel den Pfadparam Regex sabotiere oder ihn vollständig entferne), funktioniert der GET-Endpunkt gut.

Ich nehme an, es gibt einige Details in JAX-RS 3.7.2 Ich vermisse das erklärt, warum dies der Fall sein sollte, aber ich kann nicht herausfinden, was es ist.

Hier ist der Code:

@Path("/garbage") 
@Produces(MediaType.APPLICATION_JSON) 
public class GarbageController { 
    private static final Logger LOG = LoggerFactory.getLogger(GarbageController.class); 

    @PUT 
    @Path("/{params: [\\d,]+}") 
    @Consumes(MediaType.APPLICATION_JSON) 
    @Timed 
    public Response updateGarbage(@PathParam("params") List<PathSegment> params) { 
     LOG.warn("updateGarbage"); 
     return Response.status(Response.Status.OK).build(); 
    } 

    @GET 
    @Path("/{garbageId}") 
    public Response getGarbageById(@PathParam("garbageId") long garbageId) { 
     LOG.warn("getGarbage"); 
     return Response.status(Response.Status.OK).build(); 
    } 
} 

Antwort

0

Der Hauptzweck der @PathSegment ist Fragment der URI zu handhaben, das nützlich ist Matrix Parameter abgerufen werden. Zum Beispiel unter der Methode:

@GET 
@Path("/book/{id}") 
public String getBook(@PathParam("id") PathSegment id) {...} 

Sollten diese Anforderung umgehen können:

GET /book;name=EJB 3.0;author=Bill Burke 

Da die @PathSegment das gesamte URL-Fragment dazwischen scheint die GET-Methode ignoriert werden. Sie können die durch Komma getrennte IDs auf der PUT-Anfrage mit einem einfachen String Split Griff:

@PUT 
@Path("/{params}") 
@Consumes(MediaType.APPLICATION_JSON) 
@Timed 
public Response updateGarbage(@PathParam("params") String params) { 
    LOG.warn("updateGarbage ", params.split(",")); 
    return Response.status(Response.Status.OK).build(); 
} 

Sie auch eine Converter/Provider das Anforderungsformat zu query parameters oder implementieren ändern können ein benutzerdefiniertes Objekt zu behandeln. Alle von ihnen sollten das GET nicht implementiertes Problem lösen.

Ich glaube, das ist kein Fall von Routenprioritäten zwischen GET und PUT, sondern hängt mit der Annotation @Consumes zusammen, die bei einer GET-Anfrage nicht verwendet werden kann. Entweder ignoriert DW diesen Endpunkt oder konvertiert ihn in die Standard-POST-Methode, was die 405-Antwort für die GET-Anforderung erklären würde.

+1

Danke für die Antwort! Leider ist \ @Consumes nicht das Problem. Ich habe es sowohl mit als auch ohne die @ @ Consumes versucht, und es hat keine Auswirkung auf das Verhalten. (Ich schrieb diesen Code zunächst ohne \ @Consumes, fügte ihn dann als zufälliges Experiment hinzu und vergaß dann, ihn zu entfernen. Ich gehe zurück und entferne \ @Consumes aus dem Beispielcode, um dies zu verdeutlichen.) –

0

Ich habe das herausgefunden, obwohl ich nicht weit genug in Jersey verfolgt habe, um zu wissen, warum es funktioniert. Die Lösung besteht darin, die @GET-Methode so umzuschreiben, dass sie die gleiche Regex-Syntax wie die @PUT verwendet. Jersey wird die Typumwandlung in der Methodensignatur behandeln, mit dem Hinweis, dass es eine 404 zurückgibt, wenn die Typumwandlung fehlschlägt (z. B. GET /garbage/xyz).

@PUT 
@Path("/{params: .+}") 
@Consumes(MediaType.APPLICATION_JSON) 
public Response updateGarbage(@PathParam("params") List<PathSegment> params) { 
    LOG.warn("updateGarbage"); 
    return Response.status(Response.Status.OK).build(); 
} 

@GET 
@Path("/{params: .+}") 
public Response getGarbageById(@PathParam("params") long garbageId) { 
    LOG.warn("getGarbage {}", garbageId); 
    return Response.status(Response.Status.OK).build(); 
} 
Verwandte Themen