@@ -36504,7 +36504,7 @@ application level WebSocket sub-protocol.
36504
36504
36505
36505
<<websocket-intro>> establishes a frame of mind in which to think about
36506
36506
WebSocket covering adoption challenges, design considerations, and thoughts on
36507
- it is a good fit.
36507
+ when it is a good fit.
36508
36508
36509
36509
<<websocket-server>> reviews the Spring WebSocket API on the
36510
36510
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.
37058
37058
37059
37059
37060
37060
[[websocket-stomp-overview]]
37061
- ==== STOMP Overview
37061
+ ==== Overview of the STOMP Protocol
37062
37062
http://stomp.github.io/stomp-specification-1.2.html#Abstract[STOMP] is a simple
37063
37063
messaging protocol originally created to connect to enterprise message brokers from
37064
37064
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.
37150
37150
37151
37151
37152
37152
[[websocket-stomp-enable]]
37153
- ==== Enable STOMP over WebSocket
37153
+ ==== Enable STOMP ( over WebSocket)
37154
37154
The Spring Framework provides support for using STOMP over WebSocket through
37155
37155
the +spring-messaging+ and +spring-websocket+ modules. It's easy to enable it.
37156
37156
@@ -37224,9 +37224,152 @@ Or if connecting via WebSocket (without SockJS):
37224
37224
37225
37225
37226
37226
[[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
+
37230
37373
37231
37374
37232
37375
[[spring-integration]]
0 commit comments