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 :-)
>