users@jax-rs-spec.java.net

[jax-rs-spec users] Re: Different algorithms for sorting MBRs and MBWs

From: Sergey Beryozkin <sberyozkin_at_talend.com>
Date: Fri, 3 Apr 2015 16:07:20 +0100

Hi

I'd like to do a very short summary (as promised to Santiago)

1. Given that MBR can support parameters which are subclasses of its
generic type (ex, JAXB reader, etc), it makes sense to clarify in the
spec (as suggested by Santiago earlier on) that MBR's generic type does
affect the order in which it is selected but only if a given pair of
MBRs offers an equivalent media type support. I'm fine if it is not
referred to as 'sorting by the (generic) type'.

This is not the same as for MBW. I'm not sure if it is good or not so
good. Unlikely to be changed anything here I guess, but may be worth
reviewing

2. This is actually not related to this thread, but while it may be
obvious, it is worth stressing IMHO that MBR that does not depend on
declarative Consumes and does the dynamic media type checks in its
isReadable(...) instead can offer the equivalent and compliant
implementation of a requirement "for supporting the conversion of a
given media type payload into a given Java type"

Thanks, Sergey

On 02/04/15 14:34, Sergey Beryozkin wrote:
> Hi Santiago,
>
> thanks, let me comment here first,
> On 02/04/15 13:14, Santiago Pericas-Geertsen wrote:
>>
>>> On Apr 1, 2015, at 5:29 PM, Sergey Beryozkin <sberyozkin_at_talend.com
>>> <mailto:sberyozkin_at_talend.com>> wrote:
>>>
>>>>>
>>>>>>
>>>>>> Perhaps providing a complete example may help :)
>>>>>
>>>>> CXF has a primitive provider (Boolean, Character, Number) as
>>>>> MBR<Object>,
>>>>
>>>> I see where your coming from now :)
>>>>
>>>>> it (now) enforces a spec requirement that these primitives are only
>>>>> supported by default if it is text/plain by doing an internal check in
>>>>> its isReadable, it has no explicit Consumes.
>>>>
>>>> Why no explicit @Consumes? This does not seem right to me.
>>>>
>>> What is non compliant in writing a provider that prefers to do a media
>>> type check itself as opposed to expecting the runtime do it ?
>>
>> Because the algorithm in Section 4.2.3 states that it looks at the
>> @Consumes. If you don’t have one, then that affects the outcome of the
>> algorithm. In particular, the following sentence from Section 4.2.3:
>>
>> Sorting of media types follows the general rule: x/y < x/* < */*, i.e. a
>> provider that explicitly lists a media types is sorted before a provider
>> that lists */*.
>
> I understand it. What you say above just confirms that an explicit
> Consumes property may affect the order in which providers are checked.
> I do not see the spec saying that providers *must* use Consumes in order
> to assert they can support a given media type.
>
> The spec may say that a given provider must support a given media type
> for converting a payload to a given Java type but the spec has never
> been into specifying how this is to be implemented nor it says that
> shipping or registering MBR without explicit Consumes (or with a
> wildcard Consumes) is non-compliant.
>
> MBR.isReadable is the ultimate 'decision-maker' and while it is true
> many/most MBRs would let the runtime take care of avoiding calling its
> isReadable by using declarative Consumes providers can choose to do such
> checks themselves by offering a wildcard Consumes. Depending on static
> Consumes with concrete values may not always be practical.
>
>>
>>
>>>
>>>>> A custom MBR<Boolean> is registered without Consumes. The test expects
>>>>> the default primitive provider is to be selected based on the fact the
>>>>> spec requires that it supports text/plain.
>>>>
>>>> If the built-in had @Consumes(text/plain) and the custom
>>>> @Consumes(*/*) (same as not @Consumes), then the primitive would be
>>>> selected if the media type is text/plain.
>>>>
>>>>>
>>>>> I think the spec does not require how its requirements that only
>>>>> text/plain payloads can be mapped to Boolean/etc, but I'm wondering,
>>>>> even if we had
>>>>>
>>>>> @Consumes(text/plain)
>>>>> BooleanAndNumberAndCharacterMBR<Object>
>>>>>
>>>>> then how would it win over a custom
>>>>>
>>>>> @Consumes(*/*)
>>>>> BooleanMBR<Boolean>
>>>>
>>>> Step 3 in 4.2.1 refers to Section 4.2.3 where concrete media types
>>>> like text/plain are preferred (sorted) over */* (or say text/*). Thus,
>>>> isReadable should be tried on the built-in first and it should be used.
>>>>
>>> I honestly do not get it.
>>>
>>> How come BooleanAndNumberAndCharacterMBR<Object> will get selected if
>>> you have said earlier that if we have B extending A, MBR<A> and
>>> MBR<B>, a B parameter, in which case B must be selected ?
>>
>> Because I was assuming that a MBR<A> could only read A and a MBR<B>
>> could only read B. You changed this when you allowed a MBR to support
>> subtypes, as in the <Object> case.
>
> Even if A == Object it does not change the fact B still extends A.
> What I'm saying is that if two such providers with *equal* Consumes are
> registered, the runtime needs to take care of MBR<Object> too, it can
> not discard it at the runtime init time.
>
> At the request time, given B, the runtime needs to choose which provider
> to use. If MBR<B> is on top of the list immediately it means the runtime
> has already sorted them at the init time and if it starts sees
> MBR<Object> first before checking MBR<B> then it obviously needs to keep
> MBR<Object> as a candidate before MBR<B> is located in which case it
> must choose the best candidate meaning comparing Object vs B, i.e,
> sorting these providers using the generic type, with Consumes being
> equal for both providers.
>
>
>
>>
>>>
>>>> It seems that Section 4.2.1 could be a bit more specific about this
>>>> “sorting” than what it is now.
>>>>
>>>
>>> Why in quotes ?
>>>
>>> If we have
>>> BooleanAndNumberAndCharacterMBR<Object>
>>> BooleanMBR<Boolean>,
>>>
>>> then BooleanMBR<Boolean> wins, yes ?
>>
>> It depends on the values for @Consumes. If <Object> has text/plain and
>> <Boolean> has */*, then no. Again see the sentence extracted from the
>> spec above.
>
> There is only conclusion I can draw from it given what I've said above:
> the keys used to select MBRs are the same as the ones used to select
> MBWs, but these keys are used in a different order. In case of MBRs, it
> is obvious to me the media type is a primary key, the provider generic
> type - a secondary one, vice-versa for MBW.
>
> This can explain why
>
> Consumes(*/*)
> MBR<B>
>
> wins against
>
> Consumes(*/*)
> MBR<Object>
>
> but
>
> Consumes(*/*)
> MBR<B>
>
> loses against
>
> Consumes(text/plain)
> MBR<Object>
>
>
> Am I still on the wrong track ?
>
> Cheers, Sergey
>
>>
>> — Santiago
>>
>> PS: We can follow up on Skype if you prefer.
>>
> Sure, I'll try to get in touch later today, thanks :-)
>
>>
>