users@jms-spec.java.net

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

From: Chris Barrow <chris.barrow_at_kaazing.com>
Date: Sun, 04 Nov 2012 01:08:42 -0700

Hi Nigel,

I would vote for getType returning an enum of {BYTES, MAP, OBJECT,
STREAM, TEXT} as I mentioned in the thread below, because it makes it
easier to write generic code to handle any message (using a switch
statement), and getBody. I do not believe isBodyAssignableTo is worth
including.

thanks,
Chris

On 10/29/2012 3:07 AM, Nigel Deakin wrote:
> Chris,
>
> On 26/10/2012 19:43, Chris Barrow wrote:
>> Hi Nigel,
>>
>> Amended Javadoc looks fine.
>>
>> I see what you mean about using isBodyAssignableTo for
>> ObjectMessages, but I still don't see the necessity for it. Users
>> can get the object as a Serializable and do instanceof checks or
>> getClass or test themselves for assignability using
>> reflection if they really want to cast it. The getBody method would
>> not be able to do any useful data type conversion
>> anyway ( as is done for example for message properties and MapMessage
>> values, which is only possible because they are
>> limited to be one of a narrow set of types).
>
> getBody is simply a convenience method intended to avoid the need for
> two casts (in the case of ObjectMessage, where you need to cast
> Message to ObjectMessage and then cast Serializable to the actual
> type) or one cast (where you need to cast Message to one of the other
> message types).
>
> Do you think this would be useful? (Would a corresponding setBody() be
> useful?)
>
> isBodyAssignableTo offers a way to find out whether getBody would
> succeed or not. It's an alternative to doing instanceof on the Message
> followed in the case of an ObjectMessage by instanceof on the
> Serializable.
>
> I quite like getBody, though as I mentioned I am less convinced about
> the need for isBodyAssignableTo.
>
>> To put it another way, as a programmer I do not believe I would ever
>> use isBodyAssignableTo, but I would certainly use
>> getType to switch to process different message types differently.
>
> Thanks for your comment. When you've decided your position, can you
> please make a comment to the user list? This makes it easier for me to
> publicly review feedback.
>
> Thanks,
>
> Nigel
>
>
>> thanks,
>> Chris
>>
>> On 10/26/2012 10:55 AM, Nigel Deakin wrote:
>>> Chris,
>>>
>>> On 26/10/2012 17:40, Chris Barrow wrote:
>>>> Hi Nigel,
>>>>
>>>> Rather than isBodyAssignableTo, which seems cumbersome, how about
>>>> just providing a method getType returning an enum of
>>>> {BYTES, MAP, OBJECT, STREAM, TEXT}? This allows developers to write
>>>> elegant switch statements to handle cases where
>>>> there can be multiple types of message:
>>>> switch(message.getType()) {
>>>> case BYTES:
>>>> ...
>>>> case MAP:
>>>> ...
>>>> }
>>>>
>>>> Of course the new method would have to be carefully distinguished
>>>> from existing method getJMSType. But since it returns
>>>> an enum instead of a string that should avoid any accidental misuse.
>>>
>>> This would offer a way of finding out the message type
>>> (BytesMessage, ObjectMessage etc) without using instanceof.
>>>
>>> isBodyAssignableTo would do something slightly different as it also
>>> tell you whether the body of an ObjectMessage
>>> could be cast to a specified type. It is intended to match the
>>> behaviour of getBody, which not only allows to, say,
>>> extract the String from a TextMessage but also extract the body of
>>> an ObjectMessage *and* cast it to the specified type.
>>>
>>> We could add getType in addition to this (if we were able to avoid
>>> confusion with the existing getJMSType() method).
>>> However I hope that methods such as getBody would make it much less
>>> necessary to know the type of a message that has
>>> been received.
>>>
>>>> Javadoc, it looks clear, nice job. Perhaps use the word "must"
>>>> instead of "should" in the description of the c parameter
>>>> to tighten it up even more?
>>>
>>> Thanks. How about this:
>>>
>>> * @param c
>>> * The type to which the message body will be assigned. <br/>
>>> * If the message is a <code>TextMessage</code> then this must
>>> * be set to <code>String.class</code> or another class to which
>>> * a String is assignable. <br/>
>>> * If the message is a <code>ObjectMessage</code> then this
>>> * must be set to <code>java.io.Serializable.class</code> or
>>> * another class to which the payload is assignable. <br/>
>>> * If the message is a <code>MapMessage</code> then this must
>>> * be set to <code>java.util.Map.class</code>. <br/>
>>> * If the message is a <code>BytesMessage</code> then this must
>>> * be set to <code>byte[].class</code>. The
>>> * <code>BytesMessage</code> must not be in write-only mode.
>>>
>>> Nigel
>>>
>>>>
>>>> Chris
>>>>
>>>> On 10/26/2012 7:00 AM, Nigel Deakin wrote:
>>>>> http://java.net/jira/browse/JMS_SPEC-101
>>>>> New method Message.getBody(Class<T> c)
>>>>>
>>>>> Following preceding discussions, I have changed the name of this
>>>>> method to getBody and polished the javadoc comment
>>>>> slightly. The updated API doc can be seen below and also at
>>>>> http://jms-spec.java.net/2.0-SNAPSHOT/apidocs/javax/jms/Message.html#getBody%28java.lang.Class%29
>>>>>
>>>>>
>>>>> In addition, I have taken up John A's suggestion and drafted an
>>>>> API doc for a method isBodyAssignableTo which can be
>>>>> used to find out whether a subsequent call to getBody would fail
>>>>> because of an incompatible type. The APi docs can be
>>>>> seen below and also at
>>>>> http://jms-spec.java.net/2.0-SNAPSHOT/apidocs/javax/jms/Message.html#isBodyAssignableTo%28java.lang.Class%29
>>>>>
>>>>>
>>>>> I think getBody() would be a nice addition to the API and is a
>>>>> useful complement to the new receivePayload methods. It
>>>>> would remove the need to cast a Message to a specific subtype in
>>>>> other cases such as in a MessageListener. However I
>>>>> would still welcome your views on this.
>>>>>
>>>>> I am less sure about isBodyAssignableTo. It is simple enough to
>>>>> define, but I'm not totally convinced there's a good
>>>>> case for adding it. Is this a useful complement to getBody, or is
>>>>> it simply bloat?
>>>>>
>>>>> So please express your views on the following:
>>>>>
>>>>> 1. Do you support the addition of Message.getBody() as defined below?
>>>>>
>>>>> 2. Do you support the addition of Message.isBodyAssignableTo() as
>>>>> defined below?
>>>>>
>>>>> Thanks,
>>>>>
>>>>> Nigel
>>>>>
>>>>> Here are those javadocs:
>>>>>
>>>>>
>>>>> /**
>>>>> * Returns the message body as an object of the specified type. The
>>>>> message
>>>>> * body must be capable of being assigned to the specified type.
>>>>> This means
>>>>> * that the specified class or interface must be either the same
>>>>> as, or a
>>>>> * superclass or superinterface of, the class of the message body.
>>>>> This
>>>>> * method may be used to obtain the body of any type of message
>>>>> except for
>>>>> * <tt>StreamMessage</tt>. If the message has no body then null is
>>>>> returned.
>>>>> *
>>>>> * @param c
>>>>> * The type to which the message body should be assigned. <br/>
>>>>> * If the message is a <code>TextMessage</code> then this should
>>>>> * be set to <code>String.class</code> or another 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
>>>>> * another 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>. The
>>>>> * <code>BytesMessage</code> must not be in write-only mode.
>>>>> *
>>>>> * @return the message body
>>>>> *
>>>>> * @exception JMSException
>>>>> * if the JMS provider fails to get the message body due to
>>>>> * some internal error.
>>>>> * @exception MessageFormatException
>>>>> * if the message is a <code>StreamMessage</code>, or the
>>>>> * message body cannot be assigned to the specified type, or
>>>>> * the message is an <code>ObjectMessage</code> and object
>>>>> * deserialization fails.
>>>>> * @exception MessageNotReadableException
>>>>> * if the message is a <code>BytesMessage</code> and the
>>>>> * message is in write-only mode.
>>>>> */
>>>>> <T> T getBody(Class<T> c) throws JMSException;
>>>>>
>>>>> /**
>>>>> * Returns whether the message body is capable of being assigned to
>>>>> the
>>>>> * specified type. If this method returns true then a subsequent
>>>>> call to the
>>>>> * method <code>getBody</code> with the same type argument would
>>>>> not throw a
>>>>> * MessageFormatException.
>>>>> * <p>
>>>>> * If the message is a <code>StreamMessage</code> then false is
>>>>> returned. If
>>>>> * the message is a <code>ObjectMessage</code> and object
>>>>> deserialization
>>>>> * fails then false is returned. If the message has no body then
>>>>> true is
>>>>> * returned.
>>>>> *
>>>>> * @param c
>>>>> * The specified type <br/>
>>>>> * If the message is a <code>TextMessage</code> then method will
>>>>> * only return true if this parameter is set to
>>>>> * <code>String.class</code> or another class to which a String
>>>>> * is assignable. <br/>
>>>>> * If the message is a <code>ObjectMessage</code> then this
>>>>> * method will only return true if this parameter is set to
>>>>> * <code>java.io.Serializable.class</code> or another class to
>>>>> * which the payload is assignable. <br/>
>>>>> * If the message is a <code>MapMessage</code> then this method
>>>>> * will only return true if this parameter is set to
>>>>> * <code>java.util.Map.class</code>. <br/>
>>>>> * If the message is a <code>BytesMessage</code> then this this
>>>>> * method will only return true if this parameter is set to
>>>>> * <code>byte[].class</code>.
>>>>> *
>>>>> * @return whether the message body is capable of being assigned to
>>>>> the
>>>>> * specified type
>>>>> *
>>>>> * @exception JMSException
>>>>> * if the JMS provider fails to return a value due to some
>>>>> * internal error.
>>>>> * @exception MessageNotReadableException
>>>>> * if the message is a <code>BytesMessage</code> and the
>>>>> * message is in write-only mode.
>>>>> */
>>>>> boolean isBodyAssignableTo(Class c) throws JMSException;
>>>>
>>