JmsTemplate with RECEIVE_TIMEOUT_NO_WAIT doesn'

2019-08-20 05:29发布

问题:

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.

回答1:

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