skip to content

What is STOMP over WebSocket in Spring, and what does @EnableWebSocketMessageBroker set up?

level: juniorimportance: must knowfreq 70%

answer

  1. WebSocket = pipe, STOMP = pub/sub on top
  2. @EnableWebSocketMessageBroker + WebSocketMessageBrokerConfigurer
  3. registerStompEndpoints + configureMessageBroker
  4. SUBSCRIBE / SEND / MESSAGE frames
  5. /ws endpoint, withSockJS fallback

basics

~20 s

WebSocket 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 s

A 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
java
@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

for a junior

Know that WebSocket is the transport and STOMP adds pub/sub semantics; @EnableWebSocketMessageBroker turns it on.

for a middle

Be able to write the config class with both override methods and explain the client message flow.

for a senior

Explain how the annotation handler, channels, and broker wire together, and the security implications of per-frame authorization.

for a principal

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.

context