JMS message types and conversion
The choice of message type affects the 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.
Send 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 IBM 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 Send 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 Send 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, we 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.
Note: Text in a JMSBytesMessage is not converted by the JMS client. The client can only receive the text in the message as a byte array. If queue manager conversion is enabled, the text is converted by the queue manager, but the JMS client must still receive it as a byte array in a JMSBytesMessage.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. We 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. We 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.
We can send multiple items in a JMSMapMessage or JMSStreamMessage.
We 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 Send 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 MQSTR
. If the destination property WMQ_RECEIVE_CONVERSION is set to 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. We 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 IBM MQ classes for JMS performing any conversion; see Send 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, we 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 we must receive the message from a destination that defines a JMS message body style. If we do not, the MQRFH2 is treated as part of the user message data, which might not be what we 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
We can send multiple items in a JMSBytesMessage. Each numeric item is converted when the message is sent using the encoding defined for the message.
We 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.
Convert 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
Send and receiving a JMSObjectMessage
Send 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.
Send data in a JMSStreamMessage and JMSMapMessage
Send 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, we 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 |
Related concepts
- JMS message conversion approaches
- JMS client message conversion and encoding
- Queue manager data conversion
Related tasks