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