users@jsr311.java.net

Error in JAX-RS method finding algorithm?

From: Barry Fitzgerald <barfitzgerald_at_gmail.com>
Date: Mon, 11 Feb 2008 15:25:12 +0000

Hi all,

I think there is an error in the algorithm in the JAX-RS specs for choosing
the resource method (see bullet 2. in section 2.6)

Consider the following scenario:

I have a resource with 2 methods:

@HttpMethod("GET")
@UriTemplate("/users/{id}")
@ProduceMime("text/xml")
public Response getUser(@UriParam("id") String id) throws Exception { ....}

@HttpMethod("GET")
@UriTemplate("/users/{id}")
@ProduceMime("application/json")
public Response getUserJSON(@UriParam("id") String id) throws Exception {
....}

If I then send a request to /users/24 with Accept headers of "text/xml,
*/*" one would expect the "text/xml" method to be invoked. However following
the algorithm in the spec it is undefined which method should be invoked.

More details:

In the algorithm, both methods match the accept headers i.e. they are both
added to the list of "matching resource methods" This list is then sorted
using the consume mime type (not relevant in this case) and then by the
produce mime. In this case it will compare "text/xml" against
"application/json". As both are equally specific it is undefined which
should be first.

However surely as the "text/xml" method matches the accept header
specifically it should always be returned first? See -
http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html for further details

One solution would be to change the algorithm to the following:

   1. Sort the Accept header according to the W3 standards
   2. Iterate through the accept header list. For each one:
   1. Find all matching methods
      2. If there is only one method return this and break out of the
      accept header loop
      3. If there are multiple methods sort these methods using
      consume mime and produce mime. Then return the first.

Therefore when accept header of "text/xml, text/*, */*" is sent in. Methods
matching "text/html" are first searched for then "text/*" then "*/*". I
think this would solve the problem.

This isn't some arbitrary obscure scenario.

Looking at firefox's defaults it sends
"text/xml,application/xml,application/xhtml+xml,text/html;q=0.9
,text/plain;q=0.8,image/png,*/*;q=0.5"

Surely for a request from firefox I'd expect to get back one of the stated
accepts not "application/widget" or "application/json"?

Barry