Building URIs

At first sight building URIs using Java SE appears deceptively simple. Beware!

Say for example i have an instance of java.net.URI, baseUri, that is the following:

"http://localhost:8080/base"

and i want to append the following relative path to that URI:

"a:b;param=matrix/hello world"

such that i would like my URI to be:

"http://localhost:8080/base/a:b;param=matrix/hello%20world"

It is not possible to create a URI with the relative path like this:

new URI("a:b;param=matrix/hello world");
new URI(null, null, "a:b;param=matrix/hello world", null);

because, in the first case, there is an illegal character, the space character in "hello world", and therefore resorting to string concatenation will also result in an invalid URI:

baseUri.toString() + '/' + "a:b;param=matrix/hello world"

Further more, for both cases java.net.URI correctly assumes the "a:" is a scheme (although it gets very confused about the rest of the URI!).

We could do this:

uri = baseUri.resolve(
    new URI(null, null, "/a:b;param=matrix/hello world", null);

but because a '/' is prefixed to the path we will loose the path of baseUri. [Update: the path of baseUri will be lost regardless of prefixing because it does not end with a '/']

The only reliable way of doing this using java.net.URI is if a new URI is created from the components of baseUri:

URI u = new URI(base.getScheme(),
    base.getUserInfo(), base.getHost(), base.getPort(),
    base.getPath() + "/a:b;param=matrix/hello world",
    base.getQuery(), base.getScheme());

What a PITA! If the baseUri was "http://localhost:8080/base/" then i would end up with two '/' in between the base path and the appended path so in general i should ensure that only a single '/' occurs.

This is why the JSR-311 expert group is specifying the UriBuilder class as part of JAX-RS so you can do this:

UriBuilder.fromUri(baseUri).
    path("a:b;param=matrix/hello world").build();

or if i would like to be explicit about the matrix parameters:

UriBuilder.fromUri(baseUri).
    path("a:b").
    matrixParam("param", "matrix").
    path("hello world").build();

to create the desired URI intuitively and safely.

UriBuilder also supports URI templates so i could do:

UriBuilder.fromUri(baseUri).
    path("a:{p1}").
    matrixParam("param", "{p2}").
    path("hello {p3}").build("b", "matrix", "world");

You can find an implementation of UriBuilder in the latest build of Jersey. however, since we have yet to pull in the latest 311 API into Jersey i have made a clone you can find it at com.sun.ws.rest.api.core.UriBuilder if you want to have a play.

Comments:

Post a Comment:
  • HTML Syntax: NOT allowed
About

sandoz

Search

Archives
« April 2014
SunMonTueWedThuFriSat
  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
   
       
Today