0

I am trying to consume a message from a RabbitMQ channel using Java code. I invoke the myAction() method two times, and it works as expected only on the first one.

private Channel receiveChannel=//...;

String myAction() {
        var wrapper = new Object(){ String message = null; };
        final CountDownLatch countDownLatch = new CountDownLatch(1);
        DeliverCallback deliverCallback = (consumerTag, delivery) -> {
            wrapper.message = new String(delivery.getBody(), "UTF-8");
            countDownLatch.countDown();
            log.info("Received response '" + wrapper.message + "'");
        };

        receiveChannel.basicConsume(recvQueueKey, true, deliverCallback, consumerTag -> {});
        if(!countDownLatch.await(10000, TimeUnit.MILLISECONDS)) {
            fail();
        }
        return wrapper.message;
}

Basically, my goal is to consume and have myAction() return the message content. What happens in the second time I invoke myAction() is that log.info("Received response.. gets printed but the countDownLatch does not get decremented, causing fail() to be executed. Does anyone have any idea what I am missing? Is line with this, is it the proper way to consume and return the message content? Thank you for your help.

João Matos
  • 6,102
  • 5
  • 41
  • 76
  • I'm no RabbitMQ expert, but are you sure that the second "Received.." message isn't being printed by the first deliverCallback? Try adding a unique ID to the callback when you create it. What is the lifetime of the consumer you are creating? – tgdavies Jul 02 '20 at 11:27
  • thanks for your reply. Yes I am sure – João Matos Jul 02 '20 at 12:22

1 Answers1

0

Here's an example which shows that the lifetime of callbacks is not limited to the scope in which you call basicConsume.

package org.example;

import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.DeliverCallback;

import java.io.IOException;
import java.util.concurrent.TimeoutException;

public class RabbitMQEg {

    private final static String QUEUE_NAME = "test";

    public static void main(String... args) throws IOException, TimeoutException, InterruptedException {
        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost("localhost");
        try (Connection connection = factory.newConnection();
             Channel c = connection.createChannel()) {

            c.queueDeclare(QUEUE_NAME, false, false, false, null);

            setupConsumer(c, "Consumer 1");
            setupConsumer(c, "Consumer 2");

            Thread.sleep(1000);

            c.basicPublish("", QUEUE_NAME, null, "A".getBytes());
            Thread.sleep(1000);
            c.basicPublish("", QUEUE_NAME, null, "B".getBytes());
            Thread.sleep(1000);
            c.basicPublish("", QUEUE_NAME, null, "C".getBytes());

            Thread.sleep(1000);
        }
    }

    private static void setupConsumer(Channel c, String tag) throws IOException, TimeoutException {
            DeliverCallback deliverCallback = (consumerTag, delivery) -> {
                System.out.println("Received response '" + new String(delivery.getBody()) + "' " + tag + " on thread " + Thread.currentThread().getName());
            };

            c.basicConsume(QUEUE_NAME, true, deliverCallback, consumerTag -> {});
    }
}

The output I get is:

Received response 'A' Consumer 1 on thread pool-1-thread-5
Received response 'B' Consumer 2 on thread pool-1-thread-6
Received response 'C' Consumer 1 on thread pool-1-thread-7
tgdavies
  • 10,307
  • 4
  • 35
  • 40