Skip to content

Commit f368639

Browse files
committed
Update STOMP/WebSocket documentation
1 parent 50b8a53 commit f368639

File tree

1 file changed

+149
-6
lines changed

1 file changed

+149
-6
lines changed

src/asciidoc/index.adoc

Lines changed: 149 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -36504,7 +36504,7 @@ application level WebSocket sub-protocol.
3650436504

3650536505
<<websocket-intro>> establishes a frame of mind in which to think about
3650636506
WebSocket covering adoption challenges, design considerations, and thoughts on
36507-
it is a good fit.
36507+
when it is a good fit.
3650836508

3650936509
<<websocket-server>> reviews the Spring WebSocket API on the
3651036510
server-side while <<websocket-fallback>> explains the SockJS protocol and shows
@@ -37058,7 +37058,7 @@ and server both need to understand how to interpret messages.
3705837058

3705937059

3706037060
[[websocket-stomp-overview]]
37061-
==== STOMP Overview
37061+
==== Overview of the STOMP Protocol
3706237062
http://stomp.github.io/stomp-specification-1.2.html#Abstract[STOMP] is a simple
3706337063
messaging protocol originally created to connect to enterprise message brokers from
3706437064
scripting languages such as Ruby, Python and Perl. It is designed to address a
@@ -37150,7 +37150,7 @@ Spring MVC provides a programming model based on HTTP.
3715037150

3715137151

3715237152
[[websocket-stomp-enable]]
37153-
==== Enable STOMP over WebSocket
37153+
==== Enable STOMP (over WebSocket)
3715437154
The Spring Framework provides support for using STOMP over WebSocket through
3715537155
the +spring-messaging+ and +spring-websocket+ modules. It's easy to enable it.
3715637156

@@ -37224,9 +37224,152 @@ Or if connecting via WebSocket (without SockJS):
3722437224

3722537225

