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
The JettySockJsIntegrationTests are enabled in the performance build
only. Following the upgrade to Jetty 9.3 where the
JettyRequestUpgradeStrategy is now Lifecycle as wel as
ServletContextAware, we need to make sure the ApplicationContext
refresh occurs after the ServletContext has been set. This change
removes the explicit .refresh() call in the test setup and instead
relies on the DispatcherServlet to do that, which ensures that the
ServletContext with which it is initialized by Jetty has been set
on the ApplicationContext before that.
Prior to this commit, Spring's MimeType checked for equality between
two MIME types based on the equality of their properties maps; however,
the properties maps contain string representations of the "charset"
values. Thus, "UTF-8" is never equal to "utf-8" which breaks the
contract for character set names which must be compared in a
case-insensitive manner.
This commit addresses this issue by ensuring that "charset" properties
in MimeType instances are compared as Java Charset instances, thereby
ignoring case when checking for equality between charset names.
Issue: SPR-13157
Prior to this commit, it was only possible to declare SQL statements
via @Sql within external script resources (i.e., classpath or file
system resources); however, many developers have inquired about the
ability to inline SQL statements with @Sql analogous to the support for
inlined properties in @TestPropertySource.
This commit introduces support for declaring _inlined SQL statements_
in `@Sql` via a new `statements` attribute. Inlined statements are
executed after statements in scripts.
Issue: SPR-13159
After this change JettyRequestUpgradeStrategy implements Lifecyle,
which is used to init and cleanup the Jetty WebSocketServerFactory.
Since a RequestUpgradeStrategy is typically created reflectively
within DefaultHandshakeHandler, the Lifecycle events are propagated
from the top, i.e. the Spring MVC HandlerMapping through the
WebSocket/SockJsHttpRequestHandler.
Issue: SPR-13140
This commit adds canWrite() and write() methods to the
GenericHttpMessageConverter interface. These are type aware variants
of the methods available in HttpMessageConverter, in order to keep
parametrized type information when serializing objects.
AbstractMessageConverterMethodProcessor now calls those type aware
methods when the message converter implements GenericHttpMessageConverter.
AbstractJackson2HttpMessageConverter and GsonHttpMessageConverter uses
these new methods to make @ResponseBody method return type available
for type resolution instead of just letting the JSON serializer trying
to guess the type to use from the object to serialize.
Issue: SPR-12811
Previously, a method could only declare one Jms endpoint so if several
destinations share the exact same business logic, you'd still need one
separate method declaration per destination.
We now make sure that JmsListener is a repeatable annotation, introducing
JmsListeners for pre Java8 use cases.
Issue: SPR-13147
This change fixes a NullPointerException in GzipResourceResolver, which
assumed that calls to the `resolveResource` method were made with only
non-null values for request.
This is not the case for the VersionResourceResolver, which tries to
resolve resources that aren't requested per se by the HTTP request.
Issue: SPR-13149
This commit introduces a convenience method in AnnotationUtils for
synthesizing an annotation from its default attribute values.
TransactionalTestExecutionListener has been refactored to invoke this
new convenience method.
Issue: SPR-13087
This commit introduces support for automatically resolving a container
annotation configured via @Repeatable in AnnotationUtils'
getRepeatableAnnotations() and getDeclaredRepeatableAnnotations()
methods.
Issue: SPR-13068
This commit introduces a minor bug fix for getRepeatableAnnotations()
so that it fully complies with the contract of Java's
getAnnotationsByType() method with regard to repeatable annotations
declared on multiple superclasses.
Issue: SPR-13068
- Simplified "check" algorithms in CorsConfiguration
- Improved robustness of setter methods in CorsConfiguration in order to
avoid attempts to modify immutable lists
- Improved CORS documentation and fixed typo
- Introduced constants in CorsConfiguration
- Removed auto-boxing in CorsRegistration
Prior to this commit, the implementation of getRepeatableAnnotation()
in Spring's AnnotationUtils complied neither with the contract of
getAnnotationsByType() nor with the contract of
getDeclaredAnnotationsByType() as defined in AnnotatedElement in Java 8.
Specifically, unexpected results can be encountered when using Spring's
support for @Repeatable annotations: either annotations show up in the
returned set in the wrong order, or annotations are returned in the set
that should not even be found based on the semantics of @Repeatable.
This commit remedies this problem by deprecating the existing
getRepeatableAnnotation() methods and replacing them with new
getRepeatableAnnotations() and getDeclaredRepeatableAnnotations()
methods that comply with the contracts of Java's getAnnotationsByType()
and getDeclaredAnnotationsByType(), respectively.
Issue: SPR-13068
The initial support for synthesizing an annotation from a Map (or
AnnotationAttributes) introduced in SPR-13067 required that the map
contain key-value pairs for every attribute defined by the supplied
annotationType. However, there are use cases that would benefit from
being able to supply a reduced set of attributes and still have the
annotation synthesized properly.
This commit refines the validation mechanism in
MapAnnotationAttributeExtractor so that a reduced set of attributes may
be supplied. Specifically, if an attribute is missing in the supplied
map the attribute will be set either to value of its alias (if an alias
value configured via @AliasFor exists) or to the value of the
attribute's default value (if defined), and otherwise an exception will
be thrown.
Furthermore, TransactionalTestExecutionListener has been refactored to
take advantage of this new feature by synthesizing an instance of
@TransactionConfiguration solely from the default values of its
declared attributes.
Issue: SPR-13087
Before this change ResponseStatusExceptionResolver always used
.sendError despite the javadoc on @ResponseStatus#code. This was
perhaps justifiable from a HandlerExceptionResolver. Nevertheless
.setStatus should be more REST API friendly while still marking
the response as an error.
Issue: SPR-11193
Before this change the AbstractMessageConverterMethodProcessor always
raised a 406 if it couldn't find a converter. However if the reason
for not finding it is because there is simply no converter for the
return value type (i.e. programming error) and doesn't have anything to
do with content negotiation, then we should raise a 500 instead and
make it easier to figure out what's wrong.
Issue: SPR-13135