Commit Graph

59 Commits

Author SHA1 Message Date
Rossen Stoyanchev
48caeef4de Polish and fix issues in STOMP broker relay
Fix error in te code that handles the result of sending a heartbeat

Fix error in processing DISCONNECTED frames that closed the TCP
connection before the message was sent.
2013-09-30 16:37:18 -04:00
Andy Wilkinson
34dd844716 Polishing
- Polish javadoc for CONNECTED_USER_HEADER
 - Improve method ordering
2013-09-30 14:24:57 -04:00
Andy Wilkinson
5025c304b8 Introduce CONNECT_ACK message type
Previously, handling of a STOMP CONNECT message and sending of a
CONNECTED response was performed by StompProtocolHandler if it was
backed by SimpleBrokerMessageHandler, or left up to the real message
broker if it was backed by StompBrokerRelayMessageHandler. This
wasn't ideal as it should be StompProtocolHandler's job to simply map
messages to and from the STOMP protocol, not to do part of the
broker's job and respond directly to CONNECT.

This commit introduces a new message type, CONNECT_ACK. When it
receives a CONNECT message, SimpleBrokerMessageHandler will now
respond with a CONNECT_ACK message that StompProtocolHandler can map
into a STOMP CONNECTED message. The CONNECT_ACK message contains the
CONNECT message as a header so that StompProtocolHandler has access to
its accept-version header.

StompProtocolHandler has been simplified so that a CONNECT message
is always passed to the output channel, irrespective of whether it's
backed by a simple broker or a real broker. The handleConnect flag,
and the code that would set it correctly depending on the app's
configuration, has been removed.
2013-09-30 14:24:57 -04:00
Andy Wilkinson
b2f31a3c74 Improve handling of send failures
Prior to this commit, a failure to send a heartbeat was ignored and a
failure to forward a message to the broker would result in an error
frame being sent but nothing more.

Following this commit, a failure to send a heartbeat to the broker
is treated as a TCP client failure. Furthermore, if the system relay
session fails to forward a message to the broker an exception is
thrown. Typically, the system relay session will be forwarding
messages on behalf of local application code, rather than a remote
WebSocket client. Throwing an exception allows the application code
to be notified of the problem directly, rather than via a broker
availability event.
2013-09-30 14:21:42 -04:00
Rossen Stoyanchev
c06ea3b437 Polish logging 2013-09-26 21:27:11 -04:00
Rossen Stoyanchev
469aaa8754 Polish 2013-09-26 16:06:35 -04:00
Andy Wilkinson
6679feb77b Improve handling of missed heartbeats
Previously, when a broker heartbeat was mnissed, the STOMP connection
would be left in a semi-disconnected state such that, for example, the
read and write idle callbacks would still be active, even though
the underlying TCP connection had been nulled out.

As part of disconnecting the STOMP connection, this commit closes the
underlying TCP connection when a heartbeat's missed which cancels the
read and write idle callbacks. It also now copes with the underlying
TCP connection being null when sending a heartbeat to the broker. This
protects again a race condition between the write idle callback being
fired, such that a heartbeat needs to be sent, and the connection
being nulled out due to it being closed.
2013-09-26 16:06:35 -04:00
Andy Wilkinson
496d8321c3 Add heart-beat support to STOMP broker relay
Previously, the STOMP broker relay did not support heart-beats. It sent
0,0 in the heart-beats header for its own CONNECTED message, and set the
heart-beats header to 0,0 when it was forwarding a CONNECTED from from a
client to the broker.

The broker relay now supports heart-beats for the system relay session.
It will send heart-beats at the send interval that's been negotiated
with the broker and will also expect to receive heart-beats at the
receive interval that's been negotiated with the broker. The receive
interval is multiplied by a factor of three to satisfy the STOMP spec's
suggestion of lenience and ActiveMQ 5.8.0's heart-beat behaviour (see
AMQ-4710).

The broker relay also supports heart-beats between clients and the
broker. For any given client's relay session, any heart-beats received
from the client are forwarded on to the broker and any heart-beats
received from the broker are sent back to the client.

Internally, a heart-beat is represented as a Message with a byte array
payload containing the single byte of new line ('\n') character and
'empty' headers. SubscriptionMethodReturnValueHandler has been updated
to default the message type to SimpMessageType.MESSAGE. This eases
the distinction between a heartbeat and a message that's been created
from a return value from application code.
2013-09-26 16:06:35 -04:00
Andy Wilkinson
8d2a376b0f Remove CONNECT-related message buffer from STOMP relay
Before this change, the StompProtocolHandler always responded to
clients with a CONNECTED frame, while the STOMP broker relay
independantly forwarded the client CONNECT to the broker and waited
for the CONNECTED frame back. That meant the relay had to buffer
client messages until it received the CONNECTED response from
the message broker.

This change ensures that clients wait for a CONNECTED frame from
the message broker. The broker relay forwards the CONNECT frame to
the broker. The broker responds with a CONNECTED frame, which the
relay then forwards to the client. As a result, a (well-written)
client will not send any messages to the relay until the connection
to the broker is fully established.