3722637226
[[websocket-stomp-handle]]
37227-
==== Handling STOMP Messages
37228-
When STOMP is enabled, the Spring application is effectively becomes a STOMP
37229-
broker to connected clients.
37227+
==== Overview of STOMP Message Handling
37228+
37229+
When a STOMP endpoint is configured, the Spring application effectively becomes
37230+
the broker to connected clients, handling incoming messages and broadcasting
37231+
messages back to them. This part of the documentation describes how STOMP
37232+
messages are handled within the application.
37233+
37234+
As mentioned in the <<websocket-intro-architecture,introduction>> the
37235+
`spring-messaging` module contains key abstractions from the
37236+
https://spring.io/spring-integration[Spring Integration] project including
37237+
`Message`, `MessageChannel`, `MessageHandler` and a few others.
37238+
37239+
[NOTE]
37240+
====
37241+
Spring Integration 4 will be the first version to start using the abstractions
37242+
from the package structure of the `spring-messaging` module as opposed to its
37243+
own present packages. Spring Integration also provides many additional
37244+
abstractions and implementations in support of the well-known
37245+
EAI patterns (http://www.eaipatterns.com/[enterprise integration patterns]).
37246+
====
37247+
37248+
https://github.com/spring-projects/spring-framework/blob/master/spring-messaging/src/main/java/org/springframework/messaging/MessageChannel.java[MessageChannel]
37249+
is a simple contract for passing messages between components without
37250+
creating tight coupling among them.
37251+
https://github.com/spring-projects/spring-framework/blob/master/spring-messaging/src/main/java/org/springframework/messaging/SubscribableChannel.java[SubscribableChannel] extends
37252+
it with the ability to register subscribers and
37253+
https://github.com/spring-projects/spring-framework/blob/master/spring-messaging/src/main/java/org/springframework/messaging/support/ExecutorSubscribableChannel.java[ExecutorSubscribableChannel]
37254+
is an implementation that passes messages to subscribers in
37255+
the same thread or a different thread depending on whether it has been provided with
37256+
a `java.util.concurrent.Executor`. This enables assembling message
37257+
handling flows from various components and modifying them through configuration.
37258+
37259+
The provided Java config `@EnableWebSocketMessageBroker` and XML namespace
37260+
`<websocket:message-broker>` each put together a default message handling
37261+
flow for applications to use, as explained next. This flow can be modified,
37262+
customized, or extended. For example an application can add a
37263+
https://github.com/spring-projects/spring-framework/blob/master/spring-messaging/src/main/java/org/springframework/messaging/support/ChannelInterceptor.java[ChannelInterceptor]
37264+
to any message channel in order to intercept messages passing through it,
37265+
it can register additional message handling components, alternate between
37266+
synchronous and asynchronous message passing, and so on.
37267+
37268+
Incoming client STOMP messages are passed to a message channel with the name
37269+
`"clientInboundChannel"`. By default the messages are routed to annotated
37270+
methods as well as to a "simple" message broker. This simple message broker
37271+
automatically records subscriptions, in-memory, and broadcasts messages as
37272+
necessary. As explained later you can also use a full-featured message broker
37273+
(e.g. RabbitMQ, ActiveMQ, and any other broker that supports STOMP) to manage
37274+
subscriptions and broadcast messages.
37275+
37276+
Below is example configuration:
37277+
37278+
[source,java,indent=0]
37279+
[subs="verbatim,quotes"]
37280+
----
37281+
@Configuration
37282+
@EnableWebSocketMessageBroker
37283+
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
37284+
37285+
@Override
37286+
public void registerStompEndpoints(StompEndpointRegistry registry) {
37287+
registry.addEndpoint("/portfolio").withSockJS();
37288+
}
37289+
37290+
@Override
37291+
public void configureMessageBroker(MessageBrokerRegistry registry) {
37292+
registry.enableSimpleBroker("/topic/");
37293+
registry.setApplicationDestinationPrefixes("/app");
37294+
}
37295+
37296+
}
37297+
----
37298+
37299+
XML configuration equivalent:
37300+
37301+
[source,xml,indent=0]
37302+
[subs="verbatim,quotes,attributes"]
37303+
----
37304+
<beans xmlns="http://www.springframework.org/schema/beans"
37305+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
37306+
xmlns:websocket="http://www.springframework.org/schema/websocket"
37307+
xsi:schemaLocation="
37308+
http://www.springframework.org/schema/beans
37309+
http://www.springframework.org/schema/beans/spring-beans.xsd
37310+
http://www.springframework.org/schema/websocket
37311+
http://www.springframework.org/schema/websocket/spring-websocket-4.0.xsd">
37312+
37313+
<websocket:message-broker application-destination-prefix="/app">
37314+
<websocket:stomp-endpoint path="/portfolio" />
37315+
<websocket:sockjs/>
37316+
</websocket:stomp-endpoint>
37317+
<websocket:simple-broker prefix="/topic"/>
37318+
</websocket:message-broker>
37319+
37320+
</beans>
37321+
----
37322+
37323+
The configuration example assigns destination prefixes -- "/app" for filtering
37324+
messages to annotated methods and "/topic" for messages to the broker. The
37325+
examples below demonstrate how this can be used.
37326+
37327+
The destination prefix should not be included in annotation mappings. For
37328+
example this method handles messages to destination "/app/greetings":
37329+
37330+
[source,java,indent=0]
37331+
[subs="verbatim,quotes"]
37332+
----
37333+
@Controller
37334+
public class GreetingController {
37335+
37336+
@MessageMapping("/greetings") {
37337+
public void handle(String greeting) {
37338+
// ...
37339+
}
37340+
37341+
}
37342+
37343+
----
37344+
37345+
The method accepts a String extracted from the payload of the message,
37346+
possibly converted based on its content type. The method can also return a
37347+
value, which is wrapped as the payload of a new message and sent to a message
37348+
channel named `"brokerChannel"` to the same destination as the client message
37349+
but with a new prefix ("/topic" by default). The `@SendTo` annotation :
37350+
37351+
[source,java,indent=0]
37352+
[subs="verbatim,quotes"]
37353+
----
37354+
@Controller
37355+
public class GreetingController {
37356+
37357+
@MessageMapping("/greetings") {
37358+
public String handle(String greeting) {
37359+
return "[" + getTimestamp() + ": " + greeting;
37360+
}
37361+
37362+
}
37363+
37364+
----
37365+
37366+
As a result, to put it all together, a client sends a greeting message to
37367+
destination "/app/greetings". The message is routed to `GreetingController`,
37368+
which enriches the greeting with a timestamp and sends a new message to the
37369+
broker with destination "/topic/greetings". The broker then broadcasts the
37370+
message to all subscribed, connected clients.
37371+
37372+
3723037373

3723137374

3723237375
[[spring-integration]]

0 commit comments

Comments
 (0)