users@jax-rs-spec.java.net

[jax-rs-spec users] [jsr339-experts] Re: Re: HEADS-UP: Revise MBR selection mechanism?

From: Bill Burke <bburke_at_redhat.com>
Date: Thu, 24 May 2012 10:16:22 -0400

On 5/24/12 5:43 AM, Sergey Beryozkin wrote:
> On 23/05/12 18:14, Marek Potociar wrote:
>>
>> On May 23, 2012, at 6:43 PM, Bill Burke wrote:
>>
>>> On 5/23/12 12:04 PM, Marek Potociar wrote:
>>>>
>>>> On May 23, 2012, at 4:49 PM, Sergey Beryozkin wrote:
>>>>
>>>>> On 23/05/12 15:37, Marek Potociar wrote:
>>>>>> Hello experts,
>>>>>>
>>>>>> please review the following issue
>>>>>> http://java.net/jira/browse/JAX_RS_SPEC-187 and provide your
>>>>>> feedback.
>>>>>> Apparently this may be considered a BW-breaking change. If we make
>>>>>> it,
>>>>>> the implementations may need to provide a BW compatibility switch if
>>>>>> necessary.
>>>>>
>>>>> I do not understand that issue at all. The resource method returns
>>>>> InputStream therefore the MBW supporting InputStream must win
>>>>
>>>> Not necessarily - see the section of the spec referenced from the
>>>> issue - 4.2.2, step 4.
>>>>
>>>> The response media types takes precedence over the generic MBW type,
>>>> so if the response is "application/json" InputStream and a custom
>>>> Jackson JSON provider claims to support any java type (Object) for
>>>> "application/json",
>
>>>> it will win over the default InputStream provider that supports
>>>> InputStream for any media type.
>
> No, it will only win over default InputStream provider in case of
> Accept: application/json, for all other types the default one wins.
>
>
> That is however most likely not what the user wanted.
>>>>
>>>> The issue suggests to reverse this ordering.
>>>>
>>>> Also, the spec mandates that custom providers should always take
>>>> precedence over the default ones, but the spec is not clear whether
>>>> this should really be a primary or tertiary key. For MBW the issue
>>>> suggests that the right thing would be to explicitly define it as a
>>>> tertiary key.
>
> I'm nervous this is going to break the fundamental expectation that the
> custom provider wins.
>
> I think what is suggested is a workaround to manage catch-all providers
> that return true in readFrom or writeTo.
>
> At this moment of time I believe that the right course of action is to
> recommend the custom provider implementations to be more selective, ex,
> providers managing POJOs should exclude InputStream.class, but...
>
>>>>
>>>>
>>>
>>> To have to separate implementations (Jersey and Resteasy) come to the
>>> same separate conclusion I think gives pretty good reason to change
>>> the algorithm.
>>>
>>> Beyond InputStream, really any "low-level" type would have to be
>>> treated as a special case in the current matching algorithm:
>>> InputStream, Reader, File, StreamingOutput, String, char[], and
>>> byte[]. Plus, if a user has a specific MBR/MBW for a specific type,
>>> then they probably want that MBR/MBW called no matter what. You can't
>>> get any more specific than the Java type.
>
> I don't have a good answer to it.
> Still, I believe that these are not main-stream cases at all.
> Having a situation where a custom JSON/etc provider helping the service
> dealing with POJOS, where the service also return byte[], etc of the
> same media type is rare and seems unusual.
>
> Why one would have a service with two methods, one returning Book &
> another - InputStream ? Just get two separate endpoints if that is
> really needed. I guess that can be tricky to do in cases where the
> scanning gets the providers loaded and visible to all the web
> application, but the scanning is an optional feature.
>
> IMHO, The following course of action:
> - recommend the custom providers to be as specific as possible in
> readFrom/writeTo
> - get a user to register a custom provider for InputStream, byte[],
> String supporting a specific media type when really needed - it's very
> very easy.
>
> needs to be reviewed alongside the proposed change of the algorithm.
>
> In this case the control is for the user to assert. In the proposed
> change we are making an assumption that this is user will not want, etc,
> based on the case centered around InputStream or primitive classes.
>
> Consider the case where a custom provider supports reading both Document
> and DOMSource, example, in order to consolidate the way DOM is
> processed. Its generic type is Object.
>

That is really bad practice, to have one MBR/MBW service multiple Java
types. But maybe I'm not understanding your example?



Maybe this sheds more light?

More specific types are used as the first sort key. So, if your Java
type matches exactly to the generic type parameter of the MBR/MBW, it
will be chosen over every other one.


@Consumes("application/json")
public class JsonReader implements MessageBodyReader<Object> {} //builtin

@Consumes("*/*")
public class InputStreamReader implemetns MessageBodyReader<InputStream>
{} // builtin


@Consumes("application/json")
public class JsonInputStreamReader implements
MessageBodyReader<InputStream> {} // application provided provider


Consider this method:

@POST
public void post(InputStream is);


Content-Type: application/json, JsonInputStream gets picked
Content-Type: text/plain, InputStreamReader gets picked

Make more sense?


-- 
Bill Burke
JBoss, a division of Red Hat
http://bill.burkecentral.com