users@jersey.java.net

Matching using Query parameters <was> Re: [Jersey] Example of matrix URIs?

From: Paul Sandoz <Paul.Sandoz_at_Sun.COM>
Date: Mon, 05 Jan 2009 12:23:32 +0100

JAX-RS specifies matching for the path component of a URI and not for
other components of the URI like query.

In your example below there is an ambiguous match and Jersey should
warn you about it.

I recommend you use a sub-resource locator and return different
instances depending on whether the query parameter is present or not.
For example:

   @Path("{id}")
   public Object locateTheme(@PathParam("id") long id,
@QueryParam("select") String select) {
     if (select == null) {
        return new ThemedResource(...);
     } else {
        return ...
     }
   }

The use of inner classes is particularly helpful if you need to share
state with the parent class.

Paul.

On Dec 29, 2008, at 6:28 PM, Gili wrote:

>
> My code defines two methods:
>
> @GET
> @Path("{ids}")
> public String selectThemes(@PathParam("ids") String ids,
> @QueryParam("select") String select);
>
> and
>
> @Path("{id}")
> public ThemeResource locateTheme(@PathParam("id") long id);
>
> I was expecting Jersey to select the 1st one if the user specifies a
> "select" query parameter and the 2nd one if he does not. Instead,
> Jersey
> always selects the first one. This is problematic because I can't
> see an
> easy way to pass Jersey a sub-resources if "select" is null. I can't
> chain
> the method calls by invoking locateTheme() because the return types
> are
> different and I'd rather not have to invoke locateTheme().get() on
> behalf of
> Jersey. What does the JAX-RS standard say about this? Couldn't we
> improve
> Jersey's handling in this case?
>
> Thanks,
> Gili
>
>
> Gili wrote:
>>
>> What about if I provide a "more specific" match for JAX-RS (as
>> follows)?
>> Will it be smart enough to pick this instead of the sub-resource?
>>
>> @GET
>> @Path("{ids}")
>> @Produces(MediaType.APPLICATION_XML)
>> public String selectThemes(@PathParam("ids") String ids,
>> @QueryParam("select") String select)
>>
>> I would then discard the "select" String and use "ids" instead.
>>
>> Gili
>>
>>
>> Gili wrote:
>>>
>>>
>>> Here are some real URIs I have mapped.
>>>
>>> POST /themes to create an image theme (a theme is like a category)
>>>
>>> GET /themes/{id} to retrieve the theme state
>>>
>>> GET /themes/{id};{id};{id}?select=randomImages to select random
>>> images
>>> from a set of image themes
>>>
>>> In other words, /theme/{id} might return the theme name whereas
>>> /theme/1;2;3?select=randomImages would generate a set of all the
>>> images
>>> that fall under themes 1, 2 and 3 then return X random images from
>>> that
>>> pool.
>>>
>>> Here is what I currently have:
>>>
>>> @Path("themes")
>>> class ThemesResource
>>> {
>>> /**
>>> * Returns the Theme sub-resource.
>>> */
>>> @Path("id")
>>> public ThemeResource locateTheme(@PathParam("id") long id);
>>> }
>>>
>>> and now I want to add:
>>>
>>> /**
>>> * Returns the Theme sub-resource.
>>> */
>>> @Path("id")
>>> public String selectRandomImages(@PathParam("id") String
>>> listOfIds);
>>>
>>> I don't think that @Path("{images: [\d,]+"} would help because
>>> locateTheme is supposed to match exactly one id so there would be an
>>> overlap. In fact, "/themes/5?select=randomImages" is perfectly
>>> legal and
>>> should not return a sub-resource.
>>>
>>> Gili
>>>
>>> Paul Sandoz (via Nabble) wrote:
>>>>
>>>> On Nov 11, 2008, at 7:31 PM, Gili wrote:
>>>>
>>>>>
>>>>> Sorry, I forgot to mention... For:
>>>>>
>>>>> http://example.com/images/1;2;5?select=random
>>>>>
>>>>> I already have a sub-resource that matches @Path("{id}").
>>>>
>>>> For what path segment the image ids "1;2;5" ?
>>>>
>>>>> This means that I
>>>>> want one method returning a sub-resource (the "Image" resource),
>>>>> and
>>>>> another
>>>>> method returning an XML document (the list of random images). In
>>>> other
>>>>> words, the method return-type varies based on the query string.
>>>>>
>>>>> Is there a way for me to configure JAX-RS to pick the right method
>>>>> somehow?
>>>>> What do you recommend?
>>>>>
>>>>
>>>> I recommend you use a comma separated list of image ids as it works
>>>> better for path matching. You could have "random" as part of the
>>>> path
>>>> too:
>>>>
>>>> @Path("{images: [\d,]+"}
>>>> public class ImagesResource {
>>>> @PathParam("images") IntegerList images;
>>>>
>>>> @Path("random")
>>>> @GET
>>>> public ... get() {
>>>> }
>>>>
>>>> @GET
>>>> }
>>>>
>>>> If you use a query parameter then you have to do some checking of
>>>> the
>>>> values yourself.
>>>>
>>>> It would help me if you could present some code of how you are
>>>> componentizing things as i might be able to help you better. Or
>>>> break
>>>> down and present the different URIs you want to support.
>>>>
>>>> Paul.
>>>>
>>>>> Thanks,
>>>>> Gili
>>>>>
>>>>>
>>>>>
>>>>> Gili wrote:
>>>>>>
>>>>>> Paul,
>>>>>>
>>>>>> Does @Path ignore query arguments? If I want to parse for:
>>>>>>
>>>>>> http://example.com/images/1;2;5?select=random
>>>>>>
>>>>>> Can I use the following?
>>>>>>
>>>>>> @Path("{id}?select=random")
>>>>>>
>>>>>> or would I be forced to use a single method and fork execution
>>>> myself
>>>>>> based on the query arguments?
>>>>>>
>>>>>> Thanks,
>>>>>> Gili
>>>>>>
>>>>>>
>>>>>> Paul Sandoz wrote:
>>>>>>>
>>>>>>>
>>>>>>> On Nov 10, 2008, at 10:40 PM, Gili wrote:
>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>> Paul Sandoz wrote:
>>>>>>>>>
>>>>>>>>> A better use would be:
>>>>>>>>>
>>>>>>>>> http://example.com/images;1;2;5/tags
>>>>>>>>>
>>>>>>>>> as then the matrix parameters are associated with a named path
>>>>>>>>> segment. Matrix parameters are ignored when path matching. The
>>>>>>>>> best
>>>>>>>>> way to think about them is as query parameters scoped to a
>>>>>>>>> path
>>>>>>>>> segment.
>>>>>>>>>
>>>>>>>>
>>>>>>>> I don't understand how the above would work. Are you saying
>>>>>>>> that
>>>>>>>> "images"
>>>>>>>> would have 3 matrix parameters: 1, 2 and 5?
>>>>>>>
>>>>>>> Yes, specifically there are three matrix parameter names, each
>>>>>>> of
>>>>>>> which has no value.
>>>>>>>
>>>>>>>
>>>>>>>> Paul Sandoz wrote:
>>>
>>>>>>>
>>>>>>>>>
>>>>>>>>> If you are using the path segment matching approach you
>>>>>>>>> could do:
>>>>>>>>>
>>>>>>>>> @GET_at_Path("images/{id: <regex for digits and commas>}/tags")
>>>>>>>>> public ... get(@PathParam("id") ImageList images) { ... }
>>>>>>>>>
>>>>>>>>> and the class ImageList has a string constructor that parses
>>>>>>>>> the
>>>>>>>>> comma
>>>>>>>>> separated list of names (see the Sparklines sample [1]).
>>>>>>>>>
>>>>>>>>
>>>>>>>> Okay, I just wanted to get back a List<Integer>. I guess I
>>>>>>>> could
>>>>>>>> code this
>>>>>>>> up myself.
>>>>>>>
>>>>>>> You could only do that with @MatrixParam (or @QueryParam) if you
>>>>>>> have
>>>>>>> one or more matrix parameters with the same name. You can use
>>>>>>> the
>>>>>>> following class for any @*Param value:
>>>>>>>
>>>>>>> public class IntegerList extends ArrayList<Integer> {
>>>>>>> public IntegerList(String s) {
>>>>>>> super();
>>>>>>>
>>>>>>> for (String v : s.split(",")) {
>>>>>>> try {
>>>>>>> add(Integer.parseInt(v.trim()));
>>>>>>> } catch (Exception ex) {
>>>>>>> throw new WebApplicationException(400);
>>>>>>> }
>>>>>>> }
>>>>>>> if (isEmpty())
>>>>>>> throw new WebApplicationException(400);
>>>>>>> }
>>>>>>> }
>>>>>>>
>>>>>>> Paul.
>>>>>>>
>>>>>>>
>>>> ---------------------------------------------------------------------
>>>>>>> To unsubscribe, e-mail: users-unsubscribe@...
>>>> <http://n2.nabble.com/user/SendEmail.jtp?
>>>> type=node&node=1486388&i=0>
>>>>>>> For additional commands, e-mail: users-help@...
>>>> <http://n2.nabble.com/user/SendEmail.jtp?
>>>> type=node&node=1486388&i=1>
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>
>>>>>>
>>>>>
>>>>> --
>>>>> View this message in context:
>>>> http://n2.nabble.com/Example-of-matrix-URIs--tp1482069p1486308.html
>>>>> Sent from the Jersey mailing list archive at Nabble.com.
>>>>>
>>>>>
>>>>> ---------------------------------------------------------------------
>>>>> To unsubscribe, e-mail: users-unsubscribe@...
>>>> <http://n2.nabble.com/user/SendEmail.jtp?
>>>> type=node&node=1486388&i=2>
>>>>> For additional commands, e-mail: users-help@...
>>>> <http://n2.nabble.com/user/SendEmail.jtp?
>>>> type=node&node=1486388&i=3>
>>>>>
>>>>
>>>>
>>>> ---------------------------------------------------------------------
>>>> To unsubscribe, e-mail: users-unsubscribe@...
>>>> <http://n2.nabble.com/user/SendEmail.jtp?
>>>> type=node&node=1486388&i=4>
>>>> For additional commands, e-mail: users-help@...
>>>> <http://n2.nabble.com/user/SendEmail.jtp?
>>>> type=node&node=1486388&i=5>
>>>>
>>>>
>>>>
>>>> ------------------------------------------------------------------------
>>>> This email is a reply to your post @
>>>> http://n2.nabble.com/Example-of-matrix-URIs--tp1482069p1486388.html
>>>> You can reply by email or by visting the link above.
>>>>
>>>
>>>
>>
>>
>
> --
> View this message in context: http://n2.nabble.com/Example-of-matrix-URIs--tp1482069p2089529.html
> Sent from the Jersey mailing list archive at Nabble.com.
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe_at_jersey.dev.java.net
> For additional commands, e-mail: users-help_at_jersey.dev.java.net
>