Starting with version 4.1, Spring Integration has WebSocket support.
It is based on the architecture, infrastructure, and API from the Spring Framework’s web-socket module.
Therefore, many of Spring WebSocket’s components (such as SubProtocolHandler or WebSocketClient) and configuration options (such as @EnableWebSocketMessageBroker) can be reused within Spring Integration.
For more information, see the Spring Framework WebSocket Support chapter in the Spring Framework reference manual.
You need to include this dependency into your project:
Maven.
<dependency> <groupId>org.springframework.integration</groupId> <artifactId>spring-integration-websocket</artifactId> <version>5.1.1.RELEASE</version> </dependency>
Gradle.
compile "org.springframework.integration:spring-integration-websocket:5.1.1.RELEASE"
For server side, the org.springframework:spring-webmvc dependency must be included explicitly.
The Spring Framework WebSocket infrastructure is based on the Spring messaging foundation and provides a basic messaging framework based on the same MessageChannel implementations and MessageHandler implementations that Spring Integration uses (and some POJO-method annotation mappings).
Consequently, Spring Integration can be directly involved in a WebSocket flow, even without WebSocket adapters.
For this purpose, you can configure a Spring Integration @MessagingGateway with appropriate annotations, as the following example shows:
@MessagingGateway @Controller public interface WebSocketGateway { @MessageMapping("/greeting") @SendToUser("/queue/answer") @Gateway(requestChannel = "greetingChannel") String greeting(String payload); }
Since the WebSocket protocol is streaming by definition and we can send and receive messages to and from a WebSocket at the same time, we can deal with an appropriate WebSocketSession, regardless of being on the client or server side.
To encapsulate the connection management and WebSocketSession registry, the IntegrationWebSocketContainer is provided with ClientWebSocketContainer and ServerWebSocketContainer implementations.
Thanks to the WebSocket API and its implementation in the Spring Framework (with many extensions), the same classes are used on the server side as well as the client side (from a Java perspective, of course).
Consequently, most connection and WebSocketSession registry options are the same on both sides.
That lets us reuse many configuration items and infrastructure hooks to build WebSocket applications on the server side as well as on the client side.
The following example shows how components can serve both purposes:
//Client side @Bean public WebSocketClient webSocketClient() { return new SockJsClient(Collections.singletonList(new WebSocketTransport(new JettyWebSocketClient()))); } @Bean public IntegrationWebSocketContainer clientWebSocketContainer() { return new ClientWebSocketContainer(webSocketClient(), "ws://my.server.com/endpoint"); } //Server side @Bean public IntegrationWebSocketContainer serverWebSocketContainer() { return new ServerWebSocketContainer("/endpoint").withSockJs(); }
The IntegrationWebSocketContainer is designed to achieve bidirectional messaging and can be shared between inbound and outbound channel adapters (see below), can be referenced from only one of them when using one-way (sending or receiving) WebSocket messaging.
It can be used without any channel adapter, but, in this case, IntegrationWebSocketContainer only plays a role as the WebSocketSession registry.
![]() | Note |
|---|---|
|
The |
The WebSocketInboundChannelAdapter implements the receiving part of WebSocketSession interaction.
You must supply it with a IntegrationWebSocketContainer, and the adapter registers itself as a WebSocketListener to handle incoming messages and WebSocketSession events.
![]() | Note |
|---|---|
|
Only one |
For WebSocket subprotocols, the WebSocketInboundChannelAdapter can be configured with SubProtocolHandlerRegistry as the second constructor argument.
The adapter delegates to the SubProtocolHandlerRegistry to determine the appropriate SubProtocolHandler for the accepted WebSocketSession and to convert a WebSocketMessage to a Message according to the sub-protocol implementation.
![]() | Note |
|---|---|
|
By default, the |
The WebSocketInboundChannelAdapter accepts and sends to the underlying integration flow only Message instances that have SimpMessageType.MESSAGE or an empty simpMessageType header.
All other Message types are handled through the ApplicationEvent instances emitted from a SubProtocolHandler implementation (such as
StompSubProtocolHandler).
On the server side, if the @EnableWebSocketMessageBroker configuration is present, you can configure WebSocketInboundChannelAdapter with the useBroker = true option.
In this case, all non-MESSAGE Message types are delegated to the provided AbstractBrokerMessageHandler.
In addition, if the broker relay is configured with destination prefixes, those messages that match the Broker destinations are routed to the AbstractBrokerMessageHandler instead of to the outputChannel of the WebSocketInboundChannelAdapter.
If useBroker = false and the received message is of the SimpMessageType.CONNECT type, the WebSocketInboundChannelAdapter immediately sends a SimpMessageType.CONNECT_ACK message to the WebSocketSession without sending it to the channel.
![]() | Note |
|---|---|
|
Spring’s WebSocket Support allows the configuration of only one broker relay.
Consequently, we do not require an |
For more configuration options, see Section 36.4, “WebSockets Namespace Support”.
The WebSocketOutboundChannelAdapter:
MessageChannel
WebSocketSession id from the MessageHeaders
WebSocketSession from the provided IntegrationWebSocketContainer
WebSocketMessage work to the appropriate SubProtocolHandler from the provided SubProtocolHandlerRegistry.
On the client side, the WebSocketSession id message header is not required, because ClientWebSocketContainer deals only with a single connection and its WebSocketSession respectively.
To use the STOMP subprotocol, you should configure this adapter with a StompSubProtocolHandler.
Then you can send any STOMP message type to this adapter, using StompHeaderAccessor.create(StompCommand...) and a MessageBuilder, or just using a HeaderEnricher (see Section 9.2.1, “Header Enricher”).
The rest of this chapter covers largely additional configuration options.
The Spring Integration WebSocket namespace includes several components described in the remainder of this chapter. To include it in your configuration, use the following namespace declaration in your application context configuration file:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:int="http://www.springframework.org/schema/integration" xmlns:int-websocket="http://www.springframework.org/schema/integration/websocket" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration.xsd http://www.springframework.org/schema/integration/websocket http://www.springframework.org/schema/integration/websocket/spring-integration-websocket.xsd"> ... </beans>
The following listing shows the attributes available for the <int-websocket:client-container> element:
<int-websocket:client-container id=""client=""
uri=""
uri-variables=""
origin=""
send-time-limit=""
send-buffer-size-limit=""
auto-startup=""
phase="">
<int-websocket:http-headers> <entry key="" value=""/> </int-websocket:http-headers>
</int-websocket:client-container>
|
The component bean name. | |
|
The | |
|
The | |
|
Comma-separated values for the URI variable placeholders within the | |
|
The | |
|
The WebSocket session send timeout limit.
Defaults to | |
|
The WebSocket session send message size limit.
Defaults to | |
|
Boolean value indicating whether this endpoint should start automatically.
Defaults to | |
|
The lifecycle phase within which this endpoint should start and stop.
The lower the value, the earlier this endpoint starts and the later it stops.
The default is | |
|
A |
The following listing shows the attributes available for the <int-websocket:server-container> element:
<int-websocket:server-container id=""path=""
handshake-handler=""
handshake-interceptors=""
decorator-factories=""
send-time-limit=""
send-buffer-size-limit=""
allowed-origins="">
<int-websocket:sockjs client-library-url=""
stream-bytes-limit=""
session-cookie-needed=""
heartbeat-time=""
disconnect-delay=""
message-cache-size=""
websocket-enabled=""
scheduler="" (16) message-codec="" (17) transport-handlers="" (18) suppress-cors="true"="" /> (19) </int-websocket:server-container>
|
The component bean name. | |
|
A path (or comma-separated paths) that maps a particular request to a | |
|
The | |
|
List of | |
|
List of one or more factories ( | |
|
See the same option on the | |
|
See the same option on the | |
|
The allowed origin header values.
You can specify multiple origins as a comma-separated list.
This check is mostly designed for browser clients.
There is nothing preventing other types of client from modifying the origin header value.
When SockJS is enabled and allowed origins are restricted, transport types that do not use origin headers for cross-origin requests ( | |
|
Transports with no native cross-domain communication (such as | |
|
Minimum number of bytes that can be sent over a single HTTP streaming request before it is closed.
Defaults to | |
|
The | |
|
The amount of time (in milliseconds) when the server has not sent any messages and after which the server should
send a heartbeat frame to the client in order to keep the connection from breaking.
The default value is | |
|
The amount of time (in milliseconds) before a client is considered disconnected after not having a receiving connection (that is, an active connection over which the server can send data to the client).
The default value is | |
|
The number of server-to-client messages that a session can cache while waiting for the next HTTP polling request from the client.
The default size is | |
|
Some load balancers do not support WebSockets.
Set this option to | |
|
The | |
|
The | |
|
List of | |
|
Whether to disable automatic addition of CORS headers for SockJS requests.
The default value is |
The following listing shows the attributes available for the <int-websocket:outbound-channel-adapter> element:
<int-websocket:outbound-channel-adapter id=""channel=""
container=""
default-protocol-handler=""
protocol-handlers=""
message-converters=""
merge-with-default-converters=""
auto-startup=""
phase=""/>
|
The component bean name.
If you do not provide the | |
|
Identifies the channel attached to this adapter. | |
|
The reference to the | |
|
Optional reference to a | |
|
List of | |
|
List of | |
|
Boolean value indicating whether the default converters should be registered after any custom converters.
This flag is used only if | |
|
Boolean value indicating whether this endpoint should start automatically.
Defaults to | |
|
The lifecycle phase within which this endpoint should start and stop.
The lower the value, the earlier this endpoint starts and the later it stops.
The default is |
The following listing shows the attributes available for the <int-websocket:outbound-channel-adapter> element:
<int-websocket:inbound-channel-adapter id=""channel=""
error-channel=""
container=""
default-protocol-handler=""
protocol-handlers=""
message-converters=""
merge-with-default-converters=""
send-timeout=""
payload-type=""
use-broker=""
auto-startup=""
phase=""/>
|
The component bean name.
If you do not set the | |
|
Identifies the channel attached to this adapter. | |
|
The | |
|
See the same option on the | |
|
See the same option on the | |
|
See the same option on the | |
|
See the same option on the | |
|
See the same option on the | |
|
Maximum amount of time (in milliseconds) to wait when sending a message to the channel if the channel can block.
For example, a | |
|
Fully qualified name of the Java type for the target | |
|
Indicates whether this adapter sends | |
|
See the same option on the | |
|
See the same option on the |
Starting with version 4.3.13, Spring Integration provides ClientStompEncoder (as an extension of the standard StompEncoder) for use on the client side of WebSocket channel adapters.
For proper client side message preparation, you must inject an instance of the ClientStompEncoder into the StompSubProtocolHandler.
One problem with the default StompSubProtocolHandler is that it was designed for the server side, so it updates the SEND stompCommand header into MESSAGE (as required by the STOMP protocol for the server side).
If the client does not send its messages in the proper SEND web socket frame, some STOMP brokers do not accept them.
The purpose of the ClientStompEncoder, in this case, is to override the stompCommand header and set it to the SEND value before encoding the message to the byte[].