Re: JAX-RS and generics

2009-09-07 Thread Sergey Beryozkin

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)

type - the class of object that is to be written.

So I don't think we should pass Object.class for MessageBodyWriterObject. If one would like to avoud doing casts during testing 
then it should be just  MessageBodyWriterBook and I'm pretty sure the runtime will pass Book.class.


Cheers, Sergey



On Sat, Sep 5, 2009 at 1:57 PM, Benson Margulies bimargul...@gmail.comwrote:


JAX-RS defines two fundamental interfaces: MessageBodyReaderT and
MessageBodyWriterT, 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 MessageBodyXT, not MessageBodyXObject.



Allow me to modulate this claim. I thought about it some more.

If you want to define a class as 'implements MessageBodyXObject', fine.
However, the right thing to pass to the ClassT 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 ClassT in a way that requires constant
@SupressWarnings(unchecked) if the base is MessageBodyXObject.

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,

AegisElementProviderBook

then implemented interface comes up as MessageBodyReaderT, not
MessageBodyReaderBook. 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.







Re: JAX-RS and generics

2009-09-07 Thread Sergey Beryozkin

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 MessageBodyWriterObject but it would stiill cause warning in the user 
test code


I can agree that implementing MessageBodyWriterObject delegates the type-safety checks to the actual provider and thus makes that 
T thing useless. But for providers choosing to implement MessageBodyWriterBook 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 
MessageBodyWriterObject - but I'm afraid it will turn the bunch of user providers out there broken...


thanks, Sergey

- Original Message - 
From: Benson Margulies bimargul...@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(ClassT type, whatever)

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

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

So, if AegisProvider implements MessageBodyReaderObject, 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 MessageBodyReaderT, you then AegisProviderBook 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 sbery...@progress.comwrote:



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 MessageBodyWriterObject.
If one would like to avoud doing casts during testing then it should be just
 MessageBodyWriterBook and I'm pretty sure the runtime will pass
Book.class.

Cheers, Sergey



 On Sat, Sep 5, 2009 at 1:57 PM, Benson Margulies bimargul...@gmail.com

wrote:

 JAX-RS defines two fundamental interfaces: MessageBodyReaderT and

MessageBodyWriterT, 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 MessageBodyXT, not MessageBodyXObject.



Allow me to modulate this claim. I thought about it some more.

If you want to define a class as 'implements MessageBodyXObject', fine.
However, the right thing to pass to the ClassT 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 ClassT in a way that requires constant
@SupressWarnings(unchecked) if the base is MessageBodyXObject.

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,

AegisElementProviderBook

then implemented interface comes up as MessageBodyReaderT, not
MessageBodyReaderBook. 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.










Re: JAX-RS and generics

2009-09-06 Thread Benson Margulies
There are two ways to look at this. From the point of view of a 'provider
bean', I can believe that a non-generic class is attractive. Maybe
essential. Maybe my change to the Aegis providers was thus a mistake.

From the point of view of a clean API callable without suppressing any
warnings, on the other hand, the generic nature of the JAX-RS APIs makes
them ugly to reduce to non-generic types.



On Sun, Sep 6, 2009 at 6:09 PM, Sergey Beryozkin sbery...@progress.comwrote:

 Hi

 I'm concerned it may be not be portable, that is the providers which
 work with other JAXRS implementations will end up being unusable in CXF.

 You may be right but I've seen the number of providers which implement
 MessageBodyXObject and then cast them internally. For ex to Feed or
 Entry, etc.

 Let me ask a question on the jaxrs users list...
 Cheers, Sergey

 -Original Message-
 From: Benson Margulies [mailto:bimargul...@gmail.com]
 Sent: 06 September 2009 03:15
 To: CXF Dev
 Subject: Re: JAX-RS and generics

 On Sat, Sep 5, 2009 at 1:57 PM, Benson Margulies
 bimargul...@gmail.comwrote:

  JAX-RS defines two fundamental interfaces: MessageBodyReaderT and
  MessageBodyWriterT, 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 MessageBodyXT, not MessageBodyXObject.
 

 Allow me to modulate this claim. I thought about it some more.

 If you want to define a class as 'implements MessageBodyXObject',
 fine.
 However, the right thing to pass to the ClassT 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 ClassT in a way that requires constant
  @SupressWarnings(unchecked) if the base is MessageBodyXObject.
 
  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,
 
  AegisElementProviderBook
 
  then implemented interface comes up as MessageBodyReaderT, not
  MessageBodyReaderBook. 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.
 



Re: JAX-RS and generics

2009-09-05 Thread Benson Margulies
On Sat, Sep 5, 2009 at 1:57 PM, Benson Margulies bimargul...@gmail.comwrote:

 JAX-RS defines two fundamental interfaces: MessageBodyReaderT and
 MessageBodyWriterT, 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 MessageBodyXT, not MessageBodyXObject.


Allow me to modulate this claim. I thought about it some more.

If you want to define a class as 'implements MessageBodyXObject', fine.
However, the right thing to pass to the ClassT 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 ClassT in a way that requires constant
 @SupressWarnings(unchecked) if the base is MessageBodyXObject.

 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,

 AegisElementProviderBook

 then implemented interface comes up as MessageBodyReaderT, not
 MessageBodyReaderBook. 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.