Geen omschrijving

Greg Turnquist f62b8d0a52 Update to Spring Boot 1.1.4.RELEASE 11 jaren geleden
complete f62b8d0a52 Update to Spring Boot 1.1.4.RELEASE 11 jaren geleden
initial f62b8d0a52 Update to Spring Boot 1.1.4.RELEASE 11 jaren geleden
test 6828e2ac12 Convert to mvn compile for initial codeset 11 jaren geleden
.gitignore 7f07f6620c Convert to asciidoctor 11 jaren geleden
README.adoc f62b8d0a52 Update to Spring Boot 1.1.4.RELEASE 11 jaren geleden

README.adoc

---
tags: [messaging, websocket]
projects: [spring-framework]
---
:spring_version: current
:spring_boot_version: 1.1.4.RELEASE
:MappingJackson2MessageConverter: http://docs.spring.io/spring/docs/{spring_version}/javadoc-api/org/springframework/messaging/support/converter/MappingJackson2MessageConverter.html
:Component: http://docs.spring.io/spring/docs/{spring_version}/javadoc-api/org/springframework/stereotype/Component.html
:jackson: http://wiki.fasterxml.com/JacksonHome
:AtMessageMapping: http://docs.spring.io/spring/docs/{spring_version}/javadoc-api/org/springframework/messaging/handler/annotation/MessageMapping.html
:AtController: http://docs.spring.io/spring/docs/{spring_version}/javadoc-api/org/springframework/stereotype/Controller.html
:AtEnableWebSocket: http://docs.spring.io/spring/docs/{spring_version}/javadoc-api/org/springframework/web/socket/server/config/EnableWebSocket.html
:AtEnableWebSocketMessageBroker: http://docs.spring.io/spring/docs/{spring_version}/javadoc-api/org/springframework/messaging/simp/config/EnableWebSocketMessageBroker.html
:SpringApplication: http://docs.spring.io/spring-boot/docs/{spring_boot_version}/api/org/springframework/boot/SpringApplication.html
:Stomp_JS: http://jmesnil.net/stomp-websocket/doc/
:DispatcherServlet: http://docs.spring.io/spring/docs/{spring_version}/javadoc-api/org/springframework/web/servlet/DispatcherServlet.html
:EnableAutoConfiguration: http://docs.spring.io/spring-boot/docs/{spring_boot_version}/api/org/springframework/boot/autoconfigure/EnableAutoConfiguration.html
:AtSendTo: http://docs.spring.io/spring/docs/{spring_version}/javadoc-api/org/springframework/messaging/handler/annotation/SendTo.html
:toc:
:icons: font
:source-highlighter: prettify
:project_id: gs-messaging-stomp-websocket

This guide walks you through the process of creating a "hello world" application that sends messages back and forth, between a browser and the server.
WebSocket is a very thin, lightweight layer above TCP. It makes it very suitable to use "subprotocols" to embed messages. In this
guide we'll dive in and use http://en.wikipedia.org/wiki/Streaming_Text_Oriented_Messaging_Protocol[STOMP] messaging with Spring
to create an interactive web application.

== 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

:java_version: 1.7
include::https://raw.githubusercontent.com/spring-guides/getting-started-macros/master/prereq_editor_jdk_buildtools.adoc[]


include::https://raw.githubusercontent.com/spring-guides/getting-started-macros/master/how_to_complete_this_guide.adoc[]


[[scratch]]
== Set up the project

include::https://raw.githubusercontent.com/spring-guides/getting-started-macros/master/build_system_intro.adoc[]

include::https://raw.githubusercontent.com/spring-guides/getting-started-macros/master/create_directory_structure_hello.adoc[]


include::https://raw.githubusercontent.com/spring-guides/getting-started-macros/master/create_both_builds.adoc[]

`build.gradle`
// AsciiDoc source formatting doesn't support groovy, so using java instead
[source,java]
----
include::initial/build.gradle[]
----

include::https://raw.githubusercontent.com/spring-guides/getting-started-macros/master/spring-boot-gradle-plugin.adoc[]


[[initial]]
== 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 link:/understanding/JSON[JSON] object. If the name given is "Fred", then the message might look something like this:

[source,json]
----
{
"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`
[source,java]
----
include::complete/src/main/java/hello/HelloMessage.java[]
----

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:

[source,json]
----
{
"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`
[source,java]
----
include::complete/src/main/java/hello/Greeting.java[]
----

Spring will use the {jackson}[Jackson JSON] 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 routed to {AtController}[`@Controller`] classes. For example the `GreetingController` is mapped to handle messages to destination "/hello".

`src/main/java/hello/GreetingController.java`
[source,java]
----
include::complete/src/main/java/hello/GreetingController.java[]
----

This controller is concise and simple, but there's plenty going on. Let's break it down step by step.

The {AtMessageMapping}[`@MessageMapping`] annotation ensures that if a message is sent to destination "/hello", then the `greeting()` method is called.

The payload of the message is bound 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 `Greeting` object and returns it. The return value is broadcast to all subscribers to "/topic/greetings" as specified in the {AtSendTo}[`@SendTo`] annotation.

== 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`
[source,java]
----
include::complete/src/main/java/hello/WebSocketConfig.java[]
----

`WebSocketConfig` is annotated with `@Configuration` to indicate that it is a Spring configuration class.
It is also annotated {AtEnableWebSocketMessageBroker}[`@EnableWebSocketMessageBroker`].
As its name suggests, `@EnableWebSocketMessageBroker` enables 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 "/topic".
It also designates the "/app" prefix for messages that are bound for `@MessageMapping`-annotated methods.

The `registerStompEndpoints()` method registers the "/hello" endpoint, enabling SockJS fallback options so that alternative messaging options may be used if WebSocket is not available.
This endpoint, when prefixed with "/app", is the endpoint that the `GreetingController.greeting()` method is mapped to handle.

== 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`
[source,html]
----
include::complete/src/main/resources/static/index.html[]
----

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 https://github.com/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 "/topic/greetings" destination, where the server will publish greeting messages. When a greeting is received on that destination, 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 link:/understanding/WAR[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 link:/understanding/Tomcat[Tomcat] servlet container as the HTTP runtime, instead of deploying to an external instance.


`src/main/java/hello/Application.java`
[source,java]
----
include::complete/src/main/java/hello/Application.java[]
----

The `main()` method defers to the {SpringApplication}[`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 link:/understanding/application-context[Spring 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}[`@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}[`@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}[`DispatcherServlet`] is configured and registered for you — no `web.xml` necessary! Auto-configuration is a powerful, flexible mechanism. See the {EnableAutoConfiguration}[API documentation] for further details.

include::https://raw.githubusercontent.com/spring-guides/getting-started-macros/master/build_an_executable_jar_subhead.adoc[]

include::https://raw.githubusercontent.com/spring-guides/getting-started-macros/master/build_an_executable_jar_with_both.adoc[]

:module: service
include::https://raw.githubusercontent.com/spring-guides/getting-started-macros/master/run_the_application_with_both.adoc[]

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.