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

From: Sergey Beryozkin <>
Date: Thu, 2 Apr 2015 14:34:20 +0100

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


wins against




loses against


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