Re: JAX-RS and generics
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
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
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
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.