1

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.

Patrik Mihalčin
  • 3,341
  • 7
  • 33
  • 68
  • I suspect subsequent no wait calls will work (after the first one with wait). I just looked at the `ActiveMQMessageConsumer.receiveNoWait()` method and he sends a pull request but, of course, that request is not satisfied immediately so there are no messages yet. Eventually those messages will arrive and the no wait option should work. – Gary Russell Jun 20 '18 at 17:56
  • It seems weird.. what's the advantage of re-configuring `JmsTemplate` from some timeout to `RECEIVE_TIMEOUT_NO_WAIT`.. I can just keep using original timeout.. I don't see any use case for it :) – Patrik Mihalčin Jun 21 '18 at 12:15

1 Answers1

3

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).

Gary Russell
  • 166,535
  • 14
  • 146
  • 179