The StompProtcolHandler can now be configured whether to send CONNECTED
frame back. By default that is off. So when using the simple broker,
the StompProtocolHandler can still respond with CONNECTED frames.

The relay's handling of a connection being dropped has also been
improved. When a connection for a client relay session is dropped
an ERROR frame will be sent back to the client. If a connection is
closed as part of a DISCONNECT frame being sent, no ERROR frame
is sent back to the client. When the connection for the system relay
session is dropped, an event is published indicating that the broker
is unavailable. Reactor's TcpClient will then attempt to re-restablish
the connection.
2013-09-26 16:06:35 -04:00
Andy Wilkinson
a489c2cf38 Add StompCodec
Previously, the broker relay's TCP client used Reactor's built in
delimited codec as part of its parsing of STOMP frames. \0 was used as
the delimiter. This worked for most STOMP frames but, crucially,
not for frames with a body that contained \0: when such a frame was
received it would be truncated.

This commit adds a custom codec that parses STOMP frames more
intelligently. It honours the content-length header allowing it to
correctly parse frames with a body that contains \0. The codec largely
delegates to two new classes: StompEncoder and StompDecoder. For
consistency, code that previously used StompMessageConverter has been
reworked to use these new encoder and decoder classes.

Issue: SPR-10818
2013-09-26 16:06:34 -04:00
Rossen Stoyanchev
45eab23e15 Rename @ReplyTo to @SendTo 2013-09-08 21:22:53 -04:00
Sam Brannen
41fa15a484 Polish Javadoc for messaging annotations 2013-09-07 22:07:09 +02:00
Rossen Stoyanchev
71e76196fe Polish StompProtocolHandler 2013-09-05 21:40:15 -04:00
Rossen Stoyanchev
1c47c8f35c Remove TODOs (replaced with JIRA tickets)
Issue: SPR-10703
2013-09-03 23:29:20 -04:00
Juergen Hoeller
8a4c6eb605 Fixed accidental use of Reactor's Assert util
Issue: SPR-10880
2013-09-03 23:56:43 +02:00
Rossen Stoyanchev
30d2f783a7 Modify return type of subProtocolWebSocketHandler bean
The @Bean method now returns WebSocketHandler allowing it to be
decorated via WebSocketHandlerDecorator.
2013-09-03 15:26:47 -04:00
Rossen Stoyanchev
0ac6998e60 Refine destination semantics for msg-handling methods
After this change, annotated message handling methods configured to use
a destination prefix (e.g. "/app") no longer have to include the prefix
in their mapping. For example if a client sends a message to "/app/foo"
the annotated methods should be mapped with @MessageMapping("/foo").
2013-09-03 11:04:00 -04:00
Rossen Stoyanchev
e1a46bb57a Add tests to spring-messaging 2013-09-02 20:36:54 -04:00
Rossen Stoyanchev
e21bbdd933 Polish WebSocket/STOMP Java config
Ensure configuration provided for WebSocketHandler's (eg interceptors,
or HandshakeHandler) are passed on to the SockJsService if congiured.

Better separate Servlet-specific parts of the configuration to make it
more obvious where non-Servlet alternatives could fit in.

Add more tests.

Improve WebSocket integration tests.
2013-09-02 09:11:26 -04:00
Rossen Stoyanchev
5d69700515 Remove incorrect package import
Issue: SPR-10880
2013-09-02 09:11:26 -04:00
Rossen Stoyanchev
cbdb99c042 Add basic javadoc to spring-messaging annotations 2013-08-29 14:09:52 -04:00
Rossen Stoyanchev
39ff1e2c53 Add StompProtocolHandler tests 2013-08-29 09:58:41 -04:00
Andy Wilkinson
364bc35709 Use correct header for version in CONNECTED frame
Previously, the negotiated version was included in the CONNECTED frame
using the accept-version header. This is incorrect. The version
header should be used.
2013-08-29 09:58:41 -04:00
Rossen Stoyanchev
80812d30d4 Protect STOMP passcode from showing up in logs
Issue: SRP-10868
2013-08-28 23:51:08 -04:00
Rossen Stoyanchev
f0dda0e38b Add WebSocket integration tests w/ Java configuration
Issue: SPR-10835
2013-08-28 21:11:05 -04:00
Rossen Stoyanchev
4b2847d9d1 Add ChannelInterceptor to spring-messaging module
Issue: SPR-10866
2013-08-28 14:41:20 -04:00
Rossen Stoyanchev
4c0da5867a Add Java config support for WebSocket and STOMP
Issue: SPR-10835
2013-08-27 22:20:07 -04:00
Rossen Stoyanchev
750930fa25 Fix bug with the order of messaging arg resolvers 2013-08-27 15:05:34 -04:00
Rossen Stoyanchev
402a3b8473 Fix javadoc 2013-08-27 12:48:48 -04:00
Jan Machacek
3f130a1c08 Add support for custom types in AMMH 2013-08-27 12:43:21 -04:00
Rossen Stoyanchev
68c0df8305 Polish StompBrokerRelayMessageHandler 2013-08-19 21:16:00 -04:00
Rossen Stoyanchev
94fefec0f9 Add ActiveMQ-based STOMP relay integration tests 2013-08-19 21:16:00 -04:00
Andy Wilkinson
3fb5ff2654 Improve broker availability events
Use a single class for the broker availability event with a boolean
that indicates whether or not the broker is available, rather than one
event for an available broker and one event for an unavailable broker.

