This commit adds a test runtime dependency on log4j 2 for every project
and migrates all log4j.properties files to log4j2-test.xml files.
Issue: SPR-14431
This commit adds a new "validator" XML attribute to the
`<websocket:message-broker/>` element. This allows configuring a
specific Validator to be used for payload validation.
Issue: SPR-13996
Recent builds of Jetty 9.3 require that Jetty's own ServletContext
implementation be supplied to WebSocketServerFactory's init() method.
Otherwise, the Jetty server will fail to start with the exception
message: "Not running on Jetty, WebSocket support unavailable".
This commit refactors AbstractWebSocketIntegrationTests,
AbstractSockJsIntegrationTests, and all WebSocketTestServer
implementations in order to support this new requirement.
Specifically:
- WebSocketTestServer defines a new getServletContext() method;
TomcatWebSocketTestServer, UndertowTestServer, and
JettyWebSocketTestServer have all been updated to return the
ServletContext created by the embedded server.
- The setup() methods in AbstractWebSocketIntegrationTests and
AbstractSockJsIntegrationTests have been updated so that the
WebApplicationContext is supplied the appropriate ServletContext,
after deployConfig() has been invoked on the WebSocketTestServer but
before the WebApplicationContext is refreshed.
Issue: SPR-13162
This change introduces SimpUserRegistry exposing an API to access
information about connected users, their sessions, and subscriptions
with STOMP/WebSocket messaging. Provides are methods to access users
as well as a method to find subscriptions given a Matcher strategy.
The DefaultSimpUserRegistry implementation is also a
SmartApplicationListener which listesn for ApplicationContext events
when users connect, disconnect, subscribe, and unsubscribe to
destinations.
The MultiServerUserRegistry implementation is a composite that
aggregates user information from the local SimpUserRegistry as well
as snapshots of user on remote application servers.
UserRegistryMessageHandler is used with MultiServerUserRegistry. It
broadcats user registry information through the broker and listens
for similar broadcasts from other servers. This must be enabled
explicitly when configuring the STOMP broker relay.
The existing UserSessionRegistry which was primiarly used internally
to resolve a user name to session id's has been deprecated and is no
longer used. If an application configures a custom UserSessionRegistr
still, it will be adapted accordingly to SimpUserRegistry but the
effect is rather limited (comparable to pre-existing functionality)
and will not work in multi-server scenarios.
Issue: SPR-12029
This change adds support for broadcasting messages with unresolved
user destinations so that other servers can try to resolve it.
That enables sending messages to users who may be connected to a
different server.
Issue: SPR-11620
Prior to this commit, the `client-library-url` XML attribute was not
effective in the MVC namespace, leaving the default value configured:
```xml
<websocket:sockjs client-library-url="/js/sockjs.js" />
```
This commit fixes the sockjs namespace handler and makes sure that this
attribute is configured on the `SockJsService` Bean to be created.
Issue: SPR-12874
This commit introduces a new OriginHandshakeInterceptor. It filters
Origin header value against a list of allowed origins.
AbstractSockJsService as been modified to:
- Reject CORS requests with forbidden origins
- Disable transport types that does not support CORS when an origin
check is required
- Use the Origin request header value instead of "*" for
Access-Control-Allow-Origin response header value
(mandatory when Access-Control-Allow-Credentials=true)
- Return CORS header only if the request contains an Origin header
It is possible to configure easily this behavior thanks to JavaConfig API
WebSocketHandlerRegistration#addAllowedOrigins(String...) and
StompWebSocketEndpointRegistration#addAllowedOrigins(String...).
It is also possible to configure it using the websocket XML namespace.
Please notice that this commit does not change the default behavior:
cross origin requests are still enabled by default.
Issues: SPR-12226
The WebSocketMessageBroker config now allows wrapping the
SubProtocolWebSocketHandler to enable advanced use cases that may
require access to the underlying WebSocketSession.
Issue: SPR-12314
In order to be able to use separators like "." (used by default
by most broker relays) instead of "/" for destination patterns
handling, the PathMatcher used in spring-messaging can now
be customized easily thanks to XML websocket namespace
or JavaConfig.
AntPathMatcher has been updated in order to use the configured path
separator instead of an hardcoded "/" for path concatenation.
Extension handling is now disabled when the "." separator is configured.
Issue: SPR-11660
This change adds a new implementation of WebSocketClient that can
connect to a SockJS server using one of the SockJS transports
"websocket", "xhr_streaming", or "xhr". From a client perspective
there is no implementation difference between "xhr_streaming" and
"xhr". Just keep receiving and when the response is complete,
start over. Other SockJS transports are browser specific
and therefore not relevant in Java ("eventsource", "htmlfile" or
iframe based variations).
The client loosely mimics the behavior of the JavaScript SockJS client.
First it sends an info request to find the server capabilities,
then it tries to connect with each configured transport, falling
back, or forcing a timeout and then falling back, until one of the
configured transports succeeds.
The WebSocketTransport can be configured with any Spring Framework
WebSocketClient implementation (currently JSR-356 or Jetty 9).
The XhrTransport currently has a RestTemplate-based and a Jetty
HttpClient-based implementations. To use those to simulate a large
number of users be sure to configure Jetty's HttpClient executor
and maxConnectionsPerDestination to high numbers. The same is true
for whichever underlying HTTP library is used with the RestTemplate
(e.g. maxConnPerRoute and maxConnTotal in Apache HttpComponents).
Issue: SPR-10797
Before this change, subscribing to a user destination and use of
@SendToUser annotation required an authenticated user.
This change makes it possible to subscribe to a user destination from
WebSocket sessions without an authenticated user. In such cases the
destination is associated with one session only rather than with a
user (and all their sessions).
It is then also possible to send a message to a user destination
via "/user/{sessionId}/.." rather than "/user/{user}/...".
That means @SendToUser works relying on the session id of the input
message, effectively sending a reply to destination private to the
session.
A key use case for this is handling an exception with an
@MessageExceptionHandler method and sending a reply with @SendToUser.
Issue: SPR-11309
BufferingStompDecoder message buffer size limit can now be configured
with JavaConfig MessageBrokerRegistry.setMessageBufferSizeLimit() or
with XML <websocket:message-brocker message-buffer-size="">.
Issue: SPR-11527
Prior to this commit, configuring a custom handshakeHandler when setting
up a stomp-endpoint with SockJS would not be taken into account:
<websocket:stomp-endpoint path="/foo">
<websocket:handshake-handler ref="customHandler"/>
<websocket:sockjs/>
</websocket:stomp-endpoint>
This commit fixes this by creating and registering a
WebsocketTransportHandler (with this handshakeHandler) as a
transportHandler override for the SockJSService.
Issue: SPR-11568
Prior to this commit, the codebase was using a mix of log4j.xml
and log4j.properties for test-related logging configuration. This
can be an issue as log4j takes the xml variant first when looking
for a default bootstrap configuration.
In practice, some modules declaring the properties variant were
taking the xml variant configuration from another module.
The general structure of the configuration has also been
harmonized to provide a standard console output as well as an
easy way to enable trace logs for the current module.
This commit adds an XML namespace equivalent of @EnableWebSocket and
@EnableWebSocketMessageBroker. Those are <websocket:handlers> and
<websocket:message-broker> respectively.
Examples can be found in the test suite.
This commit also alters the way MessageHandler's subscribe to their
respective MessageChannel's of interest. Rather than performing the
subscriptions in configuration code, the message channels are now
passed into MessageHandler's so they can subscribe themselves on
startup.
Issue: SPR-11063
The method WsServerContainer.getServerContainer() was removed from
JSR-356 but remained in Tomcat a little while longer. Instead the
ServerContainer is obtained through a ServletContext attribute.
Tomcat has now removed this method, hence the need for this fix.