Skip to main content

URL patterns are more flexible in Jersey than in the web.xml

Posted by felipegaucho on September 17, 2009 at 10:26 AM PDT

Rule of thumb: Avoid to use {variables} as the first path of a
Jersey's @Path

I am working on the Arena PUJ Project, a RESTful web-service to
support PUJ competitions. We are in the early stages of the project but
we already got some resources published on the web. Let me show you a
few URL samples:

  1. An insecure GET method to read all competitions promoted by a
    JUG:

    GET /{competition_id}/homework
    Sample URL: 		href="http://fgaucho.dyndns.org:8080/arena-http/institution/cejug/competition">http://fgaucho.dyndns.org:8080/arena-http/institution/cejug/competition
    curl -v -H "Accept: application/json" -XGET
    http://fgaucho.dyndns.org:8080/arena-http/institution/cejug/competition
  2. An insecure GET method to read all homeworks from a competition
    name:

    GET /{competition_id}/homework
    Sample URL: 		href="http://fgaucho.dyndns.org:8080/arena-http/PUJCE-08/homework">http://fgaucho.dyndns.org:8080/arena-http/PUJCE-08/homework
    curl -v -H "Accept: application/json" -XGET
    http://fgaucho.dyndns.org:8080/arena-http/PUJCE-08/homework
  3. A secure method for creating a new homework. In the PUJ business
    model, only professors can submit a homework.

    POST /{competition_id}/homework/{homework_id}
    Sample URL:
    http://fgaucho.dyndns.org:8080/arena-http/PUJCE-08/homework/newHomework
    curl -v -H "Accept: application/json" -XPOST
    http://fgaucho.dyndns.org:8080/arena-http/PUJCE-08/homework/newHomework

The problem: you cannot map variables in the beggining of the
path in the web.xml

In Jersey, all the above URLs are valid, actually Jersey can also
use regular expressions to map URLs to resources. A cool feature that
looses its beauty in the web.xml file.

Observe the third example, it is a URL that starts with a
variable, in Jersey it is declared like this:

@Path("{puj}/homework") 	color="red"><-- Avoid to use {variables} as the first path of a resource
public class PujHomeworkResource {
    @POST
    @Produces( { MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
    @Path("{acronym}")
    public PujHomeworkEntity create(@PathParam("puj") String name, @PathParam("acronym") String acronym) {
        // href="http://kenai.com/projects/puj/sources/arena/content/arena-http/src/main/java/com/kenai/puj/arena/http/PujHomeworkResource.java?rev=81">click here to see the full code.
    }
}

And the simple problem is: web.xml does not support dynamic
patterns in the same way Jersey do. So, you just cannot declare a
url-pattern like /*/homework/*:

    <security-constraint>
        <display-name>Restrict advertisement pages to
            customers</display-name>
        <web-resource-collection>
            <web-resource-name>To create Homework is privileged to Professors</web-resource-name>
            <description />
            <url-pattern>/*/homework/*</url-pattern> color="red"><-- This is valid but useless :(
            <http-method>POST</http-method>
            <http-method>GET</http-method>
        </web-resource-collection>
        <auth-constraint>
            <description>PUJ Homeworks.</description>
            <role-name>professor</role-name>
        </auth-constraint>
        <user-data-constraint>
            <transport-guarantee>CONFIDENTIAL</transport-guarantee>
        </user-data-constraint>
    </security-constraint>

Such url-pattern /*/homework/* will not map URLs
like /PUJCE-09/homework or /GOJAVA-09/homework.
It is yet possible to use the variables from Jersey, but it would
required a static mapping for each possible value in the web.xml file -
useless.

Workarounds

There is no much I can see as alternative other
than to refactor my code and do include a static path in the beginning
of my URLs. An alternative proposed by href="http://www.java.net/blogs/mhadley/">Dr. Hadley is to use
the href="http://java.sun.com/developer/technicalArticles/J2EE/security_annotation/">@RolesAllowed
annotation, what can fix the problem but eventually creates another
problem (IMO). If you declare the security of your application by
annotations, you need to recompile and re-deploy the whole application
on every security constraints update. In case you know in advance that
your application will have seldom updates, ok - go ahead and use the
annotations. For now, I will
include the static names in the beginning of all paths. Once I finish
that task, I will continue my REST trip and perhaps come back here with
more details. I included some references below in case you are looking
for what the specs say about that :)
border="0" src="http://jersey.dev.java.net/images/Jersey_yellow.png" />

The Mappings in the Servlet 2.5 specification

From the section 11.2 of the href="http://jcp.org/aboutJava/communityprocess/mrel/jsr154/index2.html">Servlet
2.5 Specification, you read:

Comments

I use variables as the path

I use variables as the path often because it's just easy to do sometimes... Anyway, I wonder how MMORPG games on Java work so smoothly. Ie. Runescape.