This change removes the recently added SockJsThreadPoolTaskScheduler
and instead builds support for the removeOnCancelPolicy property in
ThreadPoolTaskScheduler and ScheduledExecutorFactoryBean.
Issue: SPR-11918
When a WebSocket session is closed after not having received any
messages, we'll use SESSION_NOT_RELIABLE to indicate to other parts
of the session closing code not to send anything further (e.g.
SockJS "Go Away!" frame).
Issue: SPR-11884
This change ensures the state of a SockJS session is set to CLOSED
immediately after close is invoked. This avoids duplicate invocations
of afterConnectionClosed in WebSocket transport.
Issue: SPR-11884
Update WebSocketSession toString methods to include the handshake URI
and add id and URI fields to ensure they're available after close().
Log WebSocket session open and close events at INFO.
Remove trace messages for destinations that do not match.
Issue: SPR-11884
This commit validates that the changes introduced in 8221c9abc5 are
indeed allowing DirectFieldBindingResult to support nested validation
paths.
Issue: SPR-10623
Optimize logging with tracking the opening and closing of WebSocket
sessions and STOMP broker connections in mind.
While the volume of messages makes it impractical to log every message
at anything higher than TRACE, the opening and closing of connections
is more manageable and can be logged at INFO. This makes it possible to
drop to INFO in production and get useful information without getting
too much in a short period of time.
The logging is also optimized to avoid providing the same information
from multiple places since messages pass through multiple layers.
Issue: SPR-11884
Prior to this commit, the ServletResponseHttpHeaders.get method
would throw an NPE when used under Wildfly 8.0.0.Final and 8.1.0.Final.
This can be traced to WFLY-3474, which throws an NPE when calling
HttpServletResponse.getHeaders("foo") and that header has not
been defined prior to that.
This would cause NPE being thrown by AbstractSockJsService when
checking for CORS HTTP headers in the server HTTP response.
This commit surrounds that method call in AbstractSockJsService and
guards against this issue.
Issue: SPR-11919
This commit adds a nested path support for DirectFieldAccessor that is
similar to what BeanWrapper provides. It is now possible to use
expressions such as "person.address.city.name" to access the name of
the city that a given person lives in using fields to traverse the
graph.
DirectFieldAccessor also now supports an auto-grow option to create
a default instance for a "null" intermediate path. This option is
false by default and leads to a NullValueInNestedPathException in such
a case.
This commit also harmonizes part of the tests suite so that core tests
are shared between BeanWrapperImpl and DirectFieldAccessor.
Note that map and list access is not implemented as part of this
commit.
Issue: SPR-9705
In a recent CI build failure a test timed out waiting for a message:
https://build.spring.io/browse/SPR-PUB-1316
In fact there was a WebSocket transport failure originating in Jetty's
WebSocket Parser. However this failure is only apparent by looking at
the logs. This change adds a check if a transport error ocurred while
we were waiting and throws an AssertionError.
Sessions connected to a STOMP endpoint are expected to receive some
client messages. Having received none after successfully connecting
could be an indication of proxy or network issue. This change adds
periodic checks to see if we have not received any messages on a
session which is an indication the session isn't going anywhere
most likely due to a proxy issue (or unreliable network) and close
those sessions.
Issue: SPR-11884
Prior to this commit, calls to getAllow would fail is setAllow was set
to an EmptyCollection right before.
java.lang.IllegalArgumentException: No enum constant
org.springframework.http.HttpMethod
This commit fixes this by testing the header value for an empty value
before trying to use it to get a value from the Enum.
Issue: SPR-11917
This commit deletes all test annotations from the spring-orm module in
order to reduce unnecessary confusion between these "copies" and the
real, current versions of such classes in the spring-test module.
Furthermore, the legacy abstract JUnit 3.8 base classes and test cases
have been refactored accordingly.
Commit 5d2e6f enabled the setRemoveOnCancelPolicy of the SockJS
ScheduledThreadPoolExecutor by default. However that property is only
available in JDK 1.7 or later. This change fixes the issue and
introduces an extension of ThreadPoolTaskScheduler for for use with
SockJS which is necessary in any case since ThreadPoolTaskScheduler
does not expose the underlying ScheduledThreadPoolExecutor otherwise.
Issue: SPR-11918
This change sets the removeOnCancelPolicy on the SockJS
ScheduledThreadPoolExecutor to true. This ensures that cancelled
tasks are removed immediately to avoid the "unbounded retention
of cancelled tasks" that is mentioned in the Javadoc of
ScheduledThreadPoolExecutor:
"By default, such a cancelled task is not automatically removed from
the work queue until its delay elapses. While this enables further
inspection and monitoring, it may also cause unbounded retention of
cancelled tasks. To avoid this, set setRemoveOnCancelPolicy to true,
which causes tasks to be immediately removed from the work queue at
time of cancellation."
Issue: SPR-11918
This change ensures the server "WebSocketHandler" is notified of the
opening of a session before writing the open frame to the remote
handler. Any messages sent by the server "WebSocketHandler" while
getting notified of the opening get cached and flushed after the open
frame has been written.
This change introduces locking in AbtractHttpSockJsSession to guard
access to the HTTP response. The goal is to prevent contention between
client requests to receive messages (i.e. long polling) and
the application trying to write.
Issue: SPR-11916
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