Building a Simple Java Application with RabbitMQ Communication

  ·   3 min read

In the world of microservices architecture, effective inter-service communication is essential for building robust applications. RabbitMQ is a widely used message broker that implements the Advanced Message Queuing Protocol (AMQP), allowing different applications to communicate with one another seamlessly and reliably. In this article, we will build a simple Java application consisting of two services that communicate with each other using RabbitMQ.

Prerequisites

Before we dive into the code, ensure you have the following installed:

  • Java Development Kit (JDK) 8 or later
  • Maven for dependency management
  • RabbitMQ server (you can use Docker for quick setup)
  • IDE of your choice (Eclipse, IntelliJ IDEA, etc.)

You can set up RabbitMQ using Docker with the following command:

docker run -d --hostname my-rabbit --name some-rabbit -p 5672:5672 -p 15672:15672 rabbitmq:management

Project Structure

We’ll create a Maven project with the following structure:

simple-rabbitmq-app/
│
├── producer/
│   ├── src/
│   │   ├── main/
│   │   │   ├── java/
│   │   │   │   └── com/
│   │   │   │       └── example/
│   │   │   │           ├── Producer.java
│   │   │   └── resources/
│   │   │       └── application.properties
│   ├── pom.xml
│
└── consumer/
    ├── src/
    │   ├── main/
    │   │   ├── java/
    │   │   │   └── com/
    │   │   │       └── example/
    │   │   │           ├── Consumer.java
    │   │   └── resources/
    │   │       └── application.properties
    ├── pom.xml

Maven Dependencies

Each pom.xml file for the producer and consumer should include the following dependencies:

<dependencies>
    <dependency>
        <groupId>com.rabbitmq</groupId>
        <artifactId>amqp-client</artifactId>
        <version>5.14.0</version> <!-- Check for the latest version -->
    </dependency>
</dependencies>

Producer Code

In Producer.java, we will send a message to a queue:

package com.example;

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

public class Producer {

    private final static String QUEUE_NAME = "message_queue";

    public static void main(String[] argv) throws Exception {
        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost("localhost");
        try (Connection connection = factory.newConnection();
             Channel channel = connection.createChannel()) {
            channel.queueDeclare(QUEUE_NAME, false, false, false, null);
            String message = "Hello, RabbitMQ!";
            channel.basicPublish("", QUEUE_NAME, null, message.getBytes("UTF-8"));
            System.out.println(" [x] Sent '" + message + "'");
        }
    }
}

Consumer Code

In Consumer.java, we will listen to the queue and print received messages:

package com.example;

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

public class Consumer {

    private final static String QUEUE_NAME = "message_queue";

    public static void main(String[] argv) throws Exception {
        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost("localhost");
        try (Connection connection = factory.newConnection();
             Channel channel = connection.createChannel()) {
            channel.queueDeclare(QUEUE_NAME, false, false, false, null);
            System.out.println(" [*] Waiting for messages. To exit press CTRL+C");

            DeliverCallback deliverCallback = (consumerTag, delivery) -> {
                String message = new String(delivery.getBody(), "UTF-8");
                System.out.println(" [x] Received '" + message + "'");
            };
            channel.basicConsume(QUEUE_NAME, true, deliverCallback, consumerTag -> { });
        }
    }
}

Running the Application

  1. Start the RabbitMQ server using the Docker command provided above.
  2. Open two terminal windows:
    • In the first terminal, navigate to the producer directory and run the producer:
      mvn clean compile exec:java -Dexec.mainClass="com.example.Producer"
      
    • In the second terminal, navigate to the consumer directory and run the consumer:
      mvn clean compile exec:java -Dexec.mainClass="com.example.Consumer"
      

Now, when you run the producer, it will send a message, and the consumer will receive and print that message.

Conclusion

In this article, we created a simple Java application where two services communicate using RabbitMQ. We utilized basic features of RabbitMQ, such as message queuing and delivery. RabbitMQ can be extended with features like message acknowledgment and routing, which adds to its robustness in production environments.

If you’re interested in learning more about RabbitMQ and its functionalities, I recommend checking out the following resources:

By understanding and implementing message brokers like RabbitMQ, you can build scalable and resilient applications that communicate effectively across distributed systems.