Why WebSocket? Advantages, Comparison, and STOMP on Spring WebSocket
This article explains the limitations of HTTP for real‑time communication, compares WebSocket with polling, long‑polling, streaming and SSE, outlines WebSocket's benefits and typical use cases, and then details how STOMP complements WebSocket within Spring's messaging framework, including configuration and message flow.
1 Why WebSocket?
WebSocket is a full‑duplex protocol over TCP that overcomes HTTP’s limitation of client‑initiated communication, enabling scenarios like online chat where either side can push data instantly.
1.1 Technical alternatives for push scenarios
Before WebSocket, solutions such as Polling, Long‑Polling, iframe/Flash streaming, and Server‑Sent Events (SSE) were used, each with drawbacks in latency, resource consumption, or bidirectional capability.
1.2 Advantages of WebSocket
Bidirectional communication
Low latency
Binary support without format restrictions
Small framing overhead
Extensible via sub‑protocols
1.3 Typical use cases
Real‑time chat, social notifications, multiplayer games, collaborative editing, financial market feeds, location‑based services, etc.
1.4 Comparison with other streaming protocols
WebSocket provides true duplex communication, whereas protocols like HLS, RTMP are oriented to media streaming with different reliability requirements.
2 Why STOMP on WebSocket?
2.1 What is missing from raw WebSocket?
WebSocket defines only the transport; it does not prescribe a message format, routing, or subscription semantics. STOMP supplies a simple text‑based messaging protocol that adds commands, headers, and bodies.
2.2 STOMP basics
STOMP frames consist of a COMMAND, a set of HEADERS, and an optional BODY. Example:
/**
* Handle an inbound message from a WebSocket client.
*/
@Override
public void handleMessage(WebSocketSession session, WebSocketMessage
message) throws Exception {
// Session management omitted for brevity
SubProtocolHandler protocolHandler = findProtocolHandler(session);
protocolHandler.handleMessageFromClient(session, message, this.clientInboundChannel);
// Heart‑beat and cleanup omitted
}
/**
* Handle an outbound Spring Message to a WebSocket client.
*/
@Override
public void handleMessage(Message
message) throws MessagingException {
String sessionId = resolveSessionId(message);
if (sessionId == null) {
logger.error("Couldn't find session id in " + message);
return;
}
WebSocketSessionHolder holder = this.sessions.get(sessionId);
if (holder == null) {
logger.debug("No session for " + message);
return;
}
WebSocketSession session = holder.getSession();
try {
findProtocolHandler(session).handleMessageToClient(session, message);
} catch (Exception ex) {
// error handling omitted
}
}Client commands include CONNECT, SEND, SUBSCRIBE, BEGIN, COMMIT, ABORT, DISCONNECT; server commands include CONNECTED, MESSAGE, RECEIPT, ERROR.
2.3 Spring’s STOMP‑WebSocket solution
Spring 4+ provides spring-websocket and spring-messaging modules. Using @EnableWebSocketMessageBroker and a configuration class you can set up a simple broker, application prefixes, user destinations, and optionally relay messages to RabbitMQ.
3 Understanding the message flow
Pipes‑and‑Filters model
Spring‑messaging implements the Pipes‑and‑Filters pattern with three core interfaces: Message , MessageHandler , and MessageChannel . Handlers act as filters, channels as pipes.
Key components
SubProtocolWebSocketHandler converts between raw WebSocketMessage and protocol‑specific Message objects.
ClientInboundChannel routes incoming messages to handlers such as WebSocketAnnotationMethodMessageHandler , SimpleBrokerMessageHandler , and UserDestinationMessageHandler .
ClientOutboundChannel sends processed messages back through SubProtocolWebSocketHandler .
Three communication modes
Topic‑based broadcast ( /topic/** )
App‑destined request‑response style ( /app/** ) mapped to @MessageMapping methods
User‑specific destinations ( /user/** ) for private messages
Configuration example
@Configuration
@EnableWebSocketMessageBroker
public class StompWebSocketConfig implements WebSocketMessageBrokerConfigurer {
@Autowired
private YqgHandshakeInterceptor yqgHandshakeInterceptor;
@Override
public void configureMessageBroker(MessageBrokerRegistry config) {
config.enableSimpleBroker("/topic");
config.setApplicationDestinationPrefixes("/app");
config.setUserDestinationPrefix("/user");
config.enableStompBrokerRelay("/exchange","/topic","/queue","/amq/queue")
.setVirtualHost("rabbit_mq_host")
.setRelayHost("localhost")
.setClientLogin("root")
.setClientPasscode("root")
.setSystemLogin("root")
.setSystemPasscode("root")
.setSystemHeartbeatSendInterval(5000)
.setSystemHeartbeatReceiveInterval(4000);
}
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/establish-websocket-sockjs").withSockJS();
registry.addEndpoint("/establish-websocket")
.setAllowedOrigins("*")
.setHandshakeHandler(handshakeHandler())
.addInterceptors(yqgHandshakeInterceptor);
}
@Override
public void configureClientInboundChannel(ChannelRegistration registration) {
registration.setInterceptors(webSocketInterceptor);
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(5);
executor.setMaxPoolSize(100);
executor.setQueueCapacity(1000);
executor.setKeepAliveSeconds(1000);
executor.setThreadNamePrefix("yqg");
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.AbortPolicy());
registration.taskExecutor(executor);
}
}4 Conclusion
WebSocket provides efficient, low‑overhead, bidirectional communication for real‑time applications. Adding STOMP via Spring’s WebSocket support supplies a robust messaging model, seamless integration with other Spring projects, and optional broker relay to systems like RabbitMQ, making it a practical choice for modern backend development.
Yang Money Pot Technology Team
Enhancing service efficiency with technology.
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.