Build Real‑Time Chat with RabbitMQ MQTT and Zero Backend Code
This guide explains how to enable MQTT support in RabbitMQ, use MQTTBox and MQTT.js for instant messaging, and integrate MQTT into a SpringBoot application, providing step‑by‑step commands, code snippets, and configuration details for both front‑end and back‑end developers.
MQTT Protocol
MQTT (Message Queuing Telemetry Transport) is a lightweight publish/subscribe messaging protocol built on TCP/IP, offering real‑time reliable messaging with minimal code and bandwidth.
Key Concepts
Publisher – the entity that sends messages.
Subscriber – the entity that receives and processes messages.
Broker – mediates between publishers and subscribers; any MQTT‑compatible middleware can act as a broker.
Topic – the routing identifier for messages; subscribers receive messages published to the topics they subscribe to.
Payload – the actual content of a message.
QoS – Quality of Service levels:
QoS 0 (At most once): message may be lost or duplicated.
QoS 1 (At least once): message is guaranteed to arrive but may be duplicated.
QoS 2 (Exactly once): message arrives exactly once.
Enabling MQTT in RabbitMQ
RabbitMQ can provide instant‑messaging via MQTT by installing the broker and enabling the MQTT plugin.
Install and start RabbitMQ (refer to the official installation guide).
Enable the MQTT plugin:
<code>rabbitmq-plugins enable rabbitmq_mqtt</code>After enabling, the MQTT service listens on port
1883.
Testing with MQTTBox Client
Use MQTTBox to test MQTT communication.
Download and install MQTTBox from
http://workswithweb.com/mqttbox.html.
Create a client, configure the broker address, port, username, password, and QoS.
Subscribe to a topic (e.g.,
testTopicA) and publish messages to verify real‑time delivery.
Front‑End Real‑Time Chat Without Backend Code
By enabling RabbitMQ's Web MQTT plugin, a web page can communicate via WebSocket.
Enable the Web MQTT plugin:
<code>rabbitmq-plugins enable rabbitmq_web_mqtt</code>The Web MQTT service runs on port
15675.
Use the
MQTT.jslibrary in the browser to connect to
ws://localhost:15675/ws, subscribe to a topic, and publish messages.
<code><!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Simple Chat</title>
</head>
<body>
<div>
<label>Target Topic: <input id="targetTopicInput" type="text"></label><br>
<label>Message: <input id="messageInput" type="text"></label><br>
<button onclick="sendMessage()">Send</button>
<button onclick="clearMessage()">Clear</button>
<div id="messageDiv"></div>
</div>
<script src="https://unpkg.com/mqtt/dist/mqtt.min.js"></script>
<script>
const url = 'ws://localhost:15675/ws';
const topic = getQueryString('topic');
let client = mqtt.connect(url);
client.on('connect', function () {
client.subscribe(topic, function (err) {
if (!err) { showMessage('Subscribed to topic: ' + topic); }
});
});
client.on('message', function (topic, message) {
showMessage('Received: ' + message.toString());
});
function sendMessage() {
const targetTopic = document.getElementById('targetTopicInput').value;
const message = document.getElementById('messageInput').value;
client.publish(targetTopic, message);
showMessage('Sent to ' + targetTopic + ': ' + message);
}
function getQueryString(name) {
const reg = new RegExp('(^|&)' + name + '=([^&]*)(&|$)', 'i');
const r = window.location.search.substr(1).match(reg);
if (r != null) { return decodeURIComponent(r[2]); }
return null;
}
function showMessage(message) {
const messageDiv = document.getElementById('messageDiv');
const messageEle = document.createElement('div');
messageEle.innerText = message;
messageDiv.appendChild(messageEle);
}
function clearMessage() {
document.getElementById('messageDiv').innerHTML = '';
}
</script>
</body>
</html></code>Integrating MQTT into SpringBoot
When server‑side notification is required, integrate MQTT with SpringBoot.
Add the dependency
spring-integration-mqttto
pom.xml.
<code><dependency>
<groupId>org.springframework.integration</groupId>
<artifactId>spring-integration-mqtt</artifactId>
</dependency></code>Configure connection details in
application.yml:
<code>rabbitmq:
mqtt:
url: tcp://localhost:1883
username: guest
password: guest
defaultTopic: testTopic</code>Create a configuration class to bind these properties.
<code>@Data
@EqualsAndHashCode(callSuper = false)
@Component
@ConfigurationProperties(prefix = "rabbitmq.mqtt")
public class MqttConfig {
private String username;
private String password;
private String defaultTopic;
private String url;
}</code>Define inbound channel and adapter with
@ServiceActivatorto handle incoming messages:
<code>@Configuration
public class MqttInboundConfig {
@Autowired
private MqttConfig mqttConfig;
@Bean
public MessageChannel mqttInputChannel() { return new DirectChannel(); }
@Bean
public MessageProducer inbound() {
MqttPahoMessageDrivenChannelAdapter adapter =
new MqttPahoMessageDrivenChannelAdapter(mqttConfig.getUrl(), "subscriberClient", mqttConfig.getDefaultTopic());
adapter.setCompletionTimeout(5000);
adapter.setConverter(new DefaultPahoMessageConverter());
adapter.setQos(1);
adapter.setOutputChannel(mqttInputChannel());
return adapter;
}
@Bean
@ServiceActivator(inputChannel = "mqttInputChannel")
public MessageHandler handler() {
return message -> log.info("handleMessage : {}", message.getPayload());
}
}
</code>Define outbound channel, client factory, and gateway to publish messages:
<code>@Configuration
public class MqttOutboundConfig {
@Autowired
private MqttConfig mqttConfig;
@Bean
public MqttPahoClientFactory mqttClientFactory() {
DefaultMqttPahoClientFactory factory = new DefaultMqttPahoClientFactory();
MqttConnectOptions options = new MqttConnectOptions();
options.setServerURIs(new String[]{ mqttConfig.getUrl() });
options.setUserName(mqttConfig.getUsername());
options.setPassword(mqttConfig.getPassword().toCharArray());
factory.setConnectionOptions(options);
return factory;
}
@Bean
public MessageChannel mqttOutboundChannel() { return new DirectChannel(); }
@Bean
@ServiceActivator(inputChannel = "mqttOutboundChannel")
public MessageHandler mqttOutbound() {
MqttPahoMessageHandler handler = new MqttPahoMessageHandler("publisherClient", mqttClientFactory());
handler.setAsync(true);
handler.setDefaultTopic(mqttConfig.getDefaultTopic());
return handler;
}
}
</code>Create a gateway interface:
<code>@Component
@MessagingGateway(defaultRequestChannel = "mqttOutboundChannel")
public interface MqttGateway {
void sendToMqtt(String payload);
void sendToMqtt(String payload, @Header(MqttHeaders.TOPIC) String topic);
void sendToMqtt(@Header(MqttHeaders.TOPIC) String topic, @Header(MqttHeaders.QOS) int qos, String payload);
}
</code>Expose a REST controller to trigger publishing:
<code>@RestController
@RequestMapping("/mqtt")
public class MqttController {
@Autowired
private MqttGateway mqttGateway;
@PostMapping("/sendToDefaultTopic")
public CommonResult sendToDefaultTopic(String payload) {
mqttGateway.sendToMqtt(payload);
return CommonResult.success(null);
}
@PostMapping("/sendToTopic")
public CommonResult sendToTopic(String payload, String topic) {
mqttGateway.sendToMqtt(payload, topic);
return CommonResult.success(null);
}
}
</code>Conclusion
Message middleware such as RabbitMQ is increasingly used for reliable asynchronous communication and instant messaging. For simple use‑cases, front‑end clients can directly use MQTT; for more complex scenarios, integrating MQTT into a SpringBoot application provides a robust, extensible solution.
macrozheng
Dedicated to Java tech sharing and dissecting top open-source projects. Topics include Spring Boot, Spring Cloud, Docker, Kubernetes and more. Author’s GitHub project “mall” has 50K+ stars.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.