This guide walks you through the process of creating a "hello world" STOMP messaging server with Spring. What you'll build ----------------- You'll build a server that will accept a message carrying a user's name. In response, it will push a greeting into a queue that the client is subscribed to. What you'll need ---------------- - About 15 minutes - A favorite text editor or IDE - [JDK 6][jdk] or later - [Gradle 1.8+][gradle] or [Maven 3.0+][mvn] - You can also import the code from this guide as well as view the web page directly into [Spring Tool Suite (STS)][gs-sts] and work your way through it from there. [jdk]: http://www.oracle.com/technetwork/java/javase/downloads/index.html [gradle]: http://www.gradle.org/ [mvn]: http://maven.apache.org/download.cgi [gs-sts]: /guides/gs/sts How to complete this guide -------------------------- Like all Spring's [Getting Started guides](/guides/gs), you can start from scratch and complete each step, or you can bypass basic setup steps that are already familiar to you. Either way, you end up with working code. To **start from scratch**, move on to [Set up the project](#scratch). To **skip the basics**, do the following: - [Download][zip] and unzip the source repository for this guide, or clone it using [Git][u-git]: `git clone https://github.com/spring-guides/gs-messaging-stomp-websocket.git` - cd into `gs-messaging-stomp-websocket/initial`. - Jump ahead to [Create a resource representation class](#initial). **When you're finished**, you can check your results against the code in `gs-messaging-stomp-websocket/complete`. [zip]: https://github.com/spring-guides/gs-messaging-stomp-websocket/archive/master.zip [u-git]: /understanding/Git Set up the project ------------------ First you set up a basic build script. You can use any build system you like when building apps with Spring, but the code you need to work with [Gradle](http://gradle.org) and [Maven](https://maven.apache.org) is included here. If you're not familiar with either, refer to [Building Java Projects with Gradle](/guides/gs/gradle/) or [Building Java Projects with Maven](/guides/gs/maven). ### Create the directory structure In a project directory of your choosing, create the following subdirectory structure; for example, with `mkdir -p src/main/java/hello` on *nix systems: └── src └── main └── java └── hello ### Create a Gradle build file Below is the [initial Gradle build file](https://github.com/spring-guides/gs-messaging-stomp-websocket/blob/master/initial/build.gradle). But you can also use Maven. The pom.xml file is included [right here](https://github.com/spring-guides/gs-messaging-stomp-websocket/blob/master/initial/pom.xml). If you are using [Spring Tool Suite (STS)][gs-sts], you can import the guide directly. `build.gradle` ```gradle apply plugin: 'java' apply plugin: 'war' apply plugin: 'eclipse' apply plugin: 'idea' war { baseName = 'gs-messaging-websocket' version = '0.1.0' } repositories { mavenCentral() maven { url "http://repo.springsource.org/libs-snapshot" } } dependencies { compile("org.springframework:spring-webmvc:4.0.0.BUILD-SNAPSHOT") compile("org.springframework:spring-websocket:4.0.0.BUILD-SNAPSHOT") providedCompile("javax.websocket:javax.websocket-api:1.0-rc5") providedCompile("javax.servlet:javax.servlet-api:3.1-b09") testCompile("junit:junit:4.11") } task wrapper(type: Wrapper) { gradleVersion = '1.6' } ``` [gs-sts]: /guides/gs/sts > **Note:** This guide is using [Spring Boot](/guides/gs/spring-boot/). Create a resource representation class -------------------------------------- Now that you've set up the project and build system, you can create your STOMP message service. Begin the process by thinking about service interactions. The service will accept messages containing a name in a STOMP message whose body is a [JSON][u-json] object. If the name given is "Fred", then the message might look something like this: { "name": "Fred" } To model the message carrying the name, you can create a plain old Java object with a `name` property and a corresponding `getName()` method: `src/main/java/hello/HelloMessage.java` ```java package hello; public class HelloMessage { private String name; public String getName() { return name; } } ``` Upon receiving the message and extracting the name, the service will process it by creating a greeting and publishing that greeting on a separate queue that the client is subscribed to. The greeting will also be a JSON object, which might look something like this: { "content": "Hello, Fred!" } To model the greeting representation, you add another plain old Java object with a `content` property and corresponding `getContent()` method: `src/main/java/hello/Greeting.java` ```java package hello; public class Greeting { private String content; public Greeting(String content) { this.content = content; } public String getContent() { return content; } } ``` Spring will use the [Jackson JSON][jackson] library to automatically marshal instances of type `Greeting` into JSON. Next, you'll create a controller to receive the hello message and send a greeting message. Create a message-handling controller ------------------------------------ In Spring's approach to working with STOMP messaging, STOMP messages can be handled by a controller. These components are easily identified by the [`@Controller`][AtController] annotation, and the `GreetingController` below is mapped to handle messages published on the "/app/hello" destination. `src/main/java/hello/GreetingController.java` ```java package hello; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.messaging.handler.annotation.MessageMapping; import org.springframework.messaging.simp.SimpMessageSendingOperations; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestBody; @Controller public class GreetingController { private SimpMessageSendingOperations messagingTemplate; @Autowired public GreetingController(SimpMessageSendingOperations messagingTemplate) { this.messagingTemplate = messagingTemplate; } @MessageMapping("/app/hello") public void greeting(@RequestBody HelloMessage message) throws Exception { Thread.sleep(3000); // simulated delay Greeting greeting = new Greeting("Hello, " + message.getName() + "!"); messagingTemplate.convertAndSend("/queue/greetings", greeting); } } ``` This controller is concise and simple, but there's plenty going on. Let's break it down step by step. The [`@MessageMapping`][AtMessageMapping] annotation ensures that if a message is published on the "/app/hello" destination, then the `greeting()` method is called. `@RequestBody` binds the payload of the message to a `HelloMessage` object which is passed into `greeting()`. Internally, the implementation of the method simulates a processing delay by causing the thread to sleep for 3 seconds. This is to demonstrate that after the client sends a message, the server can take as long as it needs to process the message asynchronously. The client may continue with whatever work it needs to do without waiting on the response. After the 3 second delay, the `greeting()` method creates a new `Greeting` object, setting its content to say "Hello" to the name from the `HelloMessage`. It then calls `convertAndSend()` on the injected `SimpMessageSendingOperations` to send the `Greeting` on the "/queue/greetings" destination. The `Greeting` object must be converted to JSON. Thanks to Spring's HTTP message converter support, you don't need to do this conversion manually. When you configure Spring for STOMP messaging, you'll inject `SimpMessagingTemplate` with an instance of [`MappingJackson2MessageConverter`][MappingJackson2MessageConverter]. It will be used to convert the `Greeting` instance to JSON. Configure Spring for STOMP messaging ------------------------------------ Now that the essential components of the service are created, you can configure Spring to enable WebSocket and STOMP messaging. Create a Java class named `WebSocketConfig` that looks like this: `src/main/java/hello/WebSocketConfig.java` ```java package hello; import org.springframework.context.annotation.Configuration; import org.springframework.messaging.simp.config.EnableWebSocketMessageBroker; import org.springframework.messaging.simp.config.MessageBrokerConfigurer; import org.springframework.messaging.simp.config.StompEndpointRegistry; import org.springframework.messaging.simp.config.WebSocketMessageBrokerConfigurer; @Configuration @EnableWebSocketMessageBroker public class WebSocketConfig implements WebSocketMessageBrokerConfigurer { @Override public void configureMessageBroker(MessageBrokerConfigurer config) { config.enableSimpleBroker("/queue"); config.setAnnotationMethodDestinationPrefixes("/app"); } @Override public void registerStompEndpoints(StompEndpointRegistry registry) { registry.addEndpoint("/hello").withSockJS(); } } ``` `WebSocketConfig` is annotated with `@Configuration` to indicate that it is a Spring configuration class. It is also annotated [`@EnableWebSocketMessageBroker`][AtEnableWebSocketMessageBroker]. As its name suggests, `@EnableWebSocketMessageBroker` enables a WebSocket message handling, backed by a message broker. The `configureMessageBroker()` method overrides the default method in `WebSocketMessageBrokerConfigurer` to configure the message broker. It starts by calling `enableSimpleBroker()` to enable a simple memory-based message broker to carry the greeting messages back to the client on destinations prefixed with "/queue". It also designates the "/app" prefix for messages that are bound for `@MessageMapping`-annotated methods. The `registerStompEndpoints()` method registers the "/hello" endpoint (which, along with the "/app" prefix, is handled by `GreetingController`'s `greeting()` method). In doing so, it enables SockJS fallback options on that endpoint so that alternative messaging options may be used if WebSocket is not available. Create a browser client ----------------------- With the server side pieces in place, now let's turn our attention to the JavaScript client that will send messages to and receive messages from the server side. Create an index.html file that looks like this: `src/main/resources/static/index.html` ```html Hello WebSocket

