jsr343-experts@jms-spec.java.net

[jsr343-experts] Re: (JMS_SPEC-101) New method Message.getPayload(Class<T> c)

From: John D. Ament <john.d.ament_at_gmail.com>
Date: Tue, 23 Oct 2012 20:22:50 -0400

Nigel,

That byte[].class thing seems new to me. Anyways yes it does apparently
work so thank you for fixing my mis-step.

So far it's looking good. One thing that does stick out to me is that JPA
has a similar method on the EntityManager interface - unwrap(Class c).
http://docs.oracle.com/javaee/6/api/javax/persistence/EntityManager.html#unwrap(java.lang.Class)
- This
class allows access to lower level objects. I'm wondering if a better for
the method is "unwrapPayload," or something along those lines. Are we
"unwrapping" the underlying payload in this case (for example, maybe the
implementation needs to deserialize the object on this method's
invocation?).

I know you mentioned the JMSConsumer class needing change as well, is there
any benefit to adding a "setPayload" to the Message interface to be able to
set the payload directly and receive a class cast exception if it wasn't
the right type? I also experimented with this a while ago - if the Message
interface was parameterized, TextMessage could extend Message<String> so
that the expected type would be a String (compilation wise), ObjectMessage
could extend Message<Serializable> and so forth. I only got mixed
reactions to this idea, so not sure if it actually is a big benefit or just
a little thing that may make a few things easier. StreamMessage was the
one I ended up getting stuck on. Since we're essentially using a
DataInputStream & DataOutputStream could we just use those as the types
perhaps (and allow the implementation to "fix" how they're handled
internally?)

One other question - just because I have it on the top of my head from
prior work, if I were using WebLogic as my JMS implementation and the
underlying message type was their XMLMessage type; can I pass in
org.w3c.dom.Document.class to my Message object and have it return the
appropriate result? Or is that too container specific of a question/up to
the implementer?

Thanks,

John

On Tue, Oct 23, 2012 at 2:01 PM, Nigel Deakin <nigel.deakin_at_oracle.com>wrote:

> On 23/10/2012 15:07, John D. Ament wrote:
>
>> Ok, so looking throught it a bit more I think we have a few issues
>>
>> 1. You cannot pass byte[].class to the method (that's not a valid class).
>> I think we need a work around here.
>>
>
> You can, actually :-)
>
>
> 2. I think the case should simply pass when Class.isAssignableFrom(**Otherclass.class)
>> is passed.
>>
>
> I like this general approach: the implementation extracts the payload,
> calls isAssignableFrom to see if this can be cast to the required return
> type, and then performs the cast.
>
> (If we adopt this approach we should change the JMSConsumer receivePayload
> methods to work in the same way)
>
>
> > So if I pass in
>
>> CharSequence.class, I should be able to get back a CharSequence in the
>> following cases:
>>
>
> - The message is a TextMessage, the underlying result is a String back
>> (returned as a CharSequence instead)
>>
> >
>
>> - The message is an ObjectMessage, the underlying type is an
>> implementation of CharSequence (StringBuilder,
>> StringBuffer, String).
>>
>
> Yes.
>
>
> IMHO from the initial messages about this method it seemed like the goal
>> was to make the client ignorant (lack of a
>> better term) to the fact that it's a text message or object message or
>> map message.
>>
>
> > Also passing in Object.class should
>
>> just return the payload, regardless of type, as long as it's not a
>> StreamMessage.
>>
>> Thoughts?
>>
>
> Yes, though in this case the returned type would be an Object, so the
> application would need to perform a cast to do anything useful with the
> payload.
>
> Here's an updated javadoc. More views please!
>
> /**
> * Returns the messages's payload, which must be assignable to the
> specified
> * type. If the message has no payload then null is returned. This
> method
> * may be used to obtain the payload of any type of message except
> for
>
> * <tt>StreamMessage</tt>.
> *
> * @param c
> * The class of the payload.
> * <br/>
>
> * If the message is a <code>TextMessage</code> then
> this should
> * be set to <code>String.class</code> or any other
> class to
> * which a String is assignable.
> * <br/>
>
> * If the message is a <code>ObjectMessage</code> then
> this
> * should be set to <code>java.io.Serializable.**class</code>
> or
> * any other class to which the payload is assignable.
>
> * <br/>
> * If the message is a <code>MapMessage</code> then
> this should
> * be set to <code>java.util.Map.class</**code>.
> * <br/>
>
> * If the message is a <code>BytesMessage</code> then
> this should
> * be set to <code>byte[].class</code>.
> * <br/>
> * If the message is a <code>StreamMessage</code>, or
> the payload
> * cannot be assigned to the specified type a
>
> * <code>MessageFormatException</**code> will be thrown
> *
> * @return the messages's payload
> *
> * @exception JMSException
> * if the JMS provider fails to get the payload due
> to some
> * internal error.
> * @exception MessageFormatException
> * if the message is a <code>StreamMessage</code>,
> or the
> * payload cannot be assigned to the specified
> type, or the
> * message is an ObjectMessage and object
> deserialization
>
> * fails.
> * @Exception MessageNotReadableException - if the message is a
> BytesMessage
> * and the message is in write-only mode.
> */
> <T> T getPayload(Class<T> c) throws JMSException;
>
> Nigel
>