JMS message conversion approaches
A number of data conversion approaches are open to JMS application designers. These approaches are not exclusive; some applications are likely to use a combination of these approaches. If your application is exchanging only text or is exchanging messages only with other JMS applications, you do not normally consider data conversion. Data conversion is performed automatically for you, by WebSphere® MQ.
- Is it necessary to think about message conversion at all?
- In some cases, such as JMS to JMS message transfers, and exchanging text messages with IBM® WebSphere MQ programs, IBM WebSphere MQ performs the necessary conversions for you, automatically. You might want to control data conversion for performance reasons, or you might be exchanging complex messages that have a predefined format. In cases such as these you must understand message conversion, and read the following topics.
- What kinds of conversion are there?
- There are four main types of conversion, which are explained in the following sections:
- Where should conversion be performed?
- The section, Choosing an approach to message conversion: "receiver makes good", describes the
usual approach of
receiver makes good
.Receiver makes good
also applies to JMS data conversion.
JMS client data conversion
JMS client1 data conversion is the conversion of Java primitives and objects into bytes in a JMS message as it is sent to a destination, and conversion back again, when it is received. JMS client data conversion uses the methods of the JMSMessage classes. The methods are listed by JMSMessage class type in Table 1.
Conversion to and from the internal JVM representation of numbers and text is performed for read, get, set, and write methods. The conversion is performed when the message is sent, and when any of the read or get methods is called on a message that has been received.
The code page and numeric encoding used to write or set the contents of a message are defined as attributes of the destination. The destination code page and numeric encoding can be changed administratively. An application can also override the destination code page and encoding by setting the message properties that control writing or setting message content.
If you want to convert number encoding when
a JMSBytesMessage message is sent to a destination
that is not defined as Native
encoding, you must
set the message property JMS_IBM_ENCODING
before
sending the message. If you are following the receiver makes good
pattern,
or if you are exchanging messages between JMS applications, the application
does not need to set JMS_IBM_ENCODING
. In most cases
you can leave the Encoding property as Native
.
For JMSStreamMessage, JMSMapMessage,
and JMSTextMessage messages, the character set
identifier properties of the destination are used. Encoding is ignored
on sending as numbers are written out in text format. The JMS client
application program does not have to set JMS_IBM_CHARACTER_SET
before
sending the message if the destination character set property to apply..
To get the data in a message an application calls the JMS message read or get methods. The methods refer to the code page and encoding defined in the previous message header to create the Java primitives and objects correctly.
JMS client data conversion meets the needs of most JMS applications that are exchanging messages between one JMS client and another. You do not code any explicit data conversion. You do not use the java.nio.charset.Charset class, which is typically used when writing text to a file. The writeString and setString methods do the conversion for you.
For more details on JMS client data conversion, see JMS client message conversion and encoding.
Application data conversion
A JMS
client application can perform explicit character data conversion
by using the java.nio.charset.Charset class;
see the examples in Figure 3 and Figure 4 . String data is converted into bytes,
using the getBytes method, and sent as bytes. The
bytes are converted back into text by using a String constructor
that takes a byte array and a Charset. Character
data is converted using the encode and decode Charset methods.
Typically the message is sent or received as JMSBytesMessage
,
because the message part of a JMSBytesMessage
does
not contain anything other than the data written by the application2. You can also send and receive bytes using JMSStreamMessage, JMSMapMessage,
or JMSObjectMessage.
There are no Java methods to encode and decode
bytes that contain numeric data represented in different encoding
formats. Numeric data is encoded and decoded automatically using the
numeric JMSMessage read and write methods. The
read and write methods use the value of the JMS_IBM_ENCODING
attribute
of the message data.
A typical use for application data conversion
is if a JMS client sends or receives a formatted message from a non-JMS
application. A formatted message contains text, numeric, and bytes
data organized by the length of the data fields. Unless the non-JMS
application has specified the message format as MQSTR
,
the message is constructed as a JMSBytesMessage.
To receive formatted message data in a JMSBytesMessage you
must call a sequence of methods. The methods must be called in the
same order the fields were written into the message. If the fields
are numeric, you must know the encoding and length of the numeric
data. If any of the fields contain byte or text data, you must know
the length of any byte data in the message. There are two ways to
convert a formatted message into a Java object
that is easy to use.
- Construct a Java class corresponding to the record, to encapsulate reading and writing the message. Access to the data in the record is with get and set methods of the class.
- Construct a Java class corresponding
to the record by extending the com.ibm.mq.headers class.
Access to the data in the class is with type-specific accessors of
the form,
getStringValue(fieldname);
Queue manager data conversion
In WebSphere MQ V7.0, code page
conversion can be performed by the queue manager when a JMS client
program gets a message. The conversion is the same as the conversion
performed for a C program. A C program sets MQGMO_CONVERT
as
an MQGET GetMsgOpts parameter
option; see Figure 2. A queue manager
performs conversion for a JMS client program that is receiving a message,
if the WMQ_RECEIVE_CONVERSION destination property
is set to WMQ_RECEIVE_CONVERSION_QMGR
, The JMS client
program can also set the destination property; see Figure 1.
Before V7.0, conversions were
always performed by the JMS client. JMS client data conversion is
restricted to converting sequences of numbers and text of type and
length known to the JMS client. It cannot convert data structures;
see Exchanging a formatted record with a non-JMS application. In V7.0, until fix pack 7.0.1.5,
if the conversion can be performed by the queue manager, it is always
performed by the queue manager. From 7.0.1.5 onwards, the default
conversion behavior reverts to the same as V6.0, and all conversions
are performed by the JMS client. From 7.0.1.5, or 7.0.1.4 with APAR
IC72897, you can set a new destination option, WMQ_RECEIVE_CONVERSION
,
to control where conversion is performed, and WMQ_RECEIVE_CCSID
,
to set the target code page; see Figure 1.
The main benefit
of queue manager conversion comes when exchanging messages with non-JMS
applications. If the Format
field in the message
is defined, and the target character set, or encoding, is different
to the message, the queue manager performs data conversion for the
target application, if the application requests it. The queue manager
converts message data formatted according to one of the predefined WebSphere MQ message types,
such as a CICS® bridge header
(MQCIH
). If the Format
field is
user-defined, the queue manager looks for a data conversion exit with
the name provided in the Format
field.
Queue
manager data conversion is used to best effect with the receiver
makes good
design pattern. A sending JMS client does not need
to perform conversion. A non-JMS receiving program relies on the conversion
exit to ensure that the message is delivered in the required code
page and encoding. With a sending JMS client, and non-JMS receiver,
the example applies to IBM WebSphere MQ
pre- and post-V7.0. With IBM WebSphere MQ
V7.0, the conversion exit can be called for a receiving JMS program
as well.
You can create a data conversion exit, using the data conversion exit utility, crtmqcvx, to enable the queue manager to convert your own record formatted data. You can build your own record format, use the com.ibm.mq.headers to access it as a Java class, and use your own conversion exit to convert it. On z/OS® the utility is called CSQUCVX, and on IBM i, CVTMQMDTA. See Exchanging a formatted record with a non-JMS application.
Message channel data conversion
WebSphere MQ Sender, Server, Cluster-receiver, and Cluster-sender channels have a message conversion option, CONVERT. The contents of a message can optionally be converted when a message is sent. The conversion takes place at the sending end of the channel. The cluster-receiver definition is used to auto-define the corresponding cluster-sender channel.
Data conversion by message channels is typically used if it is not possible to use other forms of conversion.
Choosing an approach to message conversion: receiver
makes good
The usual approach in WebSphere MQ application design for code
conversion is receiver makes good
. Receiver makes good
reduces
the number of message conversions. It also avoids the problem of unexpected
channel errors if message conversion fails on some intermediary queue
manager during message transfer. The receiver makes good
rule
is only broken if there is some reason why the receiver cannot make
good. The receiving platform might not have the right character set,
for example.
Receiver makes good
is also good general
guidance for JMS client applications. But in specific cases, conversion
to the correct character set at source can be more efficient. Conversion
from the JVM internal representation must take place when a message
containing text or numeric types is sent. Conversion to the character
set required by the receiver, if the receiver is not a JMS client,
might remove the need for the non-JMS recipient to perform conversion.
If the recipient is a JMS client, it is going to convert again, anyway,
to decode the message data and create Java primitives
and objects.
The difference between JMS client applications, and applications written in a language such as C, is that Java must perform data conversion. A Java application must convert numbers and text from their internal representation to an encoded format used in messages.
By setting destination, or message properties,
you can set the character set and encoding used by WebSphere MQ to encode numbers and text
in messages. Normally, you would leave the character set as 1208
and
encoding as Native
.
WebSphere MQ does not convert byte arrays.
To encode strings and character arrays into byte arrays use the java.nio.charset package. Charset specifies
the character set used to convert a string or character array into
a byte array. You can also decode a byte array into a string or character
array using a Charset. It is not good practice
to rely on java.nio.charset.Charset.defaultCodePage when
encoding strings and character arrays. The default Charset is
typically windows-1252
on Windows, and UTF-8
on UNIX. windows-1252
is
a single-byte character set and UTF-8
is a multi-byte
character set.
Generally leave the destination character set
and encoding properties at their default values of UTF-8
and Native
when
exchanging messages with other JMS applications. If you are exchanging
messages containing numbers or text with a JMS application, choose
one of the JMSTextMessage, JMSStreamMessage, JMSMapMessage,
or JMSObjectMessage message types that fit your
purpose. There are no other conversion tasks to do.
MQ
, and use JMSBytesMessage to
avoid the IBM WebSphere MQ
classes for JMS adding additional header and tagging information to
the message data. Use JMSBytesMessage methods to
write numbers and bytes, and the Charset class
convert text into byte arrays explicitly. A number of factors might
influence your choice of character set:- Performance: Can you reduce the number of conversions by transforming text into a character set that is used on the largest number of servers?
- Uniformity: Transfer all messages in the same character set.
- Richness: What character sets have all the code points that applications must use?
- Simplicity: Single-byte character sets are simpler to use than variable length and multibyte character sets.
See Exchanging a formatted record with a non-JMS application. for examples of converting messages exchanged with non-JMS applications.
Examples
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 |
Calling data conversion from a C program
Sending and receiving text in a JMSBytesMessage
The
code in Figure 3 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 4. Even for a string with a fixed number
of characters, the length of the byte representation might be longer.
JMS Clientrefers to the WebSphere MQ classes for JMS that implement the JMS interface, which runs either in client or bindings mode.