users@jersey.java.net

Re: [Jersey] how to generate URLs

From: Paul Sandoz <Paul.Sandoz_at_Sun.COM>
Date: Mon, 28 Sep 2009 09:53:56 +0200

On Sep 25, 2009, at 4:47 PM, Geoffrey Hendrey wrote:

> Hi Paul,
>
> Agreed that UriInfo would need to be able to serve up a templatized
> version of a uri. If UriInfo had a method getUriTemplate, that might
> do the trick. I think 'putPathParameter' is a better method name
> than replaceOrAppendPathParameter. Usage might look like this.
>
>
> uribuilder
> .path
> (uriInfo
> .getUriTemplate
> ()).putPathParameter("bookNo",bn).putPathParameter("chapterNo",cn);
>

Hmm... there might be some way to support this, it all depends on how
the template is obtained.

Jersey supports ExtendedUriInfo:

   https://jersey.dev.java.net/nonav/apidocs/1.1.2-ea/jersey/com/sun/jersey/api/core/ExtendedUriInfo.html

from which one can get the matched templates that are related to the
matched URIs obtainable from URIInfo.

UriBuilder supports the putting of path parameters templates. Take a
close look at the build method:

   https://jsr311.dev.java.net/nonav/javadoc/javax/ws/rs/core/UriBuilder.html
#build%28java.lang.Object...%29
   https://jsr311.dev.java.net/nonav/javadoc/javax/ws/rs/core/UriBuilder.html
#buildFromMap%28java.util.Map%29

Paul.


> The code that I've had to write instead uses regexes to find the
> right parts of the UriInfo to modify and if not found, appends the
> path parameter.
>
> -geoff
>
> On Sep 25, 2009, at 1:42 AM, Paul Sandoz <Paul.Sandoz_at_Sun.COM> wrote:
>
>> On Sep 25, 2009, at 4:39 AM, Geoff hendrey wrote:
>>
>>> Let's say I have a resource at relative path /book/1/chapter/2, or
>>> more generally, /book/{bookNo}/chapter/{chapterNo}.
>>>
>>> I've been looking for a generic way to generate a list of links.
>>> I've made up a fake method called "replaceOrAppendPathParameter"
>>> to try to convey what I want to do. The URIInfo passed into the
>>> createLinks method might be for any of the following:
>>>
>>> /
>>> /book
>>> /book/9
>>> /book/2/chapter/3
>>>
>>> I want to be able to pass the UriInfo for any of the path's above
>>> into the method below to generate a list of links that includes
>>> both the bookNo and the chapterNo path parameters.
>>>
>>> List<URI> createLinks(UriInfo uriInfo){
>>> List<URI> links = new ArrayList<URI>();
>>> for(int i=0;i<NUM_BOOKS;i++){
>>> for(int j=0;j<NUM_CHAPTERS;j++){
>>> URI link =
>>> uriInfo
>>> .getAbsolutePathBuilder().replaceOrAppendPathParameter("bookNo",
>>> i).replaceOrAppendPathParameter("chapterNo", j).build();
>>> links.add(link);
>>> }
>>> }
>>> return links;
>>> }
>>>
>>> Can anyone help me to accomplish this? I don't want to manually
>>> feed "/book/{bookNo}/chapter/{chapterNo}" into the UriBuilder as
>>> that defeats the purpose of having a single generalized method
>>> capable of generating simple numbered links.
>>>
>>
>> How would the UriBuilder know how to construct the URL without
>> knowing what the template is?
>>
>> There needs to be some knowledge somewhere that "book" and
>> "chapter" are path segments. Are you assuming those path segment
>> names are derived from the path parameter names?
>>
>>
>> It seems that what you want to do even if templates are used is
>> something that UriBuilder cannot easily support. The tricky bit is
>> detecting what URL is given as input to determine whether a path
>> segment should be replaced or path segments should be added. So i
>> do not think UriBuilder is the right solution.
>>
>> Instead i think you require some higher level functionality that
>> operates on the path segments of the URL. You can use
>> UriComponent.decodePath to obtain a list of path segments from
>> which you can iterate through and determine if something should be
>> added or replace according to the rules you require. Thus you can
>> construct the new URL path from the updated list of path segments.
>>
>> Does that help?
>>
>> Paul.
>>
>> [1] https://jersey.dev.java.net/nonav/apidocs/1.1.2-ea/jersey/com/sun/jersey/api/uri/UriComponent.html
>> #decodePath%28java.lang.String,%20boolean%29