Search code examples
javajmsrabbitmqactivemq-classicjboss-messaging

Does JMS receiveNoWait() guarantee message delivery when messages are available?


Hello I am writing some kind of simple testing scenario where I execute the following source code:

Here is my send() method:

public void send() throws JMSException {

    Session session = null;
    MessageProducer producer = null;

    try {
        session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);

        Destination destination = session.createQueue("TEST.FOO");

        producer = session.createProducer(destination);
        producer.setDeliveryMode(DeliveryMode.NON_PERSISTENT);

        byte[] uselessData = new byte[1024];

        BytesMessage message = session.createBytesMessage();
        message.writeBytes(uselessData);

        producer.send(message);

    } finally {
        producer.close();
        session.close();
    }
}

Here is my receive() method:

public void receive() throws JMSException {

    Session session = null;
    MessageConsumer consumer = null;

    try {
        session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
        Destination destination = session.createQueue("TEST.FOO");
        consumer = session.createConsumer(destination);

        Message hugeMessage = consumer.receiveNoWait();

        if (hugeMessage == null) {
            System.out.println("Message was not received");
            unsucsesfullCount++;
        } else {
            if (hugeMessage instanceof BytesMessage) {
                System.out.println("Message received");
            }
        }
    } finally {
        consumer.close();
        session.close();
    }

}

I execute:

send();
receive();

The message value after receiveNoWait() is always null.

My question here is does the receiveNoWait() guarantee message delivery when there are messages in the broker? The send() is executed successfully so there is at least one message in the destination.

I've searched in the specification but there is not really clear definition if a message, which is available at the broker side should be explicitly received by receiveNoWait() at client side.

Also I want to ask, if receiveNoWait() does not have message available, should it trigger some refresh consumer process in the broker, so the next receiveNoWait() will receive the message?

The example code I provided run on ActiveMQ but my question is more conceptual than provider specific, because I have the same observation for other JMS providers.


Solution

  • No, the specification does not guarantee that any call to receiveNoWait will return a message, it might and then again it might not. When using receiveNoWait you must always check for a null return and act accordingly.

    In the case of ActiveMQ the client will return a message if the broker has dispatched one to it and it is immediately available in the consumer prefetch buffer otherwise it just returns null.

    Other implementations my indeed send a poll request to the broker, Qpid JMS for instance uses an AMQP link drain request to ask that the broker send it any messages that are available for dispatch and the broker will either send them or signal that the link is drained and there are no messages ready.

    In short it's completely up to the client and broker how they implement receiveNoWait but no matter what you always need to account for the chance that you won't get a message returned to you from that method.