``` The main piece of this HTML file to pay attention to is the JavaScript code in the `connect()` and `sendName()` functions. The `connect()` function uses [SockJS][SockJS] and [stomp.js][Stomp_JS] to open a connection to "/gs-messaging-stomp-websocket/hello", which is where `GreetingController` is waiting for connections. Upon a successful connection, it subscribes to the "/queue/greetings" destination, where the server will publish greeting messages. When a greeting appears on that queue, it will append a paragraph element to the DOM to display the greeting message. The `sendName()` function retrieves the name entered by the user and uses the STOMP client to send it to the "/app/hello" destination (where `GreetingController.greeting()` will receive it). Make the application executable ------------------------------- Although it is possible to package this service as a traditional [WAR][u-war] file for deployment to an external application server, the simpler approach demonstrated below creates a standalone application. You package everything in a single, executable JAR file, driven by a good old Java `main()` method. Along the way, you use Spring's support for embedding the [Tomcat][u-tomcat] servlet container as the HTTP runtime, instead of deploying to an external instance. ### Create an Application class `src/main/java/hello/Application.java` ```java package hello; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.SpringApplication; import org.springframework.context.annotation.ComponentScan; @ComponentScan @EnableAutoConfiguration public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } } ``` The `main()` method defers to the [`SpringApplication`][] helper class, providing `Application.class` as an argument to its `run()` method. This tells Spring to read the annotation metadata from `Application` and to manage it as a component in the [Spring application context][u-application-context]. The `@ComponentScan` annotation tells Spring to search recursively through the `hello` package and its children for classes marked directly or indirectly with Spring's [`@Component`][] annotation. This directive ensures that Spring finds and registers the `GreetingController`, because it is marked with `@Controller`, which in turn is a kind of `@Component` annotation. The [`@EnableAutoConfiguration`][] annotation switches on reasonable default behaviors based on the content of your classpath. For example, because the application depends on the embeddable version of Tomcat (tomcat-embed-core.jar), a Tomcat server is set up and configured with reasonable defaults on your behalf. And because the application also depends on Spring MVC (spring-webmvc.jar), a Spring MVC [`DispatcherServlet`][] is configured and registered for you — no `web.xml` necessary! Auto-configuration is a powerful, flexible mechanism. See the [API documentation][`@EnableAutoConfiguration`] for further details. ### Build an executable JAR Now that your `Application` class is ready, you simply instruct the build system to create a single, executable jar containing everything. This makes it easy to ship, version, and deploy the service as an application throughout the development lifecycle, across different environments, and so forth. Below are the Gradle steps, but if you are using Maven, you can find the updated pom.xml [right here](https://github.com/spring-guides/gs-messaging-stomp-websocket/blob/master/complete/pom.xml) and build it by typing `mvn clean package`. Update your Gradle `build.gradle` file's `buildscript` section, so that it looks like this: ```groovy buildscript { repositories { maven { url "http://repo.spring.io/libs-snapshot" } mavenLocal() } dependencies { classpath("org.springframework.boot:spring-boot-gradle-plugin:0.5.0.M6") } } ``` Further down inside `build.gradle`, add the following to the list of applied plugins: ```groovy apply plugin: 'spring-boot' ``` You can see the final version of `build.gradle` [right here]((https://github.com/spring-guides/gs-messaging-stomp-websocket/blob/master/complete/build.gradle). The [Spring Boot gradle plugin][spring-boot-gradle-plugin] collects all the jars on the classpath and builds a single "über-jar", which makes it more convenient to execute and transport your service. It also searches for the `public static void main()` method to flag as a runnable class. Now run the following command to produce a single executable JAR file containing all necessary dependency classes and resources: ```sh $ ./gradlew build ``` If you are using Gradle, you can run the JAR by typing: ```sh $ java -jar build/libs/gs-messaging-stomp-websocket-0.1.0.jar ``` If you are using Maven, you can run the JAR by typing: ```sh $ java -jar target/gs-messaging-stomp-websocket-0.1.0.jar ``` [spring-boot-gradle-plugin]: https://github.com/spring-projects/spring-boot/tree/master/spring-boot-tools/spring-boot-gradle-plugin > **Note:** The procedure above will create a runnable JAR. You can also opt to [build a classic WAR file](/guides/gs/convert-jar-to-war/) instead. Run the service ------------------- If you are using Gradle, you can run your service at the command line this way: ```sh $ ./gradlew clean build && java -jar build/libs/gs-messaging-stomp-websocket-0.1.0.jar ``` > **Note:** If you are using Maven, you can run your service by typing `mvn clean package && java -jar target/gs-messaging-stomp-websocket-0.1.0.jar`. Logging output is displayed. The service should be up and running within a few seconds. Test the service ---------------- Now that the service is running, point your browser at http://localhost:8080 and click the "Connect" button. Upon opening a connection, you are asked for your name. Enter your name and click "Send". Your name is sent to the server as a JSON message over STOMP. After a 3-second simulated delay, the server sends a message back with a "Hello" greeting that is displayed on the page. At this point, you can send another name, or you can click the "Disconnect" button to close the connection. Summary ------- Congratulations! You've just developed a STOMP-based messaging service with Spring. [u-rest]: /understanding/rest [u-json]: /understanding/json [jackson]: http://wiki.fasterxml.com/JacksonHome [MappingJackson2MessageConverter]: http://static.springsource.org/spring/docs/4.0.x/javadoc-api/org/springframework/messaging/support/converter/MappingJackson2MessageConverter.html [AtController]: http://static.springsource.org/spring/docs/current/javadoc-api/org/springframework/stereotype/Controller.html [AtEnableWebSocket]: http://static.springsource.org/spring/docs/current/javadoc-api/org/springframework/web/socket/server/config/EnableWebSocket.html [AtEnableWebSocketMessageBroker]: http://static.springsource.org/spring/docs/current/javadoc-api/org/springframework/messaging/simp/config/EnableWebSocketMessageBroker.html [AtMessageMapping]: http://static.springsource.org/spring/docs/current/javadoc-api/org/springframework/messaging/handler/annotation/MessageMapping.html [AtController]: http://static.springsource.org/spring/docs/current/javadoc-api/org/springframework/stereotype/Controller.html .html [SockJS]: https://github.com/sockjs [Stomp_JS]: http://jmesnil.net/stomp-websocket/doc/