What's the best way to implement a Request/Reply pattern if no temporary queues are available?

4.8k views Asked by At

I have many instances of my client application. These clients send requests to a server application via messaging and receive a reply. Normally the reply would be sent using a temporary queue.

Unfortunately I have to use the Stomp protocol which has no concept of temporary queues or topics. (Although the message broker has)

What's the best way to ensure only the original requestor receives the reply? Are there any best-practices for this unfortunate situation?

2

There are 2 answers

0
T.Rob On BEST ANSWER

The customary solution when several requestors listen for replies on the same queue is to use correlation IDs to select messages. On the client side it looks like this:

  1. Place a message on the request queue and commit.
  2. Retrieve the JMSMessageID from the outbound message (the value is determined by the broker and updates the message object as a result of the send).
  3. Receive a message from the reply queue specifying the JMSMessageID from the outbound message as the correlation ID in the selector.
  4. Process and commit.

On the server side it looks like this:

  1. Receive a message under syncpoint.
  2. Process the request and prepare the response.
  3. Set the JMSCorrelationID on the response to the value of JMSMessageID from the request.
  4. Send the message.
  5. Commit.

The consumer would set the selector something like this: activemq.selector:JMSCorrelationID=.

Since the broker creates a message ID that is supposed to be globally unique, the pattern of using it as the correlation ID prevents collisions that are possible when each requestor is allowed to specify it's own value.

2
skaffman On

The best way to implement this pattern with JMS (that I've found, anyway) is to create a pre-configured topic for the response messages, and use correlation selectors on the response message so that the client can get the correct one.

In more detail, this means setting a random ID on the request message (using setJMSCorrelationID()), and putting that message on the request Queue. The consumer of that request message processes it, creates the response message, sets the same correlation ID on the response message, and puts it on the response Topic. The client, meanwhile, is listening on the response topic with a selector expression which specifies the correlation ID that it's expecting.

The danger is that the response message is sent before the client can get around to listening for it, although that's probably unlikely. You can try using a pre-configured Queue for the responses rather than a topic, but I've found that topics tend to work more reliably (my JMS provider of choice is HornetQ - your mileage may vary).

All this is tell me that JMS is a very poor fit for the request/response model. The API just doesn't support it properly. This is hardly surprising, since that was never a use-case for JMS.

Something like a compute grid (Terracotta, Gigaspaces, Infinispan, etc) would likely yield better results, but that's not really an option for you.