Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JMS message re-delivery delay

I have a JMS client that can ssh to remote systems upon receiving a message (and do various things there - not relevant to the question). It is possible that hundreds of such messages will arrive in a short period of time which need to be processed ASAP.

However, it is also possible that certain remote systems are not available when the message is received, so they should be postponed until later (eg. 1 hour or so). The best solution would be to put the message back to the queue with some "delay" value set, which will tell the JMS broker not to try to deliver the message again within an hour.

What is not OK: sleep in the receiving thread and wake up an hour later. Since the message consumer pool is limited (eg. 8 connections available) having 8 non-reachable systems would block the whole processing unnecessarily, which is unacceptable.

I didn't find a setting for either the message or the queue itself for such a "delay" value, does it exist?

A workaround solution is to use a second queue for storing messages to unreachable systems, and process these separately. But it is not a very elegant solution, and requires additional programming. Perhaps there is a better way.

like image 492
egbokul Avatar asked Aug 09 '10 10:08

egbokul


People also ask

Does JMS guarantee order?

A JMS queue guarantees only that each message is processed only once. Out-of-band cancel request is not easy to achieve with JMS then. Two ideas: Store a ticket which corresponds to each message in a database could be used to cancel message easily.

What is onMessage method called in JMS?

The onMessage method is called by the bean's container when a message has arrived for the bean to service. This method contains the business logic that handles the processing of the message. It is the message-driven bean's responsibility to parse the message and perform the necessary business logic.

How do I make JMS synchronous?

The best way to implement request-response over JMS is to create a temporary queue and consumer per client on startup, set JMSReplyTo property on each message to the temporary queue and then use a correlationID on each message to correlate request messages to response messages.


2 Answers

This is not possible through the JMS API prior to JMS 2.0. As a general rule, message transports are optimized to deliver messages as fast as possible and lack schedulers to hold a message for redelivery at some arbitrary interval. Assuming there is a transport provider that does have such functionality, anything you write would then be bound to that transport provider because, although the code might be JMS-compliant, the app itself would rely on this vendor-specific behavior.

See @Shashi's answer for an answer that applies to versions of MQ that support JMS 2.0.

like image 175
T.Rob Avatar answered Oct 13 '22 15:10

T.Rob


JMS 2.0 Specification defines a "Delivery delay" where client can specify a delivery delay value in milliseconds for each message it sends. This value defines a message delivery time which is the sum of the message’s delivery delay and the GMT it is sent (for transacted sends, this is the time the client sends the message, not the time the transaction is committed).

A message's delivery time is the earliest time when a JMS provider may make the message visible on the target destination and available for delivery to consumers. The provider must not deliver messages before the delivery time has been reached.

This feature is quite handy for the scenario described above.

like image 21
Shashi Avatar answered Oct 13 '22 15:10

Shashi