Websocket Spring Boot
title: "WebSocket with Spring Boot" description: "Learn how to implement WebSocket in Spring Boot applications using STOMP protocol, WebSocket handlers, and SockJS fallback." weight: 28 date: 2026-06-28 lastmod: 2026-06-28 tags: ["apis", "websocket"]
Spring Boot provides comprehensive WebSocket support through raw WebSocket handlers and the STOMP protocol sub-protocol. This lesson covers both approaches with configuration, messaging, and security.
## What You'll Learn
- Spring WebSocket configuration
- STOMP message broker setup
- WebSocket handlers
- SockJS fallback support
- WebSocket security in Spring
## Why It Matters
Spring Boot is a popular Java framework for building microservices. Native WebSocket support allows Java developers to add real-time features without additional infrastructure.
## Real-World Use
A Java-based trading platform uses Spring Boot with STOMP over WebSocket to stream real-time market data. Traders subscribe to stock symbols and receive price updates via STOMP topics.
## Flow Chart
```mermaid
flowchart LR
A[Client] -->|STOMP over WS| B[Spring Boot Server]
B --> C[WebSocket Handler]
B --> D[STOMP Broker]
C --> E[Raw WS Messages]
D --> F[Topics / Queues]
D --> G[Message Mapping]
E --> H[Application Handler]
F --> I[Subscribers]
Code Examples
Example 1: STOMP WebSocket Configuration
import org.springframework.context.annotation.Configuration;
import org.springframework.messaging.simp.config.MessageBrokerRegistry;
import org.springframework.web.socket.config.annotation.*;
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
@Override
public void configureMessageBroker(MessageBrokerRegistry config) {
// Prefix for messages from server to clients
config.enableSimpleBroker("/topic", "/queue");
// Prefix for messages from clients to server
config.setApplicationDestinationPrefixes("/app");
// Prefix for user-specific messages
config.setUserDestinationPrefix("/user");
}
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/ws")
.setAllowedOrigins("https://app.example.com")
.withSockJS(); // Enable SockJS fallback
}
}
Expected output: Spring Boot WebSocket with STOMP broker, configured for topics and queues, with SockJS fallback for browsers that do not support WebSocket.
Example 2: STOMP Message Controller
import org.springframework.messaging.handler.annotation.MessageMapping;
import org.springframework.messaging.handler.annotation.SendTo;
import org.springframework.messaging.simp.SimpMessagingTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.beans.factory.annotation.Autowired;
@Controller
public class WebSocketController {
@Autowired
private SimpMessagingTemplate messagingTemplate;
// Handle incoming message, broadcast to all subscribers
@MessageMapping("/chat.sendMessage")
@SendTo("/topic/public")
public ChatMessage sendMessage(ChatMessage message) {
message.setTimestamp(System.currentTimeMillis());
return message;
}
// Handle typing events
@MessageMapping("/chat.addUser")
@SendTo("/topic/public")
public ChatMessage addUser(ChatMessage message) {
message.setType(ChatMessage.MessageType.JOIN);
return message;
}
// Send to specific user
@MessageMapping("/chat.private")
public void sendPrivateMessage(ChatMessage message) {
messagingTemplate.convertAndSendToUser(
message.getRecipient(),
"/queue/private",
message
);
}
// Send to specific topic
public void broadcastUpdate(String topic, Object payload) {
messagingTemplate.convertAndSend("/topic/" + topic, payload);
}
}
// Message model
class ChatMessage {
public enum MessageType { CHAT, JOIN, LEAVE }
private MessageType type;
private String content;
private String sender;
private String recipient;
private long timestamp;
// getters and setters
}
Expected output: STOMP controller handles public chat messages, user join/leave events, and private messaging via SimpMessagingTemplate.
Example 3: Spring WebSocket Security
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.messaging.MessageSecurityMetadataSourceRegistry;
import org.springframework.security.config.annotation.web.socket.AbstractSecurityWebSocketMessageBrokerConfigurer;
@Configuration
public class WebSocketSecurityConfig extends AbstractSecurityWebSocketMessageBrokerConfigurer {
@Override
protected void configureInbound(MessageSecurityMetadataSourceRegistry messages) {
messages
// Public endpoints
.simpDestMatchers("/topic/public").permitAll()
// Authenticated endpoints
.simpDestMatchers("/app/**").authenticated()
// User-specific destinations
.simpDestMatchers("/user/**", "/queue/**").authenticated()
// Admin-only destinations
.simpDestMatchers("/topic/admin/**").hasRole("ADMIN")
// Any other destination requires authentication
.anyMessage().authenticated();
}
@Override
protected boolean sameOriginDisabled() {
// Allow cross-origin (needed for SockJS from different domains)
return true;
}
}
// JWT Authentication interceptor
@Component
public class WebSocketAuthInterceptor implements ChannelInterceptor {
@Override
public Message<?> preSend(Message<?> message, MessageChannel channel) {
StompHeaderAccessor accessor =
StompHeaderAccessor.wrap(message);
if (StompCommand.CONNECT.equals(accessor.getCommand())) {
String token = accessor.getFirstNativeHeader("Authorization");
if (token != null && token.startsWith("Bearer ")) {
String jwt = token.substring(7);
try {
// Validate JWT and set authentication
Authentication auth = validateToken(jwt);
accessor.setUser(auth);
} catch (Exception e) {
throw new AuthenticationCredentialsNotFoundException(
"Invalid token");
}
}
}
return message;
}
}
Expected output: WebSocket messages secured with Spring Security, role-based destination access, and JWT authentication at the STOMP CONNECT frame.
Common Mistakes
| Mistake | Explanation |
|---|---|
| Not configuring CORS properly | SockJS from different origins requires explicit CORS configuration |
| Using too many STOMP destinations | Keep destination hierarchy simple to avoid confusion |
| Forgetting to enable SockJS | Not all browsers support WebSocket; SockJS provides automatic fallback |
| Mixing raw WebSocket and STOMP | Choose one approach; STOMP adds messaging semantics on top of WebSocket |
| Not handling session cleanup | Clean up subscriptions and resources when WebSocket sessions end |
Practice Questions
- What is the difference between STOMP and raw WebSocket?
- How do you configure STOMP destinations in Spring Boot?
- What is the purpose of SimpMessagingTemplate?
- How do you secure WebSocket endpoints in Spring Boot?
- What is SockJS and when should you use it?
Challenge
Build a Spring Boot WebSocket application for a collaborative task board. Users can create, update, and move tasks in real time. Use STOMP for messaging, Spring Security for authentication, and SockJS for browser compatibility.
FAQ
Mini Project
Build a real-time collaboration tool with Spring Boot WebSocket and STOMP. Implement document editing with cursor position sharing, chat, and presence indicators. Use Spring Security with JWT authentication and SockJS for browser compatibility.
What's Next
Build a complete WebSocket project
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro