cxf-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Sergey Beryozkin" <sbery...@progress.com>
Subject Re: JAX-RS and generics
Date Mon, 07 Sep 2009 12:33:34 GMT
Hi Benson

In MessageBodyWriter.writeTo() it's actually Class<?> which is in the signature. And
there's no return value.

We could've implemented just MessageBodyWriter as opposed to MessageBodyWriter<Object>
but it would stiill cause warning in the user 
test code....

I can agree that implementing MessageBodyWriter<Object> delegates the type-safety checks
to the actual provider and thus makes that 
<T> thing useless. But for providers choosing to implement MessageBodyWriter<Book>
the runtime will now ensure the class of the 
object to be written is assignable to Book.class (now that we've implemented the message body
provides sorting requirement from 
JAXRS 1.1).

Please don't get me wrong, may be it would be the best option indeed to go ahead with passing
Object.class 
MessageBodyWriter<Object> - but I'm afraid it will turn the bunch of user providers
out there broken...

thanks, Sergey

----- Original Message ----- 
From: "Benson Margulies" <bimargulies@gmail.com>
To: <dev@cxf.apache.org>
Sent: Monday, September 07, 2009 1:06 PM
Subject: Re: JAX-RS and generics


Sergey,

With Java generics, there's a pattern:

   <T> public T gloop(Class<T> type, whatever)

That pattern requires that you pass in the class of what you expect to get
out.

If XXXProvider implements MessageBodyReader<T>, then it must have a
implement the read API against the same T. You can't, legitimately, cast it
to MessageBodyReader<Book>.

So, if AegisProvider implements MessageBodyReader<Object>, and you want to
write clean code that does not get warnings, you have to write:

Object o = p.read(Object.class, ...)

If it implements MessageBodyReader<T>, you then AegisProvider<Book> does

  Book b = p.read(Book.class, ...)

Now, if the people who invented JAX-RS have decided to ignore this pattern
and force us to write code that needs @SuppressWarning("unchecked"), well,
I'm sad but I'll stop sending email. Since my generic AegisProvider passes
tests, however, ...




On Mon, Sep 7, 2009 at 5:50 AM, Sergey Beryozkin <sberyozk@progress.com>wrote:

>
> https://jsr311.dev.java.net/nonav/javadoc/javax/ws/rs/ext/MessageBodyWriter.html#writeTo(T,%20java.lang.Class,%20java.lang.reflect.Type,%20java.lang.annotation.Annotation[],%20javax.ws.rs.core.MediaType,%20javax.ws.rs.core.MultivaluedMap,%20java.io.OutputStream)<https://jsr311.dev.java.net/nonav/javadoc/javax/ws/rs/ext/MessageBodyWriter.html#writeTo%28T,%20java.lang.Class,%20java.lang.reflect.Type,%20java.lang.annotation.Annotation%5B%5D,%20javax.ws.rs.core.MediaType,%20javax.ws.rs.core.MultivaluedMap,%20java.io.OutputStream%29>
>
> type - the class of object that is to be written.
>
> So I don't think we should pass Object.class for MessageBodyWriter<Object>.
> If one would like to avoud doing casts during testing then it should be just
>  MessageBodyWriter<Book> and I'm pretty sure the runtime will pass
> Book.class.
>
> Cheers, Sergey
>
>
>
>  On Sat, Sep 5, 2009 at 1:57 PM, Benson Margulies <bimargulies@gmail.com
>> >wrote:
>>
>>  JAX-RS defines two fundamental interfaces: MessageBodyReader<T> and
>>> MessageBodyWriter<T>, and providers implement.
>>>
>>> I claim that GENERIC providers that work for any object (like those
>>> corresponding to data bindings) should, themselves, be GENERIC, and
>>> implement MessageBodyX<T>, not MessageBodyX<Object>.
>>>
>>>
>> Allow me to modulate this claim. I thought about it some more.
>>
>> If you want to define a class as 'implements MessageBodyX<Object>', fine.
>> However, the right thing to pass to the Class<T> argument will ALWAYS be
>> Object.class. If you want to cue in the code to the sort of object in
>> flight, use the Type argument further down the parameter list.
>>
>>
>>
>>> I claim this because the whole API structure of MessageBodyX assumed
>>> this.
>>> It uses Class<T> in a way that requires constant
>>> @SupressWarnings("unchecked") if the base is MessageBodyX<Object>.
>>>
>>> To put my money where my mouth is, as it were, I implemented this for the
>>> Aegis providers. When I did this, I discovered that the JAX-RS runtime
>>> code
>>> couldn't handle generic type providers. When the provider type is, say,
>>>
>>> AegisElementProvider<Book>
>>>
>>> then implemented interface comes up as MessageBodyReader<T>, not
>>> MessageBodyReader<Book>. So it is a TypeVariable, not a class or a
>>> ParameterizedType.
>>>
>>> I fixed the provider selection code to cope, but I didn't write the
>>> additionally complex code to look at bounds and insist that if there is a
>>> bound the type at hand be within it.
>>>
>>>
>>
>


Mime
View raw message