dev@jsr311.java.net

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

From: Marc Hadley <Marc.Hadley_at_Sun.COM>
Date: Mon, 09 Jul 2007 09:44:27 -0400

On Jul 9, 2007, at 5:39 AM, Paul Sandoz wrote:
>
> When i read back through the thread it is hard for me to understand
> what you are proposing as my understanding keeps changing.
>
> If you have the time it would be most helpful if you could provide
> a concrete example of what you are proposing.
>
+1, I'd also appreciate a concrete example. Could you rewrite the
example I gave using your ideas so we can make a direct comparison.

Thanks,
Marc.

> I get the impression you are proposing to return a list of
> 'representation+meta-data' (concretely it could be a list of
> Response) from which one 'representation+meta-data' will be
> selected and returned as the response to a GET request. But, I
> really don't want to speculate any further :-)
>
> Paul.
>
> Jerome Louvel wrote:
>> 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
>>>
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: dev-unsubscribe_at_jsr311.dev.java.net
>> For additional commands, e-mail: dev-help_at_jsr311.dev.java.net
>
> --
> | ? + ? = To question
> ----------------\
> Paul Sandoz
> x38109
> +33-4-76188109
>
> ---------------------------------------------------------------------
> 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.