Asynchronous messaging means that the sender doesn’t receive an immediate reply or confirmation of receipt. After sending a message for processing by a remote service, most applications require at least confirmation that the message was received and acted upon, and often require the results of the remote process. Remember—in a normal application, even if a method doesn’t return a value, the system at least knows that the method has had a chance to execute.
A reply message is a message received in response to another message. Reply messages are generally document or event messages, but are distinguished by being associated with a particular message. Typically, this association is accomplished by assigning each outgoing message a unique identifier (MOM systems do this automatically). If an incoming message is a reply, it includes a reference to the message the remote application is replying to.
JMS includes built-in functionality for associating a reply message
with the original. Each
JMS
message, upon creation, is assigned a message ID, which is accessible
via the JMSMessageID
property of the
Message
class. Messages also have a
JMSCorrelationID
field, not set by default. When
composing a reply message, it’s standard practice to
take the JMSMessageID
and store it in the
JMSCorrelationID
field. Assuming that
message
and reply
are valid JMS
messages, and that reply
is a response to
message
, this is how we’d set the
correlation:
reply.setJMSCorrelationID(message.getJMSMessageID( ));
This approach presupposes that the original sender kept track of the message ID. Obviously, reply messages can be linked to their original in whatever manner is appropriate for your application. An identifier with real world significance (purchase orders or database record keys) might make more sense than the ID assigned by the JMS provider.
Message transport systems have limits. These limits frequently have to do with size. Even if the messaging system you’re using doesn’t impose a strict upward boundary on the size of a message, practical considerations often impose one anyway. Network connections can be interrupted and servers can run out of memory.
As a result, it is sometimes necessary to divide a message into several parts, each of which can be easily digested by the messaging system and the recipient. The Sequenced Messages pattern allows you to spread one logical message over a series of actual messages (Figure 11-5). The client must wait until it has received all of the messages in the sequence before it can proceed.
To send sequenced messages in JMS, you need to include at least two additional properties in each message, and usually three. The first is a sequence ID, which allows the recipient to group messages from particular sequences. The second property is the order of the current message in the sequence. For example, your application might assign a particular message sequence the ID “MSEQ-001”, and each of the five messages in the sequence would include a message sequence ID property containing “MSEQ-001” and a message number from 1 to 5. If your application isn’t able to determine the length of a message sequence by examining the messages itself, a third property, providing the number of messages in the sequence, is also required.[5]
Here’s a basic example, using two properties. For
simplicity, we assume the content is presented as a set of text
strings (perhaps an XML file broken up into pieces) created by a
getContent( )
method:
String sSeqID = "MSEQ-001"; int msgIndex = 1; String[] contentPieces = getContent(...) for (int index = 0; index < contentPieces; index++) { TextMessage message = session.createTextMessage(contentPieces[i]); message.setStringProperty("MessageSequenceID", sSeqID); message.setIntProperty("MessageNumber", index); publisher.publish(topic, message, delivery_mode, priority, 0); }
Since none of the messaging systems we’ve discussed support sequenced messages natively, error handling in the case of an incomplete sequence is very much in the hands of the client application.
[5] If the end of the sequence is self-evident from examining the last message, you don’t need to specify the number of segments up front; the recipient can look at the message number of the final message in order to determine how many messages were supposed to have been received. This approach can be particularly helpful when it’s unclear at the start how large a sequence might end up being.