Rehtron
Rehtron

Reputation: 234

Jersey @Path cannot process question mark('?')

I have two REST URLs like:

http://myschool/student/jack //get student information.
http://myschool/student/jack?books //get student books.

Code:

@Path("student")
public class StudentResource {

    @GET
    @Path("{name}")
    public Response getInformation(@PathParam("name") String name) {
        return Response.ok(loadStudentInformation(name));
    }

    @GET
    @Path("{name}?books") //ineffective expression
    public Response getBooks(@PathParam("name") String name) {
        return Response.ok(loadStudentBooks(name));
    }

Jersey cannot process the second url 'http://myschool/student/jack?books', it always dispatch the incoming request which end with '?books' to the first method 'getInformation'.

I try to use regular expression like this:

    @GET
    @Path("{name : .*(\\?books$)}") //ineffective expression
    public Response getBooks(@PathParam("name") String studentName) {

The regular expression is ineffective too, can someone please help me figure out how to implement this.

Thanks.

Upvotes: 1

Views: 4213

Answers (2)

Martin Matula
Martin Matula

Reputation: 7989

If you really need to use question mark to separate {name} and books, you can do it as follows:

@GET
@Path("{name}")
public Response getInformation(@PathParam("name") String name, @QueryParam("books") String books) {
    if (books != null) {
        // "books" was included after the question mark
        return getBooks(name);
    } else {
        // "books" was not included after the question mark
        return Response.ok(loadStudentInformation(name));
    }
}

public Response getBooks(String name) {
    return Response.ok(loadStudentBooks(name));
}

UPDATE: Also, if you are using a question mark where slash would be more appropriate (as according to the spec, question mark starts the query parameters section), as another alternative you can consider writing a ContainerRequestFilter that replaces question mark in the request by slash - this will allow you to design your resources as the other answer suggests without breaking the API compatibility.

The filter can be as simple as this:

public class QueryParamToPathSegmentFilter implements ContainerRequestFilter {

    @Override
    public ContainerRequest filter(ContainerRequest request) {
        String requestUri = request.getRequestUri().toString();
        requestUri = requestUri.replace('?', '/');
        request.setUris(request.getBaseUri(), UriBuilder.fromUri(requestUri).build());
        return request;
    }

}

Depending on how your URI's look like - you can make it more sophisticated. Here is more on how you can register filters in your application: http://jersey.java.net/nonav/apidocs/latest/jersey/com/sun/jersey/api/container/filter/package-summary.html

Upvotes: 3

talnicolas
talnicolas

Reputation: 14053

You could just set the path to:

@Path("{name}/books")

instead of:

@Path("{name}?books")

and then you would just get the list of books at that url:

http://myschool/student/jack/books //get student books.

Question mark in a URL usually means that you want to pass parameters to a service (in which case you'd want to use QueryParam), but I don't think this is what it is about here, you just want to create a different service.

Upvotes: 0

Related Questions