Java – How to map semicolon-separated PathParams in Jersey

javajax-rsjerseyrest

Is there a way to use this parameter style:

/products/123;456;789

in JAX-RS with Jersey? If I use PathParam, only the first parameter in the list is returned. I tried to escape the semicolon but then Jersey returns only "123;456;789" as the value of the first parameter list entry

I declared the GET method as

public List<Product> getClichedMessage(@PathParam("ids") List<String> idList)

Update: I am referring to the Jersey user guide for Jersey 1.1.5:

In general the Java type of the method
parameter may (…) 4) be List,
Set or SortedSet, where T
satisfies 2 or 3 above. The resulting
collection is read-only. (…)
Sometimes parameters may contain more
than one value for the same name. If
this is the case then types in 4) may
be used to obtain all values.

Update: here is my test code:

package de.betabeans.resources;

import java.util.List;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;

@Path("/test")
public class TestResource {

    @GET
    @Path("/{ids}")
    @Produces({"text/plain"})
    public String getClichedMessage(@PathParam("ids") List<String> idList) {
        return "size=" + idList.size();
    }

}

Test URL with semicolon escaped: http://localhost:8080/resources/test/1%3B2%3B3

Update: the changelog for Jersey 1.3 include this information:

Fixed issue 540
http://java.net/jira/browse/JERSEY-540
Parameterized types of
List/Set/SortedSet are supported for
parameters, for example
@QueryParam("d") List>,
if there is a StringReaderProvider
registered that supports the type
List.

I'll check out StringReaderProvider based on this post http://comments.gmane.org/gmane.comp.java.jersey.user/7545

Best Answer

When you use semicolon, you create Matrix parameters. You can use either @MatrixParam or PathSegment to get them. Example:

 public String get(@PathParam("param") PathSegment pathSegment)

Pay attention that Matrix parameters are these that follow the original parameter. So in case of "123;456;789" - 123 is path parameter, while 456 and 789 are the names of matrix parameters.

So if you want to get products by ids, you can do something like this:

public List<Product> getClichedMessage(@PathParam("ids") PathSegment pathSegment) {
    Set<String> ids = pathSegment.getMatrixParameters().keySet();
    // continue coding
}

Pay attention that your url should be /products/ids;123;456;789

Actually, IMO it is not a very good design: you use matrix parameter name as a value. I think using query parameters is better: /products?id=123&id=456&id=789, so you can easily get them in method:

public List<Product> getClichedMessage(@QueryParam("id") List<String> ids)