How to connect to multiple RabbitMQ instances using Spring Cloud Stream

Raphael De Lio
5 min readApr 16, 2022

Twitter | LinkedIn | YouTube | Instagram

Spring Cloud Stream is a framework for building highly scalable event-driven microservices connected with shared messaging systems.

The framework introduces three main components that allow developers to utilize messaging in their code:

  1. Binder — The component that implements communication with a specific message broker. For example, there is a RabbitMQ Binder, a Kafka Binder, and so on.
  2. Binding — The interface for sending and receiving messages. This component links the abstract channels in your code with a topic or queue that’s handled by the binder.
  3. Message — The data structure used to communicate with the bindings between your code and your message broker. How this data is packaged and communicated over the message broker is determined by the binder.

In this tutorial we will be learning how to connect to two or more RabbitMQ instances and how to exchange messages among them.

Let’s put our hands in the fire!

Getting RabbitMQ running

Let’s get started by running two different instances of RabbitMQ using Docker.

Let’s pull the image with the management plugin installed:

docker pull rabbitmq:3-management

And then run the first one exposed to ports 15672 and 5672:

docker run --rm -it -p 15672:15672 -p 5672:5672 rabbitmq:3-management

And the second one exposed to ports 15671 and 5671:

docker run --rm -it -p 15671:15672 -p 5671:5672 rabbitmq:3-management

You can check they are running by accessing localhost:15671 and localhost:15672 and logging in with username guest and password guest

You should be able to see something like in both cases:

Setting up our application

Now that we have our instances of RabbitMQ working locally, let’s setup a Spring Boot application to set up our connections.

I’m setting it up using Spring Initializr with Gradle and Kotlin. You can do it the way you prefer, but we will need the following dependencies in our project:

dependencies {
implementation("org.springframework.boot:spring-boot-starter-amqp")
implementation("org.springframework.cloud:spring-cloud-stream")
implementation("org.springframework.cloud:spring-cloud-stream-binder-rabbit")
}

Now that we have our application set up, let’s edit our application.yml file and add the following properties to tell Spring Cloud Stream which Rabbit instances we would like to be connecting to:

spring:
cloud:
stream:
binders:
coolrabbit:
type: rabbit
environment:
spring:
rabbitmq:
host: localhost
port: 5671
awesomerabbit:
type: rabbit
environment:
spring:
rabbitmq:
host: localhost
port: 5672

In this example, we will be calling the first one coolrabbit and the second one awesomerabbit , you can call them whatever you want though.

Now, let’s define a function in our application to process messages sent coolrabbit and deliver them to awesomerabbit afterwards:

@Bean
fun toUpperCase(): Function<String, String> {
return Function<String, String> { input ->
val output = input.uppercase()
output
}
}

This Bean is responsible for receiving messages as a String, converting them to upper case and sending them back as a String.

Now that we have our function defined, let’s see how you can set up our application to bind this function to the right queues and binders.

First, we need to tell Spring Cloud Stream which functions we will be using. We can do it by adding the following property:

spring:
cloud:
stream:
function:
definition: toUpperCase

And to which queues and binders we should bind this function to:

spring:
cloud:
stream:
bindings:
toUpperCase-in-0:
destination: TOUPPERCASE # exchange
group: INPUT # queue
binder: coolrabbit
toUpperCase-out-0:
destination: TOUPPERCASE # exchange
group: OUTPUT # queue
binder: awesomerabbit
producer:
requiredGroups:
- OUTPUT # to create the queue automatically

In the end, the file should look like this:

spring:
cloud:
stream:
binders:
coolrabbit:
type: rabbit
environment:
spring:
rabbitmq:
host: localhost
port: 5671
awesomerabbit:
type: rabbit
environment:
spring:
rabbitmq:
host: localhost
port: 5672
function:
definition: toUpperCase
bindings:
toUpperCase-in-0:
destination: TOUPPERCASE # exchange
group: INPUT # queue
binder: coolrabbit
toUpperCase-out-0:
destination: TOUPPERCASE
group: OUTPUT
binder: awesomerabbit
producer:
requiredGroups:
- OUTPUT # to create the queue automatically

Cool! Let’s run and test our application!

I’m very happy you got to this part of the story, I‘m truly thankful for this.
Support my work: follow me and clap to this story.

Testing the application

Let’s run our application and connect to the coolrabbit by going to localhost:15671 . You should see our TOUPPERCASE.INPUT queue in the Queues tab:

Let’s manually publish a message to this queue:

Now, let’s connect to awesomerabbit by going to localhost:15672 . In the Queues tab you should see our TOUPPERCASE.OUTPUT queue with one message ready in it:

Let’s get this message and see its payload:

Awesome! We can see that our application consumed the message from coolrabbit , processed it by turning its content into upper case and delivered it to awesomerabbit ! Pretty easy, wasn’t it?

You can check this implementation’s source code on my GitHub:

I hope you have enjoyed this tutorial! Happy coding!

Contribute

Writing takes time and effort. I love writing and sharing knowledge, but I also have bills to pay. If you like my work, please, consider donating through Buy Me a Coffee: https://www.buymeacoffee.com/RaphaelDeLio

Or by sending me BitCoin: 1HjG7pmghg3Z8RATH4aiUWr156BGafJ6Zw

Follow Me on Social Media

Stay connected and dive deeper into the world of Spring with me! Follow my journey across all major social platforms for exclusive content, tips, and discussions.

Twitter | LinkedIn | YouTube | Instagram

--

--

Raphael De Lio

Software Consultant @ Xebia - Dutch Kotlin User Group Organizer: https://kotlin.nl