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.
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.
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.
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
This fine-tuned change restores the original Spring 3.0 behavior for Oracle AQ, and also allows for other ConnectionFactory types to comply with the "getDataSource()" pattern.
Issue: SPR-10829
Prior to this commit, the DispatcherServlet would send an error
response using the HttpServlet API when no Handler was found to
handle this request.
Now the DispatcherServlet can be configured to throw a
NoHandlerFoundException, when the throwExceptionIfNoHandlerFound
property is set to "true".
Those exceptions can be later on caught by default or custom
HandlerExceptionResolvers/ExceptionHandlers.
Issue: SPR-10481
Prior to this commit, RestTemplate would not would
not accept IPv6 raw addresses in URLs because UriComponentsBuilder
would not parse/encode the Host part correctly.
The UriComponentsBuilder now parses and encode raw IPv6 addresses
in the "[1abc:2abc:3abc::5ABC:6abc]" format and also supports the
use of IPv6 scope_ids (see JDK8 java.net.Inet6Address),
like "[1abc:2abc:3abc::5ABC:6abc%eth0]".
Issue: SPR-10539
S0 doesn't seem to be universally used for SQL grammar problems: see MS SQL Server's RAISERROR. This was reported years back; not sure why the fix didn't actually appear in the codebase back then.
Issue: SPR-10902
Update CallMetaDataContext to use the metaDataProvider
createDefaultOutParameter method when creating a SqlOutParameter as
a result of a SQL function call.
This change allows Spring to support Oracle cursor types when returned
from functions.
Issue: SPR-10606
Update `CacheAspectSupport` to expand any var-arg parameters before
calling `KeyGenerator` implementations. Prior to this commit var-args
would be passed to `KeyGenerator` implementations as a nested array,
often causing the same key to be generated regardless of the arguments.
Issue: SPR-10870
Extended DefaultAopProxyFactory to create Objenesis based proxies if the
library is on the classpath. This allows classes without a default
constructor being CGLib proxied. We're now falling back to original CGLib
based behavior in case the proxy creation using Objenesis fails.
Objenesis 2.0 is now inlined into spring-core to avoid interfering with
other Objenesis versions on the classpath.
Issue: SPR-10594
This commit undoes the changes made in ec5d81e78e and ensures that the
getRequestURL() method in MockHttpServletRequest does not include the
String "null" for a null requestURI by first checking if the requestURI
contains text before including it in the composed URL.
Issue: SPR-10643