I'm working with Dropwizard, which uses Jersey internally. I have two methods on a controller:
PUT /garbage/[id1,id2,...idN]
is intended to take a path parameter that's a list of numeric IDs representing resources to be updated. I'm using a regex-based PathParam
here. I've fudged the regex in this example because I don't think it matters, but the point is that a single numeric ID should match the regex.
GET /garbage/[id]
fetches data about a single piece of garbage.
Jersey seems to get confused, despite the difference in method. When I query with something like
curl localhost:8080/garbage/1
Jersey gives me a 405 error. If I take the PUT out of the picture (for example, sabotage the path param regex, or remove it entirely), the GET endpoint works fine.
I assume there is some detail in JAX-RS 3.7.2 I'm missing that explains why this should be the case, but I can't figure out what it is.
Here's the 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();
}
}
The main purpose of @PathSegment is to handle fragments of the URI which is useful to retrieve Matrix Parameters. For example the method below:
@GET
@Path("/book/{id}")
public String getBook(@PathParam("id") PathSegment id) {...}
Should be able to handle this request:
GET /book;name=EJB 3.0;author=Bill Burke
Because the @PathSegment intercepts the entire URL fragment the GET method seems to be ignored. You can handle the comma-separated IDs on the PUT request with a simple String split:
@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();
}
You can also change the request format to query parameters or implement a Converter/Provider to handle a custom object. All of them should solve the GET not implemented issue.
I believe this is not a case of route priorities between GET and PUT but instead this is related to the @Consumes annotation which cannot be used on a GET request.
Either DW is ignoring this endpoint or is converting it into the default POST method, which would explain the 405 response for the GET request.
I figured this out, although I have not traced far enough into Jersey to know why it works. The solution is to rewrite the @GET
method to use the same regex syntax as the @PUT
. Jersey will handle the type conversion in the method signature, with the note that it will return a 404 if the type conversion fails (ie, 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();
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.