JMS message types and conversion
The choice of message type affects your approach to message conversion. The interaction of message conversion and message type is described for the JMS message types, JMSObjectMessage, JMSTextMessage, JMSMapMessage, JMSStreamMessage, and JMSBytesMessage.
JMSObjectMessage
JMSObjectMessage contains
one object, and any objects that it references, serialized into a
byte stream by the JVM. Text is serialized into UTF-8
,
and limited to strings or character arrays of no more than 65534 bytes.
An advantage of JMSObjectMessage is that applications
are not involved in any data conversion issues as long as they use
only the methods and attributes of the object. JMSObjectMessage provides
data conversion for complex objects without the application programmer
considering how to encode an object in a message. The disadvantage
of using JMSObjectMessage is it can be exchanged
only with other JMS applications. By choosing one of the other JMS
message types, it is possible to exchange JMS messages with non-JMS
applications.
Sending and receiving a JMSObjectMessage shows a String object being exchanged in a message.
A JMS client application can receive a JMSObjectMessage only in a message that has a JMS-style body. The destination must specify a JMS style body.
JMSTextMessage
JMSTextMessage contains
a single text string. When a text message is sent, the text Format
is
set to "MQSTR "
, WMQConstants.MQFMT_STRING
.
The CodedCharacterSetId
of the text is set to the
coded character set identifier defined for its destination. The text
is encoded into the CodedCharacterSetId
by WebSphere® MQ. The CodedCharacterSetId
and Format
fields
are either set in the message descriptor, MQMD
, or
into the JMS fields in an MQRFH2
. If the message
is defined as having an WMQ_MESSAGE_BODY_MQ
message
body style, or the body style is unspecified, but the target destination
is WMQ_TARGET_DEST_MQ
, then the message descriptor
fields are set. Otherwise the message has a JMS RFH2
and
the fields are set in the fixed part of the MQRFH2
.
An application can override the coded character set identifier defined for a destination. It must set the message property JMS_IBM_CHARACTER_SET to a coded character set identifier; see the example in Sending and receiving a JMSTextmessage.
When the JMS client calls the consumer.receive method
queue manager conversion is optional. Queue manager conversion is
enabled by setting the destination property WMQ_RECEIVE_CONVERSION
to WMQ_RECEIVE_CONVERSION_QMGR
.
The queue manager converts the text message from the JMS_IBM_CHARACTER_SET
specified
for the message before transferring the message to the JMS client.
The character set of the converted message is 1208
, UTF-8
,
unless the destination has a different WMQ_RECEIVE_CCSID
.
The CodedCharacterSetId
in the message that refers
to the JMSTextMessage is updated to the target
character set ID. The text is decoded from the target character set
into Unicode by the getText method; see the example
in Sending and receiving a JMSTextmessage.
A JMSTextMessage can
be sent in an MQ-style message body, without a JMS MQRFH2
header.
The value of the destination attributes, WMQ_MESSAGE_BODY and WMQ_TARGET_DEST determine
the message body style, unless overridden by the application. The
application can override the values set on the destination by calling destination.setMessageBodyStyle(WMQConstants.WMQ_MESSAGE_BODY_MQ) or destination.setTargetClient(WMQConstants.WMQ_TARGET_DEST_MQ).
If
you send a JMSTextMessage with an MQ style body
by sending it to a destination with WMQ_MESSAGE_BODY set
to WMQ_MESSAGE_BODY_MQ, you cannot receive it as
a JMSTextMessage from the same destination. All
messages received from a destination with WMQ_MESSAGE_BODY set
to WMQ_MESSAGE_BODY_MQ are received as a JMSBytesMessage.
If you try to receive the message as a JMSTextMessage it
causes an exception, ClassCastException: com.ibm.jms.JMSBytesMessage
cannot be cast to javax.jms.TextMessage
.
It is generally
better to use the WMQ_TARGET_DEST property to control
whether a JMSTextMessage is sent with an MQ or
JMS body style. You can then receive the message from a destination
that has either WMQ_TARGET_DEST set to WMQ_TARGET_DEST_MQ
or WMQ_TARGET_DEST_JMS
. WMQ_TARGET_DEST has
no effect on the receiver.
JMSMapMessage and JMSStreamMessage
These two JMS message types are similar. You can read and write primitive types to the messages using methods based on the DataInputStream and DataOutputStream interfaces; see Table of message types and conversion types. The details are described in JMS client message conversion and encoding. Each primitive is tagged; see The JMS message body.
Numeric data is read and written to the message encoded as XML text. No reference is made to the destination property, JMS_IBM_ENCODING. Text data is treated the same way as text in a JMSTextMessage. If you were to look at the message contents created by the example in Figure 5, all the message data would be in EBCDIC as it was sent with a character set value of 37.
You can send multiple items in a JMSMapMessage or JMSStreamMessage.
You
can retrieve the individual items of data by name from a JMSMapMessage,
or by position from a JMSStreamMessage. Each item
is decoded when a get or read method is called using the CodedCharacterSetId
value
stored in the message. If the method used to retrieve the item returns
a different type to the type that was sent, the type is converted.
If the type cannot be converted, an exception is thrown. See Class JMSStreamMessage for details. The example
in Sending data in a JMSStreamMessage and JMSMapMessage illustrates type conversion,
and getting the JMSMapMessage contents out of sequence.
The MQRFH2.format
field
for the JMSMapMessage and JMSStreamMessage is
set to
. If the destination
property WMQ_RECEIVE_CONVERSION is set to MQSTR
WMQ_RECEIVE_CONVERSION_QMGR
,
the message data is converted by the queue manager before being sent
to the JMS client. The MQRFH2.CodedCharacterSetId
of
the message is the WMQ_RECEIVE_CCSID
of the destination.
The MQRFH2.Encoding
is Native
. If WMQ_RECEIVE_CONVERSION is WMQ_RECEIVE_CONVERSION_CLIENT_MSG
the CodedCharacterSetId
and Encoding
of
the MQRFH2
is the value set by the sender.
A JMS client application can receive a JMSMapMessage or JMSStreamMessage only in a message that has a JMS-style body, and from a destination that does not specify an MQ style body.
JMSBytesMessage
A JMSBytesMessage can contain multiple primitive types. You can read and write primitive types to the messages using methods based on the DataInputStream and DataOutputStream interfaces; see Table of message types and conversion types. The details are described in JMS message types and conversion.
The
encoding of numeric data in the message is controlled by the value
of JMS_IBM_ENCODING
that is set before writing numeric
data to the JMSBytesMessage. An application can
override the default Native
encoding defined for JMSBytesMessage by
setting the message property JMS_IBM_ENCODING.
Text
data can be read and written in UTF-8
using the readUTF and writeUTF,
or in Unicode using the readChar and writeChar methods.
There are no methods that use CodedCharacterSetId
.
Alternatively, the JMS client can encode and decode text into bytes
using the Charset class. It transfers the bytes
between the JVM and message without the WebSphere MQ classes for JMS performing
any conversion; see Sending and receiving text in a JMSBytesMessage.
A JMSBytesMessage sent
to an MQ application is typically sent in an MQ-style message body,
without a JMS MQRFH2
header. If it is sent to a JMS
application, the message body style is typically JMS. The value of
the destination attributes, WMQ_MESSAGE_BODY and WMQ_TARGET_DEST determine
the message body style, unless overridden by the application. The
application can override the values set on the destination by calling destination.setMessageBodyStyle(WMQConstants.WMQ_MESSAGE_BODY_MQ) or destination.setTargetClient(WMQConstants.WMQ_TARGET_DEST_MQ).
If
you send a JMSBytesMessage with an MQ style body,
you can receive the message from a destination that defines either
an MQ or a JMS message body style. If you send a JMSBytesMessage with
a JMS style body, then you must receive the message from a destination
that defines a JMS message body style. If you do not, the MQRFH2
is
treated as part of the user message data, which might not be what
you are expecting.
Whether a message has an MQ or a JMS body style, the way it is received is not affected by setting WMQ_TARGET_DEST.
The
message might be transformed later, by the queue manager, if a Format
is
supplied for the message data, and queue manager data conversion is
enabled. Do not use the format field for anything other than specifying
the format of the message data, or leave it blank, MQConstants.MQFMT_NONE
You can send multiple items in a JMSBytesMessage. Each numeric item is converted when the message is sent using the encoding defined for the message.
You can retrieve the individual items
of data from JMSBytesMessage. Call read methods
in the same order as the write methods were called to create the message.
Each numeric item is converted when the message is called using the Encoding
value
stored in the message.
Unlike JMSMapMessage and JMSStreamMessage, JMSBytesMessage contains only data written by the application. No additional data is stored in the message data, such as the XML tags used to define the items in a JMSMapMessage and JMSStreamMessage. For this reason, use JMSBytesMessage to transfer messages formatted for other applications.
Converting between JMSBytesMessage and DataInputStream and DataOutputStream is
useful in some applications. Code based on the example, Reading and writing messages using DataInputStream and DataOutputStream, is necessary to use the com.ibm.mq.header
package
with JMS.
Examples
Sending and receiving a JMSObjectMessage
Sending and receiving a JMSTextmessage
A text message cannot contain text in different character sets. The example shows text in different character sets, sent in two different messages.
Sending data in a JMSStreamMessage and JMSMapMessage
Sending and receiving text in a JMSBytesMessage
The
code in Figure 6 sends a string in a
BytesMessage. For simplicity, the example sends a single string, for
which a JMSTextMessage is more appropriate. To
receive a text string in bytes message containing a mixture of types,
you must know the length of the string in bytes, called TEXT_LENGTH
in Figure 7. Even for a string with a fixed number
of characters, the length of the byte representation might be longer.
Reading and writing messages using DataInputStream and DataOutputStream
The code in Figure 8 creates a JMSBytesMessage using a DataOutputStream.
The statement that sets the JMS_IBM_ENCODING
property
is commented out. The statement is valid, if writing directly to a
JMSBytesMessage, but has no effect when writing to DataOutputStream.
Numbers that are written to the DataOutputStream are
encoded in Native
encoding. Setting JMS_IBM_ENCODING
has
no effect.
The code in Figure 9 receives a JMSBytesMessage using a DataInputStream.
The code page is printed out using the code page property
of the input message data, JMS_IBM_CHARACTER_SET
.
On input JMS_IBM_CHARACTER_SET
is a Java code page and not a numeric coded character
set identifier.
Table of message types and conversion types
Conversion type | ||||
---|---|---|---|---|
Message type | Text | Numeric | Other | None |
JMSObjectMessage
|
getObject
setObject |
|||
JMSTextMessage
|
getText
setText |
|||
JMSBytesMessage
|
readUTF
writeUTF |
readDouble
readFloat readInt readLong readShort readUnsignedShort writeDouble writeFloat writeInt writeLong writeShort |
readBoolean
readObject writeBoolean writeObject |
readByte
readUnsignedByte readBytes readChar writeByte writeBytes writeChar |
JMSStreamMessage
|
readString
writeString |
readDouble
readFloat readInt readLong readShort writeDouble writeFloat writeInt writeLong writeShort |
readBoolean
readObject writeBoolean writeObject |
readByte
readBytes readChar writeByte writeBytes writeChar |
JMSMapMessage
|
getString
setString |
getDouble
getFloat getInt getLong getShort setDouble setFloat setInt setLong setShort |
getBoolean
getObject setBoolean setObject |
getByte
getBytes readChar setByte setBytes setChar |