Spring Boot WebSocket

WebSocket STOMP refers to using the STOMP protocol (Simple/Streaming Text Oriented Messaging Protocol) over a WebSocket connection.

Here’s the breakdown:

1. WebSocket

  • A communication protocol that provides full-duplex, bidirectional communication between client and server over a single TCP connection.
  • Unlike HTTP (request-response), WebSockets let the server push messages to the client in real time.

2. STOMP

  • Short for Simple (or Streaming) Text-Oriented Messaging Protocol.
  • A simple text-based protocol for working with message brokers (like ActiveMQ, RabbitMQ, etc.).
  • Defines a standard way to send and subscribe to messages (frames with commands like SEND, SUBSCRIBE, UNSUBSCRIBE, ACK, etc.).

2. Configure WebSocket with STOMP

import org.springframework.context.annotation.Configuration;
import org.springframework.messaging.simp.config.MessageBrokerRegistry;
import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
import org.springframework.web.socket.config.annotation.StompEndpointRegistry;
import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer;

@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {

    @Override
    public void configureMessageBroker(MessageBrokerRegistry config) {
        config.enableSimpleBroker("/topic"); // topic for subscriptions
        config.setApplicationDestinationPrefixes("/app"); // prefix for messages from client
    }

    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry) {
        registry.addEndpoint("/ws").withSockJS(); // endpoint for WebSocket handshake
    }
}

3. Create a Message Model

public class ChatMessage {
    private String sender;
    private String content;

    // Getters and setters
    public String getSender() { return sender; }
    public void setSender(String sender) { this.sender = sender; }
    public String getContent() { return content; }
    public void setContent(String content) { this.content = content; }
}

4. Create a Controller to handle messages

import org.springframework.messaging.handler.annotation.MessageMapping;
import org.springframework.messaging.handler.annotation.SendTo;
import org.springframework.stereotype.Controller;

@Controller
public class ChatController {

    @MessageMapping("/chat") // /app/chat
    @SendTo("/topic/messages")
    public ChatMessage send(ChatMessage message) throws Exception {
        // Could add timestamp, validation, etc.
        return message;
    }
}

5. Thymeleaf HTML Client (src/main/resources/templates/chat.html)

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <title>WebSocket Chat</title>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/sockjs-client/1.5.2/sockjs.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/stomp.js/2.3.3/stomp.min.js"></script>
</head>
<body>
<h2>Chat</h2>
<div>
    <input type="text" id="sender" placeholder="Name">
    <input type="text" id="message" placeholder="Message">
    <button onclick="sendMessage()">Send</button>
</div>

<ul id="messages"></ul>

<script>
    let stompClient = null;

    function connect() {
        const socket = new SockJS('/ws');
        stompClient = Stomp.over(socket);
        stompClient.connect({}, function(frame) {
            console.log('Connected: ' + frame);
            stompClient.subscribe('/topic/messages', function(msg){
                showMessage(JSON.parse(msg.body));
            });
        });
    }

    function sendMessage() {
        const sender = document.getElementById('sender').value;
        const content = document.getElementById('message').value;
        stompClient.send("/app/chat", {}, JSON.stringify({sender: sender, content: content}));
    }

    function showMessage(message) {
        const messages = document.getElementById('messages');
        const li = document.createElement('li');
        li.appendChild(document.createTextNode(message.sender + ": " + message.content));
        messages.appendChild(li);
    }

    connect();
</script>
</body>
</html>

How it works:

  1. Client connects via SockJS /ws.
  2. Sends messages to /app/chat (handled by @MessageMapping in controller).
  3. Server broadcasts to /topic/messages.
  4. All subscribed clients receive the message.

Leave a Reply