What is STOMP over WebSocket in Spring, and what does @EnableWebSocketMessageBroker set up?
answer
- WebSocket = pipe, STOMP = pub/sub on top
- @EnableWebSocketMessageBroker + WebSocketMessageBrokerConfigurer
- registerStompEndpoints + configureMessageBroker
- SUBSCRIBE / SEND / MESSAGE frames
- /ws endpoint, withSockJS fallback
basics
~20 sWebSocket is a raw two-way connection; STOMP is a simple text messaging protocol layered on top that adds destinations (like topics). @EnableWebSocketMessageBroker turns on Spring's message-broker support so clients can subscribe and publish over WebSocket.
solid answer
~40 sA raw WebSocket only gives you a bidirectional byte/text pipe with no message semantics. STOMP (Simple Text Oriented Messaging Protocol) is a lightweight, frame-based sub-protocol that adds a pub/sub model on top: clients SUBSCRIBE to destinations and SEND to destinations. Spring's @EnableWebSocketMessageBroker (on a @Configuration class implementing WebSocketMessageBrokerConfigurer) activates the full messaging stack: you register the STOMP endpoint clients connect to (registerStompEndpoints), and configure the message broker and destination prefixes (configureMessageBroker). This lets you write @MessageMapping controller methods that handle incoming messages and route outgoing ones to a broker, rather than manually managing raw WebSocketHandler callbacks. It's the higher-level programming model, analogous to how @RestController sits above raw servlets.
code
java · 15 lines@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/ws").withSockJS();
}
@Override
public void configureMessageBroker(MessageBrokerRegistry registry) {
registry.setApplicationDestinationPrefixes("/app");
registry.enableSimpleBroker("/topic", "/queue");
}
}go deeper
Know that WebSocket is the transport and STOMP adds pub/sub semantics; @EnableWebSocketMessageBroker turns it on.
Be able to write the config class with both override methods and explain the client message flow.
Explain how the annotation handler, channels, and broker wire together, and the security implications of per-frame authorization.
Weigh STOMP-over-WebSocket vs SSE vs raw WebSocket, and factor in the operational cost of the messaging stack for the use case.
### The layers **WebSocket** is a transport: after an HTTP handshake it upgrades the connection to a persistent, full-duplex TCP channel over which either side can push text or binary frames at any time. But WebSocket by itself defines *no application semantics* — no concept of a 'topic', 'subscribe', or message routing. If you used Spring's raw `WebSocketHandler`, you'd have to invent your own message format and routing. **STOMP** (Simple/Streaming Text Oriented Messaging Protocol) is a simple, broker-neutral sub-protocol negotiated during the WebSocket handshake (`Sec-WebSocket-Protocol: v12.stomp`). It gives you a small set of frame commands — `CONNECT`, `SUBSCRIBE`, `SEND`, `MESSAGE`, `UNSUBSCRIBE`, `ACK`, `DISCONNECT` — each with a command line, headers (including a `destination`), and a body. This makes the connection a **pub/sub messaging channel**: clients subscribe to destinations like `/topic/prices` and send to destinations like `/app/greeting`. ### What @EnableWebSocketMessageBroker does Put it on a `@Configuration` class that implements `WebSocketMessageBrokerConfigurer`. It imports Spring's messaging infrastructure and expects you to override two methods: - `registerStompEndpoints(StompEndpointRegistry)` — declares the HTTP URL where clients open the WebSocket + STOMP connection, e.g. `registry.addEndpoint("/ws").withSockJS()`. `withSockJS()` adds a fallback for browsers/proxies that can't do native WebSocket. - `configureMessageBroker(MessageBrokerRegistry)` — declares destination prefixes and which broker handles them (see below). Once enabled, Spring wires up: a `clientInboundChannel` (messages from clients), a `SimpAnnotationMethodMessageHandler` that dispatches to your `@MessageMapping` methods, the broker (simple in-memory or a relay to RabbitMQ/ActiveMQ), and a `clientOutboundChannel` (messages back to clients). ### The message flow 1. Client opens WebSocket to `/ws`, sends STOMP `CONNECT`. 2. Client `SUBSCRIBE`s to `/topic/greetings`. 3. Client `SEND`s to `/app/hello`. 4. Spring routes `/app/**` messages to your `@MessageMapping("/hello")` controller method (application destinations). 5. The method's return value (with `@SendTo("/topic/greetings")`) is published to the broker, which fans it out to all subscribers. ### When to use Use STOMP-over-WebSocket for interactive, low-latency, multi-user push: chat, live dashboards, notifications, collaborative editing, live sports/price feeds. If you only need occasional server-to-client push and not a full pub/sub model, Server-Sent Events (SSE) may be simpler. ### Gotchas - You still need Spring Security config for the WebSocket handshake and message authorization — the normal HTTP filter chain only covers the handshake, not individual STOMP frames. - SockJS and native WebSocket have different endpoint URLs/behaviors; the client library must match.
- What does withSockJS() add and why would you need it?It enables the SockJS fallback protocol, so clients behind proxies or in browsers without native WebSocket support can still get a WebSocket-like connection via HTTP streaming/long-polling transports.
- Is STOMP required to use WebSocket in Spring?No. You can implement a raw WebSocketHandler and define your own message format. STOMP is the higher-level, broker-backed option that gives you pub/sub routing and @MessageMapping controllers for free.