Hello RabbitMQ

Current version of RabbitMQ is 2.7.1, you can freely download it from the RabbitMQ site. I have installed it on Windows, following the clear instructions given by the RabbitMQ people, and I easily set up a working environment.

The RabbitMQ server is written in Erlang, and that means we need to install it before. So we should go to the Erlang download page, get the latest version, in my case R15B.

After this prelude I had no more issues, and I installed the RabbitMQ server fast.

Next step is installing the Java RabbitMQ client side support. Very easy, not much to say on this point.

I am ready to create my "Hello" application.

The official RabbitMQ tutorial, episode one Java flavor, is a very good place where to start.

You could just use the provided code as is. Being lazy, I have merged the two-class producer-consumer "hello world" example in a single class application, and made some minor changes. I named the class SendRec, and I put it in the package rmq.

The class has a constant, the queue name, and a main function:
private final static String QUEUE_NAME = "simple";

// ...

public static void main(String[] argv) {
    SendRec sr = new SendRec();

    System.out.println("Sending");
    if(!sr.send())
        return;

    System.out.println("Receiving");
    sr.receive();
}
The idea is pretty straightforward, firstly we send messages to the queue and, if this works fine, we receive them back.

Let's see how to send messages:
public boolean send() {
    ConnectionFactory factory = new ConnectionFactory();
    factory.setHost("localhost"); // 1

    try {
        Connection connection = factory.newConnection(); // 2

        Channel channel = connection.createChannel(); // 3
        channel.queueDeclare(QUEUE_NAME, false, false, false, null); // 4
        String message = "A message"; // 5
        channel.basicPublish("", QUEUE_NAME, null, message.getBytes()); // 6
        System.out.println(message);

        channel.basicPublish("", QUEUE_NAME, null, null); // 7
        System.out.println("Empty message");

        channel.close(); // 8
        connection.close();
    } catch (IOException e) {
        System.out.println("Error sending messages: " + e.getMessage());
        return false;
    }
    return true;
}
1. Usually we pass more information to a connection factory, but here we are working on a local vanilla setup, so we can rely on the default RabbitMQ setting.
2. Given a factory we can create a connection.
3. And given a connection we can create a communication channel.
4. The simplest communication requires the name of the queue we want to use, a bunch of false and a final null. We'll see more on this in the next future.
5. This is the message that we want to deliver.
6. And this is the simplest way to publish a message. Notice the queue name in second position and the data sent as last parameter. We send just a bare byte array.
7. In this way we send an empty message.
8. We won't use anymore this channel in the current session, so we close it. Actually, we could save some typing here, because when closing the connection the open channels within are automatically closed. But it is better to be more explicit, especially in an example code.

And here is how to receive the messages:
public boolean receive() {
    ConnectionFactory factory = new ConnectionFactory();
    factory.setHost("localhost");

    try {
        Connection connection = factory.newConnection();
        Channel channel = connection.createChannel();
        channel.queueDeclare(QUEUE_NAME, false, false, false, null); // 1

        QueueingConsumer consumer = new QueueingConsumer(channel); // 2
        channel.basicConsume(QUEUE_NAME, true, consumer);

        while (true) {
            QueueingConsumer.Delivery delivery = consumer.nextDelivery(); // 3
            byte[] body = delivery.getBody(); // 4
            if(body.length == 0) { // 5
                System.out.println("Empty message received");
                break;
            }

            String message = new String(body); // 6
            System.out.println(message);
        }

        channel.close(); // 7
        connection.close();
    } catch (IOException|InterruptedException e ) { // 8
        System.out.println("Error getting messages: " + e.getMessage());
        return false;
    }
    return true;
}
}
1. Just the same as before, factory, connection, channel.
2. But here we need another object, a consumer from a queue, associated to the used channel.
3. Get the next message pending on the queue.
4. In the delivery body we find the original message.
5. Here an empty message is considered a terminator.
6. The message is not empty, let's use it.
7. As above, before exiting we close channel and connection.
8. Java 7 feature, more exception types caught in one shot.

To run the application, I wrote a one-liner script like this:
java -cp .;C:\dev\rmq\commons-io-1.2.jar;C:\dev\rmq\commons-cli-1.1.jar;
C:\dev\rmq\rabbitmq-client.jar rmq.SendRec
In your case the path to the RabbitMQ JAR should be different, as the fully qualified class name. And remember that it is running on Windows, so the separators in the classpath are semicolon.

Even for this simple example, could be worthy to know how to use a couple of RabbitMQ server scripts. To check the status of the server we can use:
rabbitmqctl status
To see which queues are currently available on this instance of RabbitMQ server:
rabbitmqctl list_queues
To start and stop the RabbitMQ service:
rabbitmq-service stop|start
The complete Java code for the class showed above is on github.

No comments:

Post a Comment