Publish broker availability events in SimpleBrokerMessageHandler so that
it can be used as a drop-in replacement for
StompBrokerRelayMessageHandler.
2013-08-19 21:16:00 -04:00
Andy Wilkinson
131b5de6f9 Add reconnect logic to the relay's system session
Upgrade to Reactor snapshot builds to take advantage of TcpClient's
reconnect support that was added post-M1. Now, the system relay session
will try every 5 seconds to establish a connection with the broker, both
when first connecting and in the event of subsequently becoming
disconnected.

A more sophisticated reconnection policy, including back off and
failover to different brokers, is possible with the Reactor API. We may
want to enhance the relay's reconnection policy in the future.

Typically, a broken connection is identified by the failure to forward
a message to the broker. As things stand, the message id then discarded.
Any further messages that are forwarded before the connection's been
re-established are queued for forwarding once the CONNECTED frame's been
received. We may want to consider also queueing the message that failed
to send, however we would then need to consider the possibility of the
message itself being what caused the broker to close the connection
and resending it would simply cause the connection to be closed again.
2013-08-19 21:15:59 -04:00
Andy Wilkinson
8b48d8f445 Publish events about broker's availability
Components that are using a StompBrokerRelayMessageHandler may want
to know whether or not the broker's unavailable. If they're sending
messages to the relay via an asynchronous channel there's currently
no way for them to find this out.

This commit enhances StompBrokerRelayMessageHandler to publish
application events when the broker's availability changes:
BrokerBecameAvailableEvent and BrokerBecameUnavailableEvent.
Irrespective of the number of relay sessions only a single event is
published for each change in the broker's availability.
2013-08-19 21:15:59 -04:00
Andy Wilkinson
be6dbe54a3 Integration tests for the broker relay 2013-08-19 21:15:59 -04:00
Rossen Stoyanchev
01feae0ad5 Polish WebSocketSession
Update methods available on WebSocketSession interface.
Introduce DelegatingWebSocketSession interface.
2013-08-13 17:28:00 -04:00
Andy Wilkinson
9e20a25607 Introduce SubProtocolHandler abstraction
Add SubProtocolHandler to encapsulate the logic for using a
sub-protocol.

A SubProtocolWebSocketHandler is also provided to
delegate to the appropriate SubProtocolHandler based on the
negotiated sub-protocol value at handshake.

StompSubProtocolHandler provides handling for STOMP messages.

Issue: SPR-10786
2013-08-01 17:31:27 -04:00
Andy Wilkinson
4390591b68 Make BeanFactoryMCDR BeanFactoryAware
SI's BeanFactoryChannelResolver was BeanFactoryAware. This commit
brings Spring's BeanFactoryMessageChannelDestinationResolver in line
with the old SI class.
2013-07-24 16:45:52 -04:00
Rossen Stoyanchev
02949fc4a7 Fix failing tests 2013-07-21 20:39:07 -04:00
Rossen Stoyanchev
b3c7c18c1b Add MessageHandler destination prefix checks 2013-07-21 12:07:50 -04:00
Rossen Stoyanchev
2cdac267f7 Add MessageMethodArumentResolver 2013-07-21 12:07:50 -04:00
Rossen Stoyanchev
90c4712d06 Revise UserSessionResolver to UserQueueSuffixResolver
The resolver for /user/{username} prefixed destinations is now
more explicitly designed to store queue suffixes rather than session
id's, which is what we happen to use as queue suffixes.

This allows something other than the sessionId to be used without
having to change many places. It also enables applications to
construct destinations with user-specific queue suffixes without
making assumptions about what's used for queue suffixes. For
example a controller may construct a map with subscription destinations
and send that down to the client.
2013-07-19 17:22:58 -04:00
Rossen Stoyanchev
3272917cf2 Polish concurrency in UserSessionResolver impl 2013-07-19 10:57:23 -04:00
Rossen Stoyanchev
aa6f30482f Reverse change committed erroneously 2013-07-17 23:00:17 -04:00
Rossen Stoyanchev
a109d6adc7 Set heartbeat to 0,0 on CONNECT to message broker 2013-07-17 22:40:44 -04:00
Rossen Stoyanchev
8a8501a992 Polish 2013-07-17 18:23:27 -04:00
Rossen Stoyanchev
329fbf31bc Fix concurrency issue in DefaultSubscriptionRegistry 2013-07-17 18:16:39 -04:00
Rossen Stoyanchev
d73c2e26a5 Polish handling of STOMP message headers 2013-07-17 13:58:45 -04:00
Rossen Stoyanchev
ba7998d03b Add SimpMessageSendingOperations 2013-07-17 10:09:55 -04:00