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:
-
An insecure GET method to read all competitions promoted by a
JUG:
GET /{competition_id}/homework
Sample URL: 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
-
An insecure GET method to read all homeworks from a competition
name:
GET /{competition_id}/homework
Sample URL: 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
-
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") <-- 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) {
// 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> <-- 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 Dr. Hadley is to use
the @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 :) |
 |
The Mappings in the Servlet 2.5 specification
From the section 11.2 of the Servlet
2.5 Specification, you read:
The Mappings in the JAX-RS 1.0 specification
Jersey is the reference implementation for the JAX-RS
specification 1.0, and the way it defines URL patterns is a bit
different from the Servlet spec. At section 3.4 of the JAX-RS
1.0 specification you read:
-
A root resource class is anchored in URI space using the @Path
annotation. The value of the annotation is 23 a relative URI path
template whose base URI is provided by the deployment context. 24 A URI
path template is a string with zero or more embedded parameters that,
when values are substituted 25 for all the parameters, is a valid URI path. The Javadoc
for the @Path annotation describes their syntax.
In the Jersey
javadoc you read:
-
Embedded template parameters are allowed and are of the form:
param = "{" *WSP name *WSP [ ":" *WSP regex *WSP ] "}"
name = (ALPHA / DIGIT / "_")*(ALPHA / DIGIT / "." / "_" / "-" ) ; \w[\w\.-]*
regex = *( nonbrace / "{" *nonbrace "}" ) ; where nonbrace is any char other than "{" and "}
"See RFC 5234 for a
description of the syntax used above and the expansions of WSP, ALPHA
and DIGIT. In the above name is the template parameter name and the
optional regex specifies the contents of the capturing group for the
parameter. If regex is not supplied then a default value of [^/]+
which terminates at a path segment boundary, is used. Matching of
request URIs to URI templates is performed against encoded path values
and implementations will not escape literal characters in regex
automatically, therefore any literals in regex should be escaped by
the author according to the rules of RFC 3986
section 3.3. Caution is recommended in the use of regex, incorrect use
can lead to a template parameter matching unexpected URI paths. See
Pattern for further information on the syntax of regular expressions.
Values of template parameters may be extracted using PathParam. The
literal part of the supplied value (those characters that are not part
of a template parameter) is automatically percent encoded to conform
to the path production of RFC 3986
section 3.3. Note that percent encoded values are allowed in the
literal part of the value, an implementation will recognize such
values and will not double encode the '%' character".
buy zithromax online