When using JMS for synchronous request response messaging there are some options and standards to consider. In this post I will explain the two most common patters for synchronous request response messaging and will provide some examples of how to implement these patterns in TIBCO BusinessWorks (BW) in combination with TIBCO Enterprise Messaging Service (EMS).
JMS request response patterns
The main problem with request response messaging is to correlate the response message to a particular request message. So if party A and party B both sends request messages the response to party B must be delivered to party B and the response messages to party A must be sent to party A.
There are two standard patterns in JMS for correlating request and response messages. These patterns are particularly used in synchronous request response messaging.
The two patterns are called:
- MessageID Pattern
- CorrelationID Pattern
MessageID pattern
n the MessageID pattern the service consumer (the party who initiates the request or invokes the service) must provide a unique MessageID and a JMS destination where the service consumer expects the response. This response destination is set in the JMS header property: ‘JMSReplyTo’
The Service provider will copy the MessageID it received in the request to the CorrelationID of the response message and send the response to the JMS destination provided by the service consumer in the JMSReplyTo property.
Graphically this can be viewed as:
CorrelationID pattern
In the CorrelationID pattern the service consumer must provide a unique CorrelationID. The service provider will copy the CorrelationID it received into the CorrelationID of the response message. All response messages will go to the same response destination.
Mixed patterns
TIBCO BW and EMS are quite flexible when it comes to these patterns and also support a mix of both patterns. For instance using the CorrelationID in the request to correlate response messages, like the CorrelationID pattern, but also use dynamic response destinations using the JMSReplyTo property, like the MessageID pattern. It is difficult (read: impossible) to choose one best pattern for all circumstances. However, all things considered equal it is probably better to stick with one of the standard patterns. Especially when you have more than one system connected to your JMS server.
For more info about these JMS patterns:
http://www.eaipatterns.com/RequestReplyJmsExample.html
http://docs.oracle.com/cd/E13171_01/alsb/docs25/interopjms/MsgIDPatternforJMS.html
Below I will show some examples of these two patterns in TIBCO. Know that these are just a few possibilities to implement these patterns. As mentioned above TIBCO is quitte flexible when it comes to these patters and even implementing one pattern can be done in more than one way using TIBCO BW and EMS.
MessageID pattern in TIBCO
Below I will show an example of the MessageID pattern in TIBCO. I will provide an example of both a service consumer and a service provider.
Service consumer
When implementing the MessageID pattern in TIBCO I always like to use the ‘JMS Queue Sender’ activity in combination with the ‘Get JMS Queue Message’ activity.
Below we are looking at the input data of the JMS Queue Sender. Note the replyToQueue field is test the response queue we would like to receive our response, this field will translate to the JMSReplyTo property in our JMS message. (and yes, it would have probable made sense to also call the field JMSReplyTo….yeah…hmmz…) Also note the MessageID is not provided in TIBCO BW, this property is set by TIBCO EMS.
When looking at the input tab of the ‘Get JMS Queue Message’ we can see a selector selecting messages based on the JMSCorrelationID property which is set to the MessageID of the request message. (probably no coincidence the MessageID is the only output field of the JMS Queue Sender activity )
When looking at the output of the Get JMS Queue Message activity we see the CorrelationID property is filled with: ‘ID:EMS-SERVER:EF854168E2C48:45’ And the JMSDestination is set to the value we provided in the request. EMS also provided a new unique MessageID property.
Service provider
Now we take our attention to the service provider. Which must copy the MessageID to the CorrelationID of the response and also send the response to the destination provided by the service consumer.
For the service provider I used a ‘JMS Queue Receiver’ process starter in combination with the ‘Reply To JMS Message’ activity.
Looking at the output of the JMS Queue Receiver we can see TIBCO EMS set the JMSMessageID property used for correlating the response message. This is the same MessageID we received in the response as the CorrelationID: ‘ID:EMS-SERVER:EF854168E2C48:45’. Also note the JMSReplyTo property is set to the value the service consumer provided in the request message.
Finally we take a look at the output of the ‘Reply To JMS Message’ activity. Here we can see none of the above properties, neither the JMSDestination nor the CorrelationID is set. This is because TIBCO BW and EMS set these properties in the background.
The way these properties are set by TIBCO BW is explained in the Pallette reference documentation available here: https://docs.tibco.com/pub/activematrix_businessworks/5.12.0/doc/pdf/tib_bw_palette_reference.pdf
at page 493 it states for setting the CorrelationID:
This ID is used to link a response message with its related request message. This property is usually set to the message ID of the message you are replying to, but any value can be used. For example, you may use another field in the body of the message (such as orderID) to correlate request and reply messages. The JMSCorrelationID of the reply message is set in this input element. If this element is not set, the correlation ID is set as follows: If the JMSCorrelationID input element is not set, the value of the JMSCorrelationID property in the message you are replying to is used.
• If neither this input element nor the JMSCorrelationID of the message you are replying to are set, the message ID of the message you are replying to is >used.• If none of the above values are set, the JMSCorrelationID of the reply message is set to null.
CorrelationID pattern in TIBCO
Next up the CorrelationID pattern in TIBCO.
Service Consumer
For the service consumer in TIBCO BW I will show two possibilities for implementing the CorrelationID pattern.
JMS Queue Requestor
TIBCO BW provides one out of the box activity for synchronous request reply over JMS, the ‘JMS Queue Requestor’ (there is also a topic version, you guessed it, the ‘JMS Topic Requestor’).
Below we are looking at the input tab of this JMS Queue Requestor activity. We provide the correlationID we want to use for this message.
When looking at the output tab we can see our response message with the correlationID we provided in the request. This copying of the CorrelationID from the request to the response message does however, in opposite to the MessageID example we have seen above, not automatically. This will be apparrant when we take a look at the service provider.
There is also another word of caution when using the ‘JMS Queue Requestor’ activity. This activity uses temporary queues as a response channel. And it does not perform correlation on selecting the message like we have seen in the example of the MessageID pattern. While using temporary queues as response channels is fine in and of itself this behavior can be overridden using the JMSReplyTo property (creating in effect a mixed pattern). Since there is no other correlation or message selection taking place when the JMS Queue Requestor reads the message from the response destination it cannot be guaranteed that the job who created the request also gets his response.
So it is strongly advised when using the ‘JMS Queue Requestor’ to stick with temporary queues for the response channel.
Also make sure your response messages have an expiration set. If for one reason your service consumer dies and the response messages don’t have an expiration set temporary queues don’t clean themselves and need manual removal.
Queue Sender
For implementing a service consumer using the CorrelationID pattern we can also take a similair approach like we did with the MessageID pattern. Using a combination of the ‘JMS Queue Sender’ and ‘Get JMS Queue Message’ activities.
The only difference being that the ‘JMS Queue Sender’ activity does not output the CorrelationID. So we need to set up a common CorrelationID field we can use in both the ‘JMS Queue Sender’ and ‘Get JMS Queue Message’ activities. In the example below we use a Mapper activity for this.
Now this CorrelationID can be used in the ‘JMS Queue Sender’ activity.
And in the message selector of the ‘Get JMS Queue Message’ we need to correlate using the CorrelationID we set in our Mapper activity.
Service provider
For the service provider we use the same ‘JMS Queue Receiver’ and ‘Reply to JMS Message’ activities as we did in the MessageID pattern. However we have to make sure we copy the CorrelationID of the request message into our response message.
When this mapping is done we can see the following output: