Message-Oriented Middleware (MOM)
1. What is Message-Oriented Middleware (MOM)?
Message-Oriented Middleware (MOM) is a software layer that facilitates communication between distributed systems by sending messages between them. It decouples the sender and receiver, allowing them to communicate asynchronously. Here are some key features:
- Decoupling : The sender and receiver do not need to know each other's existence or state.
- Asynchronous Communication : Messages can be sent and received at different times.
- Reliability : Messages can be queued and stored until they are processed.
- Scalability : The system can easily scale by adding more consumers or producers.
2. Synchronous vs. Asynchronous Communication
Synchronous Communication :
- The sender waits for the receiver to process the message and send a response.
- This can lead to blocking operations, which can reduce system performance and increase latency.
- Example: HTTP requests in RESTful services.
Asynchronous Communication :
- The sender sends a message and continues its processing without waiting for a response.
- This improves system performance and responsiveness.
- Example: Sending messages to a message broker (like RabbitMQ or Kafka) and processing them later.
graph TD
Producer1[Producer 1] -->|Sends Message| Queue1[Queue 1]
Producer2[Producer 2] -->|Sends Message| Queue1
Queue1 -->|Delivers Message| Consumer1[Consumer 1]
Queue1 -->|Delivers Message| Consumer2[Consumer 2]
subgraph Broker
Exchange[Exchange] -->|Routes Messages| Queue1
Exchange -->|Routes Messages| Queue2[Queue 2]
end
Producer3[Producer 3] -->|Sends Message| Exchange
Queue2 -->|Delivers Message| Consumer3[Consumer 3]
Consumer3 -->|Acknowledges| Queue2
classDef highlight fill:#f9f,stroke:#333,stroke-width:2px;
class Queue1,Queue2 highlight;
RabbitMQ is a message broker that facilitates communication between different systems, applications, or services by enabling them to exchange messages asynchronously.
It implements the Advanced Message Queuing Protocol (AMQP) and supports other protocols like MQTT and STOMP
Producers:
- Producer 1, Producer 2, and Producer 3 send messages to RabbitMQ.
- Producers do not directly communicate with consumers; they rely on RabbitMQ to handle the routing.
Exchange:
- RabbitMQ's Exchange determines how messages are routed to the appropriate queue(s) based on routing rules.
- Different exchange types (e.g., direct, topic, fanout) allow for various routing patterns.
Queues:
- Messages are stored in Queue 1 and Queue 2 until consumers are ready to process them.
- Queues act as buffers between producers and consumers.
Consumers:
- Consumer 1 and Consumer 2 consume messages from Queue 1, enabling load balancing.
- Consumer 3 consumes messages from Queue 2 and sends an acknowledgment to RabbitMQ once a message is processed.
Acknowledgments:
- Consumers send acknowledgments to RabbitMQ to confirm successful message processing.
- If a consumer fails, RabbitMQ re-queues the message for another consumer.
3. Why Use MOM?
- Loose Coupling : Systems can evolve independently.
- Scalability : New services can be added or existing ones can be modified without affecting others.
- Flexibility : Supports different protocols and message formats.
- Resilience : Ensures messages are not lost even if the receiver is down.
4. How to Implement a Project
We will create a simple Spring Cloud project to illustrate these concepts. We'll use RabbitMQ as our message broker.
Project Structure
- Service A (Producer)
- Service B (Consumer)
Setting Up RabbitMQ

Install Erlang OTP:
- RabbitMQ requires Erlang to run.
- Download the latest Erlang/OTP installer for Windows from the Erlang website.
- Install it by following the on-screen instructions.
- Set
ERLANG_HOME
:- Add the Erlang installation path (e.g.,
C:\Program Files\erl-XX.X
) to theERLANG_HOME
environment variable.
- Add the Erlang installation path (e.g.,
Install RabbitMQ:
- Download RabbitMQ from the RabbitMQ website.
- Choose the appropriate version for your system and install it.
What is Erlang?
functional programming language and runtime system designed for building highly concurrent, distributed, and fault-tolerant applications.It was originally developed by Ericsson in the 1980s for use in telecommunications systems but has since been used in a variety of domains requiring robust and scalable solutions.
-module(hello).
-export([start/0, say_hello/1]).
say_hello(Name) ->
io:format("Hello, ~p!~n", [Name]).
start() ->
spawn(fun() -> say_hello("Erlang") end).
Install Erlang
go to https://www.erlang.org/downloads install itadd the installation folder to:
ERLANG_HOME:C:\Program Files\Erlang OTP
Install rabbitmq
go to https://www.rabbitmq.com/docs/install-windows-manualExtract the software
run CMD as administrator
go to innstalation folder of rabbitmq:
cd C:\Users\user\Desktop\jee\rabbitmq-server-windows-4.0.3\rabbitmq_server-4.0.3\sbin
run rabbitmq:
rabbitmq-plugins enable rabbitmq_management
rabbitmq-service install
rabbitmq-service start
go to http://localhost:15672/
username :guestpassword:guest

1. Connections
- Definition: A Connection is the TCP connection between a client (e.g., a producer or consumer) and the RabbitMQ server.
- Purpose: It is the physical link that allows clients to send and receive messages from RabbitMQ. Each connection can have multiple channels.
2. Channels
- Definition: A Channel is a virtual connection within a Connection.
- Purpose: It allows multiple communication streams over a single connection, making it more efficient to send and receive messages.
3. Exchanges
- Definition: An Exchange is responsible for routing messages to queues based on certain rules (e.g., routing keys).
- Purpose: It determines how to deliver messages to one or more queues based on routing logic.
4. Queues
- Definition: A Queue is a buffer where messages are stored until they are consumed by a consumer.
- Purpose: It holds messages for future processing. Each message in a queue is consumed by a single consumer (unless shared).
graph TD
%% Connections
A[Producer] -->|Creates Connection| B[Connection]
%% Channels within Connection
B -->|Uses Channel| C[Channel]
%% Exchange routing
C -->|Routes Message to Exchange| D[Exchange]
%% Queues and Consumers
D -->|Routes to Queue| E[Queue]
E -->|Delivers Message| F[Consumer]
%% Streams (for large data processing)
E -->|Persistent Storage| G[Stream]
%% Connections and Components Relationship
B --> C
F -->|Processes Message| E
Create Spring Boot Applications
Service A (Producer)Create a Spring Boot Application
Use Spring Initializr (https://start.spring.io/) to create a Spring Boot application named service-a with the following dependencies:
Spring Web
Spring for RabbitMQ
Configure Application Properties
In src/main/resources/application.properties, add the following RabbitMQ configuration:
spring.rabbitmq.host=localhost
spring.rabbitmq.port=5672
Create a Message Producer
Create a REST controller to send messages. Create a new class MessageController:
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class MessageController {
@Autowired
private RabbitTemplate rabbitTemplate;
@PostMapping("/send")
public String sendMessage(@RequestBody String message) {
rabbitTemplate.convertAndSend("myQueue", message);
return "Message sent: " + message;
}
}
Explanation:
The @RestController annotation indicates that this class will handle HTTP requests.
The RabbitTemplate is used to send messages to the RabbitMQ broker. We inject it using @Autowired.
The sendMessage method listens for POST requests on /send, sends the received message to the queue named myQueue, and returns a confirmation response.
Create a RabbitMQ Configuration Class
Create a configuration class RabbitConfig to set up the RabbitMQ queue and exchange:
import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.core.TopicExchange;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class RabbitConfig {
@Bean
public Queue myQueue() {
return new Queue("myQueue", false);
}
@Bean
public TopicExchange exchange() {
return new TopicExchange("myExchange");
}
@Bean
public Binding binding(Queue myQueue, TopicExchange exchange) {
return BindingBuilder.bind(myQueue).to(exchange).with("myQueue");
}
}
Explanation:
The @Configuration annotation indicates that this class contains bean definitions.
The myQueue method creates a new queue named myQueue.
The exchange method defines a topic exchange named myExchange.
The binding method binds the queue to the exchange with a routing key, allowing messages sent to the exchange to reach the queue.
Service B (Consumer)
Create Another Spring Boot Application
Create a Spring Boot application named service-b with the same dependencies (Spring Web, Spring for RabbitMQ).Configure Application Properties
In src/main/resources/application.properties, add the RabbitMQ configuration:
spring.rabbitmq.host=localhost
spring.rabbitmq.port=5672
Create a Message Listener
Create a new class MessageListener to listen for messages from the queue:
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Service;
@Service
public class MessageListener {
@RabbitListener(queues = "myQueue")
public void receiveMessage(String message) {
System.out.println("Received message: " + message);
}
}
Explanation:
The @Service annotation indicates that this class is a Spring service.
The @RabbitListener annotation marks the receiveMessage method as a listener for messages on the myQueue queue.
When a message is received, the method prints it to the console.
Running the Applications
Start service-b first, as it will listen for incoming messages.Start service-a next. Use a tool like Postman or curl to send a POST request to http://localhost:8080/send with a message body. For example:
curl -X POST http://localhost:8080/send -d "Hello, RabbitMQ!"
Check the Console of service-b: You should see the received message printed in the console.
4. Conclusion
In this project, we have created a simple producer-consumer setup using RabbitMQ and Spring Cloud:
Service A sends messages to a RabbitMQ queue.
Service B listens for those messages and processes them asynchronously.