users@jersey.java.net

Re: [Jersey] Using _at_Produces to match Accept with WebKit advice

From: Paul Sandoz <Paul.Sandoz_at_Sun.COM>
Date: Fri, 30 Apr 2010 13:53:35 +0200

Hi John,

On Apr 30, 2010, at 12:51 PM, John Lister wrote:

> Hi, using Jersey 1.1.5 I've got a set of resources that return
> differently formatted data depending on the accept type
> passed(amongst other things) using @Produces, this all works fine
> for most browsers. However I'm having trouble with webkit based ones
> (ie safari), safari lists the accept header as (rightly or wrongly)
>
> application/xml,application/xhtml+xml,text/html;q=0.9,text/
> plain;q=0.8,image/png,*/*;q=0.5
>
> but if I used @Produces ({MediaType.TEXT_HTML,
> MediaType.APPLICATION_XML}) then a request for a page in safari that
> you would expect to be returned as html, actually comes back as xml
> which isn't what a user would expect or probably want.
>

Yes, that is the expected behavior as declared by the accept header
and specified by JAX-RS.


> Does anyone have any suggestions/solutions to this? I've tried a
> couple of things but neither seemed to work...
>
> Originally I had a single method taking all types, but I've tried
> splitting that into 2, one for xml and the other for the other media
> types using the qs qualifier, for example
>
> @Products ({"text/html;qs=1", ...}
> public Response getHtml(){
> ...
>
> @Products ("application/xml;qs=.5")
> public Response getXml(){
> ...
> }
>

Can you try making all the qs values > 1 (the default value being 1),
for example:

@Products ({"text/html;qs=2", ...}
public Response getHtml(){
...

@Products ("application/xml")
public Response getXml(){
...
}

I am trying to think why i restricted values to be > 1 for this to
work. It could be because using "qs=0.5" on the value results in all
other produceable media types with no qs being higher but with no
defined order to those media types.

Could you log an issue? i think we should throw a parsing error if qs
< 1.


> but this doesn't seem to work. I'd expect html to have priority 0.9
> (eg multiply cient and server values) and xml to be 0.5 - but I'm
> still getting xml. I've even added xhtml media type to the first
> method, but the same result..
>

I changed the priority algorithm such that multiplication does not
occur. The media types are ordered just by the qs value. This results
in predictable behavior. The reason being is what required is HTML to
have a higher priority than XML regardless of the client quality as
long as the accept header contains a media type declaration compatible
with the HTML media type. The client cannot know what the priorities
of the server are, thus it cannot meaningfully adjust it's quality
factors in respect the server priorities.


> Secondly I've tried using Request.selectVariant to return the best
> matched type from a supplied list which includes application/xhtml
> +xml and according to the various things I've read on the web as it
> is the most specific at the highest priority it should be matched
> first, but again I still get xml. Looking through the source, it
> seems that for the same priority the first type listed is returned
> first which as I imagine it is almost impossible to know which types
> are more specific than others there isn't much more to do.

Request.selectVariant will not take into account the Jersey "qs"
parameter (another bug, log another issue?) and will result in the
first expected behavior.


> Therefore any ideas short of checking if the browser is webkit and
> doing something different.
>
> On a similar note, is it possible to find out what type @Produces
> has matched against - I originally tried to get this using
> Request.selectVariant as I couldn't see another way.
>

Unfortunately not, this is an oversight in JAX-RS/Jersey. Could you
log another issues?

Thanks,
Paul.