This change adds support for a custom "websocket" scope.
WebSocket-scoped beans may be injected into controllers with message
handling methods as well as channel interceptor registered on the
"inboundClientChannel".
Issue: SPR-11305
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
Animal sniffer provides tools to assist verifying that classes
compiled with a newer JDK are compatible with an older JDK.
This integratesthe latest version of the tool (1.11) that
permits the use of custom annotations. Added @UsesJava7,
@UsesJava8 and @UsesSunHttpServer and annotated the few places
where we rely on a specific environment.
The verification process can be invoked by running the 'sniff'
task.
Issue: SPR-11604
polishing
The original fix for SPR-11423:
32e5f57e64
was insufficient when using an external broker since the original
destination header has to be in the "native headers" map (i.e. with
STOMP headers) in order to be included in messages broadcast by
the broker.
The BufferingStompDecoder now decorates rather than extend
StompDecoder. This allows a single StompDecoder instance to be
configured and extended independantly while buffering remains a
separate concern.
Mutate rather than re-create headers when decoding STOMP messages
before a message is sent on a message channel.
Use MessageBuilder.createMessage to ensure the fully prepared
MessageHeaders is used directly MessageHeaderAccessor instance.
Issue: SPR-11468
Refine semantics of ID and TIMESTAMP headers provided to protected
MessageHeaders constructor.
Refactor internal implementation of MessageHeaderAccessor.
Support mutating headers from a single thread while a message is being
built (e.g. StompDecoder creating message + then adding session id).
Improve immutablity in NativeMessageHeaderAccessor and in
StompHeaderAccessor.
Optimize object creation for initializing messages and subsequent
accessing their headers.
Introduce MessageHeaderAccessorFactory support to enable applying a
common strategies for ID and TIMESTAMP generation to every message.
Add MessageBuilder shortcut factory method for creating messages from
payload and a full-prepared MessageHeaders instance. Also add
equivalent constructors to GenericMessage and ErrorMessage.
Issue: SPR-11468
The UserDestinationMessageHandler adds a header providing a hint for
what the original destination a user may have used when subscribing.
That is then used when writing messages back to WebSocket clients to
ensure they dont see the internally used, transformed user destination.
This change moves the header name constatn to make it more broadly
applicable. For example SPR-11645.
Prior to this commit, @SubscribeMapping mapped methods (backed with
@SendTo* annotations, or not) would send MESSAGEs with the wrong
destination. Instead of using the original SUBSCRIBE destination, it
would use the lookup path computed from the configured prefixes in the
application.
This commit fixes this issue - now @SubscribeMapping MESSAGEs use the
original SUBSCRIBE destination.
Issue: SPR-11648
Update some native WebSocket session getters to return basic
information after it is closed. It is required for example in
SubProtocolWebSocketHandler#afterConnectionEstablished() or
StompSubProtocolHandler#afterSessionStarted().
Issue: SPR-11621
Proactively notify all active WebSocket sessions when a shutdown is
progress. Sessions then can ignore further attempts to send messages
and also stop stop trying to flush messages right away.
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
Before this change the StompDecoder decoded and returned only the first
Message in the ByteBuffer passed to it. So to obtain all messages from
the buffer, one had to loop passing the same buffer in until no more
complete STOMP frames could be decoded.
This chage modifies StompDecoder to return List<Message> after
exhaustively decoding all available STOMP frames from the input buffer.
Also an overloaded decode method allows passing in Map that will be
populated with any headers successfully parsed, which is useful for
"peeking" at the "content-length" header.
This change also adds a BufferingStompDecoder sub-class which buffers
any content left in the input buffer after parsing one or more STOMP
frames. This sub-class can also deal with fragmented messages,
re-assembling them and parsing as a whole message.
Issue: SPR-11527
When a send timeout is detected, the WebSocket session is now closed
with a custom close status that indicates so. This allows skipping
parts of the close logic that may cause further hanging.
Issue: SPR-11450
Before this change SockJsSession implementations of WebSocketSession
used synchronization around its method implementations protecting
internal state and ensuring only a single thread is sending messages
at a time.
A WebSocketSession is generally expected to be used from one thread
at a time and now that application messages are sent through
ConcurrentWebSocketSessionDecorator, there is no concern about
application messages sent from the different threads.
While there are some remaining concerns, those can be addressed
without using the synchronized keyword. This change removes it from
the methods of all SockJS session implementations.
Issue: SPR-11450
Before this change the decorator ensured that for a specific WebSocket
session only one thread at a time can send a message. Other threads
attempting to send would have their messages buffered and each time
that occurs, a check is also made to see if the buffer limit has been
reached or the send time limit has been exceeded and if so the session
is closed.
This change adds further protection to ensure only one thread at a time
can perform the session limit checks and attempt to close the session.
Furthermore if the session has timed out and become unresponsive,
attempts to close it may block yet another thread. Taking this into
consideration this change also ensures that state associated with the
session is cleaned first before an attempt is made to close the session.
Issue: SPR-11450
Since we now wrap the WebSocketSession with a concurrent decorator, the
synchronized keyword around message sending needed to be removed.
Issue: SPR-11586