# STOMP over WebSocket with Spring: a browser-to-server message guide

> The Spring guide to building an interactive web application on WebSocket shows the whole path, a JSON payload in a STOMP frame, a controller that receives it, a broker that pushes the reply, and a browser client that subscribes and receives.

**spring-guides/gs-messaging-stomp-websocket** — Using WebSocket to build an interactive web application :: Learn how to the send and receive messages between a browser and the server over a WebSocket

- Repository: https://github.com/spring-guides/gs-messaging-stomp-websocket
- Website: http://spring.io/guides/gs/messaging-stomp-websocket/
- Stars: 559 · Forks: 490
- Language: Java
- License: Apache-2.0
- Published: 2026-10-22 · Updated: 2026-10-22 · Language: en
- Canonical page: https://hysenlabs.com/projects/spring-guides-gs-messaging-stomp-websocket

## Why WebSocket with a subprotocol

The guide walks you through creating a Hello world application that sends messages back and forth between a browser and a server. The reasoning for the stack is given up front. WebSocket is a thin, lightweight layer above TCP, and that makes it suitable for using subprotocols to embed messages, and the guide uses STOMP messaging with Spring to create the interactive application, with STOMP being a subprotocol operating on top of the lower-level WebSocket. The layering is the point. WebSocket gives you a persistent bidirectional channel and says nothing about the format of what travels on it, and STOMP supplies a frame format that a browser client can speak without a heavy library on either end. The project is licensed Apache 2.0, its homepage is the published guide on spring.io, and the last push to the repository was on 2026-09-01.

## What the application actually does

The specification of the finished application is short enough to hold in your head. You build a server that accepts a message carrying a user's name, and in response the server pushes a greeting into a queue to which the client is subscribed. That single sentence contains the whole architecture, including the part that makes it interesting, which is that the reply does not travel back down the same request but arrives on a separate subscription whenever it is sent. The guide's own diagram of the flow is the sequence of the client sending to one destination and the server publishing to another. The repository layout is a two directory split, with initial/ holding the project as the reader starts it and complete/ holding the finished version, and the source files are referenced by path within the guide, such as the HelloMessage class in src/main/java/com/example/messagingstompwebsocket/.

## The payload, and why it is a plain object

The service accepts messages that contain a name in a STOMP message whose body is a JSON object, and if the name is Fred the message body looks like this.

```json
{
    "name": "Fred"
}
```

To model that, you create a plain old Java object with a name property and a corresponding getName method, which the guide shows in the HelloMessage.java listing. The reply is modelled the same way, a plain object with a content property and a getContent method in Greeting.java, and the body on the wire is this.

```json
{
    "content": "Hello, Fred!"
}
```

Spring uses the Jackson JSON library to automatically marshal instances of these types into JSON, which is the detail that makes the whole example work without a line of serialisation code. The two objects are deliberately unremarkable, and that is the lesson of the first step, because the message representation is where most of the accidental complexity in a messaging application comes from.

## The controller, and the annotation that does the routing

In Spring's approach to working with STOMP messaging, messages can be routed to controller classes, and the GreetingController is mapped to handle messages to the /hello destination. The controller is described as concise and simple, but with plenty going on, and the guide breaks it down step by step. The @MessageMapping annotation ensures that if a message is sent to the /hello destination, the greeting method is called, and the payload of the message is bound to a HelloMessage object which is passed into the method. Internally, the method simulates a processing delay by causing the thread to sleep for one second, and the guide is explicit about why: to demonstrate that after the client sends a message, the server can take as long as it needs to asynchronously process the message, and the client can continue with whatever work it needs to do without waiting for the response.

## Where the reply goes, and the sanitising detail

After the one-second delay, the greeting method creates a Greeting object and returns it, and the return value is broadcast to all subscribers of /topic/greetings as specified in the @SendTo annotation. The destination names matter here. The client sends to /hello and the server publishes to /topic/greetings, and the client is subscribed to the latter. The guide also calls out a security detail that is easy to miss when copying code. The name from the input message is sanitized, since in this case it will be echoed back and re-rendered in the browser DOM on the client side. That is a one-line detail in a Hello world example and the reason it is there, because the input reaches the browser, and anything that reaches the browser has to be treated as untrusted.

