RabbitMQ is lightweight broker and easy to on premises and in the cloud. It supports multiple messaging protocols. RabbitMQ can be deployed in distributed and federated configurations to meet high-scale, high-availability requirements. In this tutorial we will learn how we can use Spring Boot to create and consume JMS messages using RabbitMQ broker.Start

StartingRabbitMQ

Before starting our project, we will need to start a RabbitMQ server. The simplest way to get started is to launch a Docker image of it:

$ docker run -d --hostname my-rabbit --name some-rabbit rabbitmq:3-management

Then, we need to find the IP Address assigned to the docker image. This can be done with:

$ docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' container_name_or_id

Now a bit of configuration. We need to connect to the RabbitMQ server and create a Queue and an Exchange. Finally, we will bind the Queue to the Exchange.

In RabbitMQ configuration Exchanges control the routing of messages to queues. Each exchange type defines a specific routing algorithm which the server uses to determine which bound queues a published message should be routed to.

Let's say that our RabbitMQ Server is bound to the IP Address 172.17.0.2, we will connect to its console at the following URL: http://172.17.0.2:15672

Login with guest/guest and add the Exchange named "demoExchange" to the configuration:

rabbitmq tutorial spring boot

Next, create a Queue named "demoQueue", as shown in this picture:

rabbitmq tutorial spring boot

Finally, we need to bind the Exchange to the Queue we have just created:

rabbitmq tutorial spring boot

Creating the projects

In order to start, we will create a consumer and producer project. The consumer will use RabbitMQ dependencies, the producer will also use the web dependencies to expose a rest controller to send messages.

Here is the CLI to create the Consumer project:

$ spring init -damqp spring-rabbit-consumer

The following dependencies will be added:

<dependencies>
   <dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter</artifactId>	
   </dependency>
   <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-amqp</artifactId>
   </dependency>
   <dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-test</artifactId>
	<scope>test</scope>
   </dependency>
</dependencies>

Here is the CLI to create the Producer project:

$ spring init -damqp,web spring-rabbit-producer

These are the dependencies added:

<dependencies>
	<dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter</artifactId>
	</dependency>	
	<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
	<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-amqp</artifactId>
        </dependency>
	<dependency>
		<groupId>org.springframework.boot</groupId>
 	        <artifactId>spring-boot-starter-test</artifactId>
		<scope>test</scope>
	</dependency>
</dependencies>

Coding the RabbitMQ Consumer Project

The Consumer project is the simpler one, as it just includes the Application class and one Listener. Here is the Application class:

package com.example;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class SpringRabbitMqSubcriberApplication {

	public static void main(String[] args) {
		SpringApplication.run(SpringRabbitMqSubcriberApplication.class, args);
	}
}

And here is the Subscriber class which contains the RabbitListener annotation that marks a method to be the target of a Rabbit message listener on the specified queues:

package com.example;

import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;

@Component
public class Subcriber {

	@RabbitListener(queues="${demo.rabbitmq.queue}")
    public void recievedMessage(String msg) {
        System.out.println("Got Message: " + msg);
    }
}

Finally, the subscriber needs information about the host, port, username and password of the RabbitMQ server. We will use the IP Address of the Docker Container for this purpose. We also need to specify the Queue name that will be subscribed:

spring.rabbitmq.host=172.17.0.2
spring.rabbitmq.port=5672
spring.rabbitmq.username=guest
spring.rabbitmq.password=guest
demo.rabbitmq.queue=demoQueue

Coding the RabbitMQ Producer Project

Let's start from the Application class:

package com.example;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class SpringRabbitMqPublisherApplication {

	public static void main(String[] args) {
		SpringApplication.run(SpringRabbitMqPublisherApplication.class, args);
	}
}

Next, we need a class for publishing messages via the AmqpTemplate:

package com.example;

import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

@Component
public class Publisher {
	
	@Autowired
	private AmqpTemplate template;
	
	@Value("${demo.rabbitmq.exchange}")
	private String exchange;
	
	public void produceMsg(String msg){
		template.convertAndSend(exchange, "",msg);
		System.out.println("Sent message: " + msg);
	}
}

Finally, if we want the messages to be sent on demand, we will add a Controller class that uses the autowired Publisher to send messages:

package com.example;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import com.javasampleapproach.rabbitmq.publisher.Publisher;

@RestController
public class WebController {
	
	@Autowired
	Publisher publisher;
	
	@RequestMapping("/send")
	public String sendMsg(@RequestParam("msg")String msg){
		publisher.produceMsg(msg);
		return "Done";
	}
}

That's all. We will complete the project adding the RabbitMQ configuration in the application.properties file:

spring.rabbitmq.host=172.17.0.2
spring.rabbitmq.port=5672
spring.rabbitmq.username=guest
spring.rabbitmq.password=guest
demo.rabbitmq.queue=demoQueue

Running the Projects

That's all. You can run both applications with:

$ ./mvnw spring-boot:run

In order to send messages, you can open the browser and reach the send endpoint with the "msg" parameter:

http://localhost:8080/send?msg=hello

You will see from the Consumer logs:

-18 16:37:46.606  INFO 810 --- [           main] o.s.a.r.c.CachingConnectionFactory       : Created new connection: rabbitConnectionFactory#50d0686:0/SimpleConnection@6e2c9341 [delegate=amqp://This email address is being protected from spambots. You need JavaScript enabled to view it..0.2:5672/, localPort= 39900]
2018-12-18 16:37:46.728  INFO 810 --- [           main] c.j.r.SpringRabbitMqSubcriberApplication : Started SpringRabbitMqSubcriberApplication in 2.298 seconds (JVM running for 2.815)
Got Message: hello