Search code examples
springjmsspring-jmsjmstemplate

JmsTemplate with RECEIVE_TIMEOUT_NO_WAIT doesn't retrieve messages from JMS queue


Given I have ActiveMQ queue where many messages are already present.

When I set receive timeout on JmsTemplate to RECEIVE_TIMEOUT_NO_WAIT which is equal to -1:

jmsTemplate.setReceiveTimeout(JmsTemplate.RECEIVE_TIMEOUT_NO_WAIT); 

and try to receive one of those messages:

Message msg = jmsTemplate.receive(queueName);

then msg is null, but it should not be according JavaDoc:

/**
 * Timeout value indicating that a receive operation should
 * check if a message is immediately available without blocking.
 */
public static final long RECEIVE_TIMEOUT_NO_WAIT = -1;

Why is that?

When I do:

jmsTemplate.setReceiveTimeout(1000);

then messages are retrieved.


Solution

  • It has absolutely nothing at all to do with the JmsTemplate since it simply delegates to the underlying JMS Consumer object:

    protected Message receiveFromConsumer(MessageConsumer consumer, long timeout) throws JMSException {
        if (timeout > 0) {
            return consumer.receive(timeout);
        }
        else if (timeout < 0) {
            return consumer.receiveNoWait();
        }
        else {
            return consumer.receive();
        }
    }
    

    I would say it is working exactly as the JMS designers intended:

    /** Receives the next message if one is immediately available.
      *
      * @return the next message produced for this message consumer, or 
      * null if one is not available
      *  
      * @exception JMSException if the JMS provider fails to receive the next
      *                         message due to some internal error.
      */ 
    
    Message receiveNoWait() throws JMSException;
    

    In other words, it is for use cases where you absolutely don't want to block the thread for any time at all, if there is not currently a message that has already been sent to the consumer by the broker - not even waiting for a network I/O to complete, which is exactly how ActiveMQ has implemented it - initiates an I/O but returns null if that I/O doesn't complete immediately (which is most likely the case if there's a network involved).