## Enabling the broker, and what the annotation actually turns on

With the components in place, Spring has to be configured to enable WebSocket and STOMP messaging, and the guide adds a WebSocketConfig class. It is annotated with @Configuration to indicate that it is a Spring configuration class, and it is also annotated with @EnableWebSocketMessageBroker, whose name says what it does: it enables WebSocket message handling, backed by a message broker. The description is cut off at that point, so the broker configuration specifics, the endpoint registration and the application entry point are not settled by the guide text that follows. The guide also has a companion for the STOMP JavaScript client, which is what the browser uses to speak the protocol, and the guide links to it as the reference for the client side.

## Starting the project, and where the code lives

The project comes from Spring Initializr, and the guide links a pre-initialised version of it with the websocket dependency already selected, and the description field filled in, so clicking Generate downloads a ZIP of a project configured to fit the examples. The manual path is spelled out too. You navigate to start.spring.io, choose either Gradle or Maven and the language you want, with the guide assuming Java, select the Websocket dependency, click Generate, and download the resulting ZIP, which is an archive of a web application configured with your choices. There are two notes for the impatient. If your IDE has the Spring Initializr integration you can complete this process from your IDE, and you can also fork the project on Github and open it in your IDE or another editor. The repository top level holds the README, the contributing file, the licence and the two source trees, initial and complete.

## Conclusion

This guide fits a Spring developer who wants a working bidirectional browser and server application rather than a one-way HTTP endpoint, since it takes you from the project skeleton to a subscribed client receiving pushed messages, and the complete and initial directories let you see the finished code next to the starting point. It does not fit a developer who needs a production messaging setup, since the guide stops at the Hello world stage and says nothing about authentication, message durability or scaling beyond the single broker instance, and it does not fit a frontend-only team, since the server side is the substance. Before you copy it, read the sanitising note in the controller, because the guide deliberately strips the name that gets echoed back into the browser DOM, and that is a small thing that is easy to drop and is worth understanding rather than pasting.

## FAQ

### What does the STOMP over WebSocket Spring guide build?

A server that accepts a message carrying a user's name and, in response, pushes a greeting into a queue to which the client is subscribed. The guide walks through creating the project with Spring Initializr, the resource classes, the message-handling controller and the Spring configuration for STOMP messaging.

### Why does the guide use STOMP on top of WebSocket?

WebSocket is described as a thin, lightweight layer above TCP, which makes it suitable for using subprotocols to embed messages, and STOMP is a subprotocol operating on top of the lower-level WebSocket, providing a frame format both the browser and the server can speak.

### Which annotations route the messages in the guide?

The controller is a @Controller class mapped to the /hello destination, with @MessageMapping on the method so a message sent there calls it, and @SendTo on the return value so the greeting is broadcast to all subscribers of /topic/greetings. The configuration class carries @Configuration and @EnableWebSocketMessageBroker.

### What is the sanitising step in the greeting controller for?

The name from the input message is sanitized because it will be echoed back and re-rendered in the browser DOM on the client side. The guide includes it so the example is not teaching a pattern that pastes untrusted input straight into a page.

## Sources

- [Issues](https://github.com/spring-guides/gs-messaging-stomp-websocket/issues)
- [License: Apache-2.0](https://github.com/spring-guides/gs-messaging-stomp-websocket/blob/main/LICENSE)
- [Project website](http://spring.io/guides/gs/messaging-stomp-websocket/)
- [README](https://github.com/spring-guides/gs-messaging-stomp-websocket/blob/main/README.md)
- [spring-guides/gs-messaging-stomp-websocket on GitHub](https://github.com/spring-guides/gs-messaging-stomp-websocket)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/spring-guides-gs-messaging-stomp-websocket
