dev@jsr311.java.net

RE: Issue 1: Adding additional conneg metadata to _at_Produce/ConsumeXXX

From: Jerome Louvel <jerome.louvel_at_noelios.com>
Date: Sat, 7 Jul 2007 12:49:18 +0200

Hi Marc,

Thanks for looking at the Variant approach in Restlet. I wasn't actually
proposing to separate the concept of Variant and Representation in the
JSR-311. I think that we can abstract things a little more by only exposing
"available representations", therefore removing the need for a
getWidget(variant) method.

> - There's no need to build a list of variants every time

You have taken a case where all the types are available in all the
languages, which looks simpler with Paul's Response.Builder. But have you
considered the case where a language is not available for certain types? You
could also take into account more dimensions: encoding and character set.
The situations where all the combinations are available is rare. Therefore
the Variant approach offers more precision and flexibility.

> - The context of the request is implicit since the conneg occurs
> directly in the method that will service the request

With proper conneg in place, there is no need for extra processing in the
case of GET/HEAD methods in 95% of cases.

> - The application gets a chance to tweak or override the default
> error response when no matching variant is found

Then, a GET method handler could be exposed, disconnecting or tweaking the
default conneg behavior...

Best regards,
Jerome

> -----Message d'origine-----
> De : Marc.Hadley_at_Sun.COM [mailto:Marc.Hadley_at_Sun.COM]
> Envoyé : mardi 3 juillet 2007 19:49
> À : dev_at_jsr311.dev.java.net
> Objet : Re: Issue 1: Adding additional conneg metadata to
> @Produce/ConsumeXXX
>
> Trying to weigh the possible approaches for supporting content
> negotiation based on dynamic metadata, I came up with the example of
> a set of widgets that are available in few different media types and
> languages but the availability differs for each widget (i.e.
> some are
> available in one language, some in two, some have html, some just a
> jpeg).
>
> The first approach is my interpretation of what Jerome is suggesting
> (Jerome if this isn't what you meant then please correct - I looked
> at the Variant class in Restlet but I might have missunderstood its
> use):
>
> @UriTemplate("widgets/{widget}")
> public class Widget {
>
> WidgetEntity widget;
>
> public Widget(@UriParam("widget") String widgetId) {
> widget = findWidgetEntity(widgetId);
> }
>
> @Variants
> List<Variant> getVariants(@HttpMethod String method) {
> List<Variant> variants = new ArrayList<Variant>();
> for (MediaType type: widget.getTypes()) {
> for (String lang: widget.getLanguages()) {
> Variant v = new Variant(type, lang);
> variants.add(v);
> }
> }
> return widget.getTypes();
> }
>
> @HttpMethod
> public InputStream getWidget(@HttpContext Variant v) {
> return widget.getStream(v.type, v.lang);
> }
> }
>
> In the above, the runtime:
>
> (i) calls the constructor,
> (ii) calls the getVariants method to obtain a list of possible
> variants for the current request (I added a @HttpMethod since it
> seems possible that you'd want to return different things depending
> on the method though that isn't shown above, you could also use any
> of the other annotations that can be used on a resource method).
> (iii) perform the conneg matching and either returns an appropriate
> error if there's no acceptable variant or
> (iv) calls the getWidget method passing in the selected
> variant (note
> there's no need to set the negotiated metadata since the runtime can
> do that automatically. If an application wanted to add metadata then
> it would need to return Response and create one from the passed in
> Variant.
>
> An alternate approach is my interpretation of what Paul is suggesting:
>
> @UriTemplate("widgets/{widget}")
> public class Widget {
>
> WidgetEntity widget;
> @HttpContext AcceptabilityEvaluator ae;
>
> public Widget(@UriParam("widget") String widgetId) {
> widget = findWidgetEntity(widgetId);
> }
>
> @HttpMethod
> public Response getWidget() {
> Response.Builder rb = ae.evaluate(widget.getTypes(),
> widget.getLanguages());
> if (rb.getStatus() < 300)
> rb.entity(widget.getStream(rb.getType(), rb.getLanguage()));
> return rb.build();
> }
> }
>
> In the above, the runtime calls the constructor followed by the
> getWidget method and the application uses the
> "AcceptabilityEvaluator" to determine if there is an acceptable
> response or not. The ae.evaluate method returns an appropriate error
> response if there's no acceptable combination or a prefilled OK
> response if there is. The application adds an entity if required and
> return the response.
>
> Personally I prefer the second approach for the following reasons:
>
> - There's no need to build a list of variants every time
> - The context of the request is implicit since the conneg occurs
> directly in the method that will service the request
> - The application gets a chance to tweak or override the default
> error response when no matching variant is found
>
> Thoughts, comments ?
> Marc.
>
>
> On Jun 30, 2007, at 3:02 AM, Jerome Louvel wrote:
>
> >
> > Hi Mark,
> >
> >>> It seems that you mix the ability to expose dynamic representation
> >>> metadata
> >>> and the content negotiation algorithm (interpreting the Accept*
> >>> headers).
> >>>
> >> I don't think its really a matter of mixing them, rather
> the runtime
> >> hands off to the application when there isn't sufficient static
> >> information to make a determination.
> >
> > The conneg algo doesn't need to rely on static metadata
> only. It could
> > perfectly work on dynamic metadata too (like we do in Restlet).
> >
> >>> For the first one, we should just have annotation ways to
> >> expose those metadata, and for some rare cases rely on an
> >> "EntityProvider" service.
> >>>
> >> I don't think EntityProvider is related to dynamic
> metadata. You can
> >> associate some static metadata with one (ConsumeMime, ProduceMime)
> >> but by the time an EntityProvider enters the process all of the
> >> conneg will have already taken place.
> >
> > Why does it have to be processed this way? If you design
> the API for a
> > stricter separation between the resources/representations and
> > conneg algo,
> > this perfectly possible IMHO.
> >
> >> For "annotation ways to expose those metadata" do you mean
> something
> >> like an annotated method that would return, say, the list of
> >> available languages ?
> >
> > Yes, and not only for languages. The notion of variant (consistent
> > set of
> > metadata) is important too.
> >
> > Best regards,
> > Jerome
> >
> >
> ---------------------------------------------------------------------
> > To unsubscribe, e-mail: dev-unsubscribe_at_jsr311.dev.java.net
> > For additional commands, e-mail: dev-help_at_jsr311.dev.java.net
> >
>
> ---
> Marc Hadley <marc.hadley at sun.com>
> CTO Office, Sun Microsystems.
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: dev-unsubscribe_at_jsr311.dev.java.net
> For additional commands, e-mail: dev-help_at_jsr311.dev.java.net
>