Hi Dig,

Thanks for the questions which gives us an opportunity to discuss content
negotiation and how it is supported in Restlet.

1) About getVariants()

This method is indeed called several times during the processing. Therefore,
it is recommended to not override it unless you have a good reason for. I've
just added this to the Javadocs:

"It is recommended to not override this method and to simply use it at
construction time to initialize the list of available variants. Overriding
it will force you to reconstruct the list for each call which is expensive."

2) Taking client preferences into account

When declaring the available variants, you shouldn't have to check client
preferences. This is the responsibility of the content negotiation
algorithm, which is invoked by the "handleGet" method transparently, unless
you set the "Resource.negotiateContent" property to false.

So, your "if (doesClientAccept(MediaType.TEXT_HTML)" test and your
"doesClientAccept" method shouldn't be necessary.

3) Is there an automated and elegant way to specify prioritisation?

There are three answers. First, if you are using the Directory finder, you
can always specify specific extensions like ".json" or ".xml".

Second, you can rely on the "Application.tunnelService" property to override
the client preferences. This is useful when you can't manually change the
"Accept" HTTP header in your client, such as for browsers. This allows you
to add a query parameter like "?media=json" at the end of your URI. The
parameter will be extracted to override the client preferences and will be
removed from the target URI actually received by your application's root
Restlet.

Otherwise, if your client obviously sends wrong client preferences (like IE5
saying it prefers Word over HTML), you could write a Filter that would
detect the user agent and alter the client preferences on the fly. That
would allow the content negotiation to work properly and this is the
recommended way. In the future, we may provide more assistance on this
front, see:
http://restlet.tigris.org/issues/show_bug.cgi?id=244

4) Is there a need for a priority number on Variant? 

IMO, there is no such need, all variants should be equally good
representations of the resource. Only the order of the variants could matter
if they all happen to get the same score during content negotiation. So, the
first variant should be the 'preferred'.

Best regards,
Jerome  

> -----Message d'origine-----
> De : news [mailto:[EMAIL PROTECTED] De la part de Dig
> Envoyé : lundi 22 janvier 2007 20:34
> À : [email protected]
> Objet : Re: handling multiple representations of a resource
> 
> 
> Sumit Lohia <sumit.lohia <at> gmail.com> writes:
> > 
> > Jerome Louvel <contact <at> noelios.com> writes:
> > 
> (snipped previous messages about handling multiple 
> representations of a
> resource). 
> 
> Hi,
> 
> I have resources which have three potential representations: 
> HTML, JSON
> and XML. I would like these representations to be available 
> all the time
> but to be prioritised sensibly based on the client - e.g. HTML first,
> then JSON and/or XML.
> 
> If I just make all the Variants available then some clients get the
> 'wrong' variant. Safari likes JSON and Firefox likes XML...
> 
> Is there an automated and elegant way to specify 
> prioritisation? Here is
> how I'm currently doing this in my Resource implementation:
> 
>     @Override
>     public List<Variant> getVariants() {
>         List<Variant> varients = super.getVariants();
>         // TODO: does cover all web browser clients?
>         if (doesClientAccept(MediaType.TEXT_HTML) ||
> doesClientAccept(MediaType.ALL)) {
>             varients.add(new Variant(MediaType.TEXT_HTML));
>         } else {
>             varients.add(new Variant(MediaType.APPLICATION_XML));
>             varients.add(new Variant(MediaType.APPLICATION_JSON));
>         }
>         return varients;
>     }
> 
>     @Override
>     public Representation getRepresentation(Variant variant) {
>         if (variant.getMediaType().equals(MediaType.TEXT_HTML)) {
>             return getHtmlRepresentation(); // implemented elsewhere
>         } else if (variant.getMediaType()
>                                               
> .equals(MediaType.APPLICATION_JSON)) {
>             return getJsonRepresentation(); // implemented elsewhere
>         } else if (variant.getMediaType()
>                                               
> .equals(MediaType.APPLICATION_XML)) {
>             return getDomRepresentation(); // implemented elsewhere
>         } else {
>             return super.getRepresentation(variant);
>         }
>     }
> 
>     // this ignores Preference 'quality'
>     public boolean doesClientAccept(MediaType mediaType) {
>         List<Preference<MediaType>> mediaTypePrefs =
>                 getRequest().getClientInfo().getAcceptedMediaTypes();
>         for (Preference<MediaType> mediaTypePref : mediaTypePrefs) {
>             if (mediaTypePref.getMetadata().equals(mediaType)) {
>                 return true;
>             }
>         }
>         return false;
>     }
> 
> I have this code in a base class so it's not really in the 
> way but I think
> it's probably not the best implementation. Any ideas?
> 
> Is there a need for a priority number on Variant? so I could do the
> following:
> 
> varients.add(new Variant(MediaType.TEXT_HTML, 1.0)); // first
> varients.add(new Variant(MediaType.APPLICATION_XML, 0.5)); // = second
> varients.add(new Variant(MediaType.APPLICATION_JSON, 0.5)); 
> // = second
> 
> Also: getVariants() gets called three times per request - is 
> this expected?
> 
> Best regards,
> 
> Dig.
> 
> 
> 

Reply via email to