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

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?

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:
Place a message on the request queue and commit.
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).
Receive a message from the reply queue specifying the JMSMessageID from the outbound message as the correlation ID in the selector.
Process and commit.
On the server side it looks like this:
Receive a message under syncpoint.
Process the request and prepare the response.
Set the JMSCorrelationID on the response to the value of JMSMessageID from the request.
Send the message.
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.

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.

Related

TimeToLive on Camel response messages

When using an InOut paradigm to send request/response messages to a JMS endpoint, the Camel JMS documentation describes how to set a message expiration on the request message, but it doesn't describe whether the response message will have a timeout (JMS expiration) set when it's sent by the consumer of the request message. The documentation does describe the replyToDeliveryPersistent URI option that the consumer can set to specify that the response message it sends should be non-persistent, but I don't see anything that would let you specify whether the response message will have an expiration date set.
Is there some way to ensure that response messages will be expired (so they can be automatically removed from the broker) if they are unconsumed for a certain amount of time (e.g. because the producer of the request was killed before it read the response to its final request), without implementing a custom ActiveMQ consumer and losing the benefits of using Camel? I control both the producer and the consumer, so the changes can happen at whichever side they need to be made (and I'm aware that the consumer end is the place this would likely need to be done); the sole criterion here is that Camel must remain the method for processing the message and responding with a reply message, because having to implement that by hand would be worse than living with persistent reply messages.
The only way to set an expiration time (JMSExpiration header) on a message is from its production point (i.e. by the producer).
In your case, the consumer of your request should set the JMSExpiration date explicitly1, using the JMS component's URI option timeToLive, and there is no way to set this option from the requesting side.
1) JMS specification points out that instead of setting the JMSExpiration directly, JMS clients should specify the time-to-live. The header is then calculated as the sum of the time-to-live and the current GMT value.

IBM WebSphere MQ Client - unlimited wait GET vs. correlation GET

I am trying to build with amqmdnet a IBM MQ receiver with 2 functionalities:
ReceiveReply(byte correlationId) – reads REPLY messages for supplied correlation identifiers. Is implemented by a GET with a correlation MATCH.
event EventHandler NewMessage – notifies the subscriber of new REQUEST messages. Is implemented by a GET with unlimited wait in infinite while loop.
The problem is that I cannot limit the second GET to read only REQUEST messages and so the correlation GET is never successful. If I only do one GET I will have to implement correlation on my own.
Anyone tried to implement something similar?
Thanks,
Radu
The simplest option is to use two queues. There are ugly ways of achieving what you are after (imagine all request messages putting something in the correlid so you could get by correlid there too, for example) but in principle you have a request queue and a reply queue - dont share!

Query regarding the java message queue

I have a design query regarding queues. My scenario is as follows:
I have to use a messaging system, with single producer and multiple consumers (asynchronous). The producer pushes different types of messages into the messaging system. Depending upon the message type, that particular consumer has to consume that message. (Each consumer is running on a different server). If one consumer is down and a message comes for that consumer, it will be in the messaging system only. If I use a message queue, the message in the queue will block the next messages that can be consumed by the other consumers. Are queues suitable for handling this kind of situation? Or do we need to go for a topic?
Whether you use a queue or a topic should depend on whether there an instance where multiple consumers must process the same message. If that is the case then a topic is required do generate that one-to-many pattern.
On the other hand, if any one message will only ever be consumed by one consumer, then you can use a queue or topic and the consumers specify the message type as a JMS selector. In this way, all consumers can listen on the same queue and each selects a different subset of messages. In the event one application is not there, it's messages do not "block the next messages that can be consumed by the other consumers" but rather they just stack up in the queue and other consumers still receive their messages based on selection criteria.
Please also realize that queues are lightweight constructions and you can easily have one queue per consumer. Typically, things providing a service listen on a well-known queue and each queue represents a different function of the service or a different service. Thus there may be many service input queues. Similarly, reply messages are generally uniquely addressed to the application instance that made the request and go to a unique, often dynamic, reply-to queue. Both of these implementations I have described lead to a separation of traffic across queues rather than pooling different message types into the same queue. Since JMS selectors always impart an additional processing cost, using more queues is generally more performant than selecting many types of message from the same queue.
I am responding to your question about selectors in the comment section here since I have more space and can put links in...
Section 3.8.1 of the JMS 1.1 spec states:
A JMS message selector allows a client to specify, by message header, the
messages it’s interested in. Only messages whose headers and properties
match the selector are delivered. The semantics of not delivered differ a bit
depending on the MessageConsumer being used. See Section 5.8,
“QueueReceiver,” and Section 6.11, “TopicSubscriber,” for more details.
Message selectors cannot reference message body values.
A message selector matches a message if the selector evaluates to true when
the message’s header field and property values are substituted for their
corresponding identifiers in the selector.
As noted above, selectors can be on fields that are implicit in the message such as MsgID or CorrelationID or thsey can be on fields specifically set by the message producer such as a message property. Either way, the client must specify the value of any selectors used by the message consumer.

Configure a JMS (ActiveMQ) queue so that it only contains the last message

We have quartz process that polls a ActiveMQ JMS queue.
We know that we could get several messages a minute would like to only respond to the most current message at a configured polling rate of a minute or more.
We don't need to process any of the previous messages.
Is there a way to configure the queue to get this behavior?
Its seems like a topic has the ability to do this via the subscription recovery policy using a count of 1. We would like to do this using a queue to guarantee (more or less) a single delivery of the message.
Or is there a conceptual flaw in our assumptions...
Thanks
In my opinion there is no standard operation for this, so you will have to write some code....
One possible solution would be to use a QueueBrowser together with a QueueReceiver:
Through the QueueReceiver you would get an Enumeration of the messages in the queue. For each message you can now perform a receive with a MessageSelector on the JMSMessageID as long as hasMoreElements() returns true. The last message will be the one you want to have....
When using activemq, you can use "image caching" on topics. One of the settings there is to always keep the last mesage sent..
Take a look at the Subscription recovery Policy settings:
http://activemq.apache.org/subscription-recovery-policy.html

What is the best way to reject messages with the same body in AMQ queue?

I have a single AMQ queue that receives simple messages with string body. Consider I'm sending CLSIDs as message bodies. CLSIDs could be not unique, but I'd like to reject all messages with not unique bodies and keep only single instance of such messages in the queue. Is there any simple way to do it?
Currently I'm using a workaround. Messages from the queue are consumed by some processor that tries to insert bodies into a simple DB table with UNIQUE constraint applied to message_body field. If processor inserts the messages succesfuly - it's assigned to exchange.out.body and sent to other queue. If ConstraintViolationException is thrown - nothing is resent to other queue.
I would like to know does AMQ support something similar out of the box?
I believe you can write an interceptor for activemq where you can perform certain actions on messages. Check out: http://activemq.apache.org/interceptors.html
That being said, in my personal opinion this is bad practice. ActiveMQ is a messaging system which should only be responssible for transport of the message. All logic can beter be performed using your application ( either make sure the sender cannot send the same message more then once OR , create an intermediate consumer which indeed matches the received body with a database that contains already seen message bodies BEFORE, routing the message to the actual receiver queue)

Resources