My application is using Messaging (53) to perform a Request-Reply (154).
How does a replier know where to send the reply?
Messages are often thought of as completely independent, such that any sender can send a message on any channel whenever it likes. However, messages are often associated. With Request-Reply (154) pairs, two messages appear independent, but the reply message has a one-to-one correspondence with the request message that caused it. Thus, the replier that processes the request message cannot simply send the reply message on any channel it wants; it must send it on the channel on which the requestor expects the reply.
Each receiver could automatically know which channel to send replies on, but hard-coding such assumptions makes the software less flexible and more difficult to maintain. Furthermore, a single replier could be processing calls from several different requestors, so the reply channel is not the same for every message; it depends on which requestor sent the request message.
Figure 5.5 Uncertain Where to Send Replies
A requestor potentially may not want a reply sent back to itself. Rather, it may have an associated callback processor to process replies, and the callback processor may monitor a different channel than the requestor does (or the requestor may not monitor any channels at all). The requestor could have multiple callback processors, requiring replies for different requests from the same requestor to be sent to different processors.
The reply channel will not necessarily transmit replies back to the requestor; it will transmit them to whomever the requestor wants to process the replies, because it’s listening to the channel the requestor specified. So, knowing what requestor sent a request or what channel it was sent on does not necessarily tell the replier what channel to send the reply on. Even if it did, the replier would still have to infer which reply channel to use for a particular requestor or request channel. It’s easier for the request to explicitly specify which reply channel to use. What is needed is a way for the requestor to tell the replier where and how to send back a reply.
Figure 5.6 The request message should contain a Return Address that indicates where to send the reply message.
This way, the replier does not need to know where to send the reply; it can just obtain the reply channel address from the request message. If different messages to the same replier require replies to different places, the replier can determine from each request message where to send the reply for that request. This encapsulates the knowledge of what channels to use for requests and replies within the requestor so those decisions do not have to be hard-coded within the replier. A Return Address is put in the header of a message because it’s not part of the application data being transmitted.
A message’s Return Address is analogous to the reply-to field in an e-mail message. The reply-to e-mail address is usually the same as the from address, but the sender can set it to a different address to receive replies in an account other than the one used to send the original message.
When the reply is sent back over the channel indicated by the Return Address, it may also need a Correlation Identifier (163). The Return Address tells the receiver what channel to put the reply message on; the Correlation Identifier (163) tells the sender which request a reply is for.
Example: JMS Reply-To Property
JMS messages have a predefined property for Return Addresses, JMSReplyTo. Its type is a Destination (a Topic or Queue) rather than just a string for the destination name, which ensures that the destination (e.g., Message Channel ) really exists, at least when the request is sent [JMS 1.1], [Monson-Haefel].
A sender that wishes to specify a reply channel that is a Queue would do so like this:
Queue requestQueue = // Specify the request destination Queue replyQueue = // Specify the reply destination Message requestMessage = // Create the request message requestMessage.setJMSReplyTo(replyQueue); MessageProducer requestSender = session.createProducer(requestQueue); requestSender.send(requestMessage);
Then, the receiver would send the reply message like this:
Queue requestQueue = // Specify the request destination MessageConsumer requestReceiver = session.createConsumer(requestQueue); Message requestMessage = requestReceiver.receive(); Message replyMessage = // Create the reply message Destination replyQueue = requestMessage.getJMSReplyTo(); MessageProducer replySender = session.createProducer(replyQueue); replySender.send(replyMessage);
Example: .NET Response-Queue Property
.NET messages also have a predefined property for Return Addresses, ResponseQueue. Its type is a MessageQueue (e.g., Message Channel ), the queue that the application should send a response message to [SysMsg], [Dickman].
Example: Web Services Request/Response
SOAP 1.2 incorporates the Request-Response Message Exchange pattern [SOAP 1.2 Part 2], but the address to which to send the reply is unspecified and therefore implied. This SOAP pattern will need to support an optional Return Address to truly make SOAP messages asynchronous and to delink the responder from the requestor.
The emerging WS-Addressing standard helps address this issue by specifying how to identify a web service endpoint and what XML elements to use. Such an address can be used in a SOAP message to specify a Return Address. See the discussion of WS-Addressing in Chapter 14, “Concluding Remarks.”