When connecting with a ReconnectStrategy we can only report the outcome
of the first connect to the ListenableFuture<Void> return value.
Failures for all subsequent attempts to reconnect however must be
channeled to TcpConnectHandler#afterConnectFailure which is used in
the STOMP broker relay for example to publish
BroadcastAvailability(true/false) events.
When decoding STOMP messages unread portions of a given input ByteBuf
must be kept until more input is received and the next complete STOMP
frame can be parsed.
In Reactor Net 2.x this was handled for us through the "remainder"
field in NettyChannelHandlerBridge. The Reactor Netty 0.6 upgrade
however applied only a simple map operator on the input ByteBuf
after which the buffer is relased.
This commit replaces the use of a simple map operator for decoding
and installs a ByteToMessageDecoder in the Netty channel pipeline
which has a built-in ability to preserve and merge unread input into
subsequent input buffers.
reactor-netty-0.6.0.RELEASE on Maven Central depends on
reactor-ipc-0.6.0.RELEASE so no need for this repository anymore.
It may be needed to cleanup Gradle or Maven local cache
since preliminary version of reactor-netty-0.6.0.RELEASE
had a dependency on reactor-ipc-0.6.0.BUILD-SNAPSHOT.
This commit removes the statically created XnioWorker which is an
"active" component and should not be created automatically and could
lead to resource leaks. Instead XnioWorker is now required at
construction aligning better with WebSocketClient#connectionBuilder
which also does not have a "default" worker option.
Since the XnioWorker is the main input for creating a ConnectionBuilder
we now create the ConnectionBuider in a protected method and then allow
a Consumer<ConnectionBuilder> to configure it further as opposed to the
Function<URI, ConnectionBuilder> used previously.
This commit also removes default SSL context initialization for RxNetty
to better align with other client implementations.
Issue: SPR-14527
The HandlerSubcriber from each listener session implementation is now
consolidated into AbstractListenerWebSocketSession since the handling
of onComplete or onError in any case is about delegating to the
session.
This also allows for the UndertowWebSocketHandlerAdapter to become
simply an (Undertow) AbstractReceiveListener.
Issue: SPR-14527
This commit removes the base class WebSocketHandlerAdapterSupport which
was mainly a container for properties. Instead we use a
java.util.Function to create the WebSocketSession which differs in any
way by client and server, which in turn allows HandshakeInfo to become
a simple immutable container once again.
Also for Undertow the WebSocketConnectionCallback implementation has
been moved into the server.upgrade package since it is for server-side
use only.
Issue: SPR-14527
The most common use case is specifying JSON views.
ServerResponse.BodyBuilder#hint(String, Object) allows to
specify response body serialization hints.
ServerRequest#body(BodyExtractor, Map) allows to specify
request body extraction hints.
Issue: SPR-15030
- RxNettyWebSocketSession filters out WebSocketCloseFrame again
- add before/afterHandshake helper methods in WebSocketClientSupport
- log request headers on server and response headers on client
- polish 400 request handling in HandshakeWebSocketService
WebSocket frames are now aggregated through a Netty decoder so that
we always receive fully assembled messages by default capped at 64K.
Issue: SPR-14527
Rename classes not specific to Tomcat:
TomcatWebSocketSession -> StandardWebSocketSession
TomcatWebSocketHandlerAdapter -> StandardWebSocketHandlerAdapter
WebSocketSessionSupport is renamed to AbstractWebSocketSession since it
actually is a WebSocketSession and pre-implements a number of methods.
ServerEndpointRegistration is now package private (mainly for use in
upgrade strategies) and renamed to DefaultServerEndpointConfig.
Switch from returning Mono<WebSocketSession> to take a WebSocketHandler
and return Mono<Void> for the entire session handling.
The WebSocketHandler callback delimits the stard and end of protocol
handling and forces the handler to operate within the scope of the
Reactor operators.
Give the full duplex nature of WebSockets, the symmetry between client
and server (each now using WebSocketHandler) also seems appropriate.
Issue: SPR-14527
The WebSocketHander adapters are now neutral for client vs server-side
use with the adapters for RxNetty and Reactor Netty (server-side only)
completely removed.
A new HandshakeInfo carries information about the handshake including
URI, headers, and principal from the upgrade strategy, to the adapter,
and then to the session.
WebSocketSession exposes the HandshakeInfo as well reducing its overall
number of methods.
Move WebSocketMessage factory methods to the WebSocketSession which
has the bufferFactory() needed to create message payloads.
WebSocketMessage is left with one public constructor.
WebSocketMessage exposes convenience retain/releasePayload methods.
Expose bufferFactory() at the WebSocketSession level for creating
payloads like ReactiveHttpOutputMessage does.
Promote getId(), getUri(), and bufferFactory() to the base class
WebSocketSessionSupport.
Apply the new HttpHeaders#getAcceptLanguageAsLocale() in places where
it was hardcoded or defaulting.
Apply ServerHttpResponse.encodeUrl in RequestContext.
Issue: SPR-15024
An update on the last commit switching from:
List<Locale> getAcceptLanguageAsLocales() to
Locale getAcceptLanguageAsLocale()
This best supports the scenario for the most preferred Locale.
If there is a need to look at the prioritized list of languages it's
best to use Locale.filter with the LocaleRange's.
This is explained in the Javadoc for getAcceptLanguage().
Issue: SPR-15024
The use of Locale.LanguageRange for the Accept-Language header makes
sense as it gives the most flexibility for a client to set a weighted
list and for a server to do filtering via Locale#filter.
This commit adds an additional convenience method that turns
the LangugeRange list to a list of Locale's also filtering out a
wildcard (i.e. "*"). A List<Locale> is the most basic way to access
prefered languages and needed when filtering is not required.
Issue: SPR-15024
Previously ForwrdedHeaderFilter did not ensure that
HttpServletResponse.sendRedirect worked properly based on
X-Forwarded-* headers.
This commit updates ForwardedHeaderFilter to overrided the
HttpServletResponse.sendRedirect method to ensure
X-Forwarded-* headers are honored.
Issue SPR-15020
ServerWebExchange.Builder has an additional Consumer-style shortcut
method that accepts a builder for modifying the request.
ServerWebExchange and ServerHttpRequest builders have fewer methods,
more use-case focused vs matching directly to properties.
ServerWebExchange now provides access to "requestParams" as a
MulitValueMap with query parameters and form data combined.
The combined map is then used for the params condition of
@RequestMapping purposes () and also for @RequestParam arguments.
Issue: SPR-15000
This is similar to the WriteListener changes on the ServerHttpResponse
where we are more naturally exposed to a delayed write. Nevertheless
we could also have a delayed read and should be consistent. The early
initialization of the RequestBodyPublisher also simplifies the
internal implementation a bit.
Instead of registering an AsyncListener in ServletHttpHandlerAdapter
we now register an AsyncListener in each of the request and response
where the events need to be handled anyway. This allows removing the
package private delegation methods in the request and response.
This commit makes it possible for handler functions to return
asynchronous status codes and headers, by making HandlerFunction.handle
return a Mono<ServerResponse> instead of a ServerResponse. As a
consequence, all other types that deal with HandlerFunctions
(RouterFunction, HandlerFilterFunction, etc.) had to change as well.
However, when combining the above change with method references (a very
typical use case), resulting signatures would have been something like:
```
public Mono<ServerResponse<Mono<Person>>> getPerson(ServerRequest request)
```
which was too ugly to consider, especially the two uses of Mono. It was
considered to merge ServerResponse with the last Mono, essentialy making
ServerResponse always contain a Publisher, but this had unfortunate
consequences in view rendering.
It was therefore decided to drop the parameterization of ServerResponse,
as the only usage of the extra type information was to manipulate the
response objects in a filter. Even before the above change this was
suggested; it just made the change even more necessary.
As a consequence, `BodyInserter` could be turned into a real
`FunctionalInterface`, which resulted in changes in ClientRequest.
We did, however, make HandlerFunction.handle return a `Mono<? extends
ServerResponse>`, adding little complexity, but allowing for
future `ServerResponse` subtypes that do expose type information, if
it's needed. For instance, a RenderingResponse could expose the view
name and model.
Issue: SPR-14870
Similar pattern as for ServerWebExchange with a default mutate method
on ServerHttpRequest returning a Builder and eventually creating an
immutable wrapper.
HttpHandlerAdapterSupport uses the builder to set the contextPath.
Remove duplicated ServerHttpResponse#setComplete also declard in the
parent ReactiveHttpOutputMessage interface.
Also rename:
ServerWebExchange.MutativeBuilder --> ServerWebExchange.Builder
This commit makes it possible for a ChannelInterceptor to override the
user header in a Spring Message that contains a STOMP CONNECT frame.
After the message is sent, the updated user header is observed and
saved to be associated with session thereafter.
Issue: SPR-14690
Now that reactor/reactor-netty#12 is fixed, we can restore the
previously ignored integration tests.
New tests are hanging, so this commit is converting the `StepVerifier`
`verify()` calls to using actual timeouts.
Issue: SPR-14975
The WebSocketHandler adapters for all runtimes now extend
WebSocketHandlerAdapterSupport, which now also exposes
a shared DataBufferFactory property initialized from the response.
Issue: SPR-14527
suspend/resumeReceiving in the AbstractListenerWebSocketSession are
now abstract methods. In Tomcat/Jetty these methods are no-op
implementations that are then coupled with a buffering strategy via
Flux#onBackpressureBuffer. In Undertow they rely on flow control for
receiving WebSocket messages.
Issue: SPR-14527
- Added suspended flag to indicate whether the ReceivePublisher
is able to process the incoming messages.
- Use buffer strategy for the incoming messages.
Issue: SPR-14527
Dropped "Support" from the name since it not only provides support
methods but actually implements WebSocketSession.
Renamed inner classes:
WebSocketMessagePublisher -> WebSocketReceivePublisher
WebSocketMessageProcessor -> WebSocketSendProcessor
Add protected getter for sendProcessor.
Reduce scoping:
WebSocketReceivePublisher -> private
WebSocketSendProcessor -> protected
WebSocketSendProcessor#setReady -> public (class is still protected)
A few more method name alignments and Javadoc updates.
Issue: SPR-14527
AbstractRequestBodyPublisher and AbstractResponseBodyProcessor are now
used for WebSocket messages too and have been renamed more generally to
AbstractListenerReadPublisher and AbstractListenerWriteProcessor.
Issue: SPR-14527
This commit also migrates from a WeakHashMap to a ConcurrentReferenceHashMap, allowing for concurrent access to existing cache entries.
Issue: SPR-15006
When getting the lookup path of a resource, both query params and hashes
should be removed from the request path.
This commit fixes the public path resolution for paths like
`/resources/main.svg#icon-hamburgermenu`.
Issue: SPR-14928
Prior to this commit, `@ExceptionHandler` methods could not be injected
with `RedirectAttributes` arguments. This would make it impossible to
handle an error by redirecting to another view and add flashmap
attributes, to be included in the model when the next view is called.
Here is an example:
```
@ExceptionHandler(MyException.class)
public String handleException(MyException ex, RedirectAttributes
redirectAttributes) {
redirectAttributes.addFlashAttribute("errorMessage",
"This is an error message");
return "redirect:/";
}
```
This commit adds a new `RedirectAttributesMethodArgumentResolver`
instance in the list of pre-configured `HandlerMethodArgumentResolver`
in `ExceptionHandlerExceptionResolver`.
Issue: SPR-14651
Due to a few changes in `WebSocketServerFactory` and `Session` API, our
`JettyRequestUpgradeStrategy` and `JettyWebSocketSession` needed to
adapt. As of 9.3.15+ and 9.4.0+, some reflection is required to support
previous versions.
Spring 5.0 supports Jetty 9.3 and 9.4.
Issue: SPR-14940
This commit ensures that POST/PUT requests sent by the Netty client have
a Content-Length header set.
Integration tests have been refactored to use mockwebserver instead of
Jetty and have been parameterized to run on all available supported
clients.
Issue: SPR-14860
This commit changes RouterFunctions.toHttpHandler to return
HttpWebHandlerAdapter (instead of HttpHandler), so that WebFilters and
WebExceptionHandler can be applied to it.
Issue: SPR-14979
This commit adds the ability to serve Resources (static files) through a
RouterFunction. Two methods have been added to RouterFunctions: one that
exposes a given directory given a path pattern, and a generic method
that requires a lookup function.
Issue: SPR-14913
Create a ReactorNettyCodec to hold the decoding and encoding function
and consumer along with a package-private sub-class that delegates to
StompDecoder and StompEncoder.
Issue: SPR-14531
* getBeanDefinitionNames defensively returns a copy of the bean definition names array.
* copyConfigurationFrom provides an independent AutowireCandidateResolver instance and copies a ConversionService and dependency comparator configuration as well.
* findAutowireCandidates only considers a self reference fallback for direct dependency declarations, not as a collection element.
Issue: SPR-14897
Issue: SPR-14921
Issue: SPR-14965
In general, web.util is supposed to remain lowest-level, not depending on any other web.* package. Since web.client also has a support package, a corresponding web.server.support package seemed appropriate for a helper class depending on ServerWebExchange in web.server itself.
The recent refactoring lead to
java.lang.NoClassDefFoundError: io/reactivex/Completable
where only RxJava 1 is in the classpath. Most likely due to the
lack of prefix in Completable::complete with rx package to avoid
the RxJava 2 reference.
Main differences with the Spring MVC original implementation:
- Default redirect HTTP code is 303 See Other since we can assume
all HTTP clients support HTTP 1.1 in 2016
- No more http10Compatible property, use statusCode instead
- By default the redirect is relative to the context path
- A builder allow to set various properties if needed
- In UrlBasedViewResolver, a Function<String, RedirectView>
redirectViewProvider property allows to customize RedirectView
instances in a flexible way
Issue: SPR-14534
Simplify getAdapterFrom/To into a single getAdapter method that looks
for an exact match by type first and then isAssignableFrom.
Also expose shortcut methods in ReactiveAdapter to minimize the need
for access to the ReactiveTypeDescriptor.
Issue: SPR-14902
The ReactiveAdapterRegistry now detects the presence of Reactor. In
practice Reactor is required for the Spring Framework reactive support
and it is expected to be present.
The registry however is now capable of being neutral if Reactor is not
present on the classpath for example where other Spring projects may
not have the same assumptions about Reactor's presence.
Issue: SPR-14902
Collapse ReactiveAdapter hierarchy into a single class that simply
delegates to functions for converting to/from a Publisher.
A private ReactorAdapter extension automaticlaly wraps adapted, "raw"
Publisher's as Flux or Mono depending on the semantics of the target
reactive type.
Issue: SPR-14902
This commit polishes previous one by also accepting
generic types explicitly declared with a class that
extends DataBuffer allowing to write Flux<DefaultDataBuffer>
for example.
Issue: SPR-14952
This modifies the signature of
ReactiveHttpOutputMessage#writeAndFlush(...) in order to
be able to use Flux<Flux<DataBuffer>> objects as arguments of
this method.
Issue: SPR-14952
This commit polishes Kotlin nullable support by reusing
MethodParameter#isOptional() instead of adding a new
MethodParameter#isNullable() method, adds
Kotlin tests and introduces Spring Web Reactive
support.
Issue: SPR-14165
Where `isOptional` is used, also check for `isNullable` i.e.
values are not considered required if they are Kotlin nullables:
- spring-messaging: named value method arguments
- spring-web: named value method arguments
- spring-webmvc: request parts
This means that Kotlin client code no longer has to explicity specify
"required=false" for Kotlin nullables -- this information is inferred
automatically by the framework.
Issue: SPR-14165
In case the filter is also registered to the ERROR dispatcher, the
following happens:
* the filter is executed once for the regular execution
* the filter should be executed a second time when dispatched to error
Since the filter is a `OncePerRequestFilter`, the filter is only
executed once and won't be executed when handling the error.
This can lead to situations like spring-projects/spring-boot#7348
This commit makes this filter a simple `GenericFilterBean`.
Issue: SPR-14891
When processing a "close" notification from the server make an effort
to cancel any outstanding heartbeat but avoid going as far as acquiring
the responseLock since the server itself may already hold a lock of its
own leading to a potential deadlock.
The heartbeat task is now also further protected with an isClosed()
check in case the heartbeat does not get cancelled in a concurrent
scenario.
Issue: SPR-14917
This commit adds a HTTP PATCH operation to the RestTemplate:
patchForObject. As with most operations, there are three variants:
varargs, Map, and URI based.
Issue: SPR-14857
Multi-value async attributes like Flux and Observable in the model
are treated with Collection semantics and resolved to Mono<List<?>>
prior to rendering.
Since https://jira.sonarsource.com/browse/SONARGRADL-30, we can now
safely update to sonarqube plugin v2.2.1.
The protobuf gradle plugin is now deprecated - instead of configuring
the new plugin supported by Google, this commits drops that part of the
gradle build since that proto->java conversion is rarely needed and can
be manually run by any member of the team.
When resolved through the `GzipResourceResolver`, CSS files can be
resolved as their pre-gzipped variant, if a ".gz" file is present in the
configured resource locations.
Such resources are gzipped and thus should not be transformed by
`CssLinkResourceTransformer`s, since rewriting those would need to
uncompress/transform/recompress. This would lead to poorer performances
than resolving plain resources and delegating compression to the
container.
This commit checks for `GzippedResource` instances in
`CssLinkResourceTransformer` and avoids processing them.
Issue: SPR-14773
This commit introduces a new ContentDisposition class designed
to parse and generate Content-Disposition header value as defined
in RFC 2183. It supports the disposition type and the name,
filename (or filename* when encoded according to RFC 5987) and
size parameters.
This new class is usually used thanks to
HttpHeaders#getContentDisposition() and
HttpHeaders#setContentDisposition(ContentDisposition).
Issue: SPR-14408
If the body class is not resolvable from the return type and there is
a body instance we now fall back on the class of the body instance.
Issue: SPR-14877
Prior to this commit, the wrong `HandlerResultHandler` could be
resolved when handling exceptions; this could happen only if the
original handler and exception handler had different signatures:
```
Publisher<String> originalHandler() { ... }
@ExceptionHandler(MyCustomException.class)
ResponseEntity<Mono<String>> handleException() { ... }
```
In that case, the `ResponseBodyResultHandler` would be used when
handling exceptions instead of the `ResponseEntityResultHandler`.
This commit ensures that the `HandlerResult` returned by the exception
handler is used to resolve the `HandlerResultHandler`. The latter will
process the result and use it to write to the HTTP response.
Issue: SPR-14876
This commit adds support for `@ResponseStatus` annotations on reactive
controller methods. `HandlerResultHandler`s implementations now
set the status on the `ServerWebExchange`, if and only if the
invocation of the controller method succeeded.
Issue: SPR-14830
This commits adds a validation check whether the SockJS session type
matches the transport type and rejects requests for which they
don't match.
Issue: SPR-14867
- ScriptedSubscriber has been renamed to Verifier
- The Publisher is passed to create() instead of verify()
- No more need to specify the generic type explicitly
- Version is now sync with reactor-core
Issue: SPR-14800
For SPR-14863 we need to adjust the code generation for OpNE
to use !x.equals(y) rather than x!=y. There are also further
cases in the equalityCheck() code in Operator that were not
being handled in the compilation case (when comparators are
used for example). This latter issue also affects OpEQ.
Rather than add yet more bytecode generation, both OpNE and
OpEQ generateCode() methods have been simplified. The
generated code now delegates to equalityCheck() in Operator
which is exactly what the interpreted case does.
This ensures that the compiled code continues to behave just
like the interpreted case. It ensures changes to the interpreted
case are automatically picked up for the compiled case. It
makes the bytecode generation simpler.
The benefit of compilation of SpEL expressions is to avoid
slow reflective calls - that doesn't apply for a basic
(in)equality test so there is no need to go crazy in bytecode
gen.
Issue: SPR-14863
The method to access the Principal from the ServerWebExchange is now
a Mono<Principal> (rather than Optional<Principal>).
There is also support for Principal as a controller method argument.
Issue: SPR-14680, SPR-14865
This commit adds support for detecting the target WebHandler along with
WebFilters, WebExceptionHandlers, and other spring-web reactive
strategies in an ApplicationContext.
WebReactiveConfigurationSupport has @Bean factory methods for
DispatcherHandler and ResponseStatusExceptionHandler.
WebHttpHandlerBuilder has a static factory method that initializes the
builder from an ApplicationContext. This method is also used in the
DispatcherHandler#toHttpHandler(ApplicationContext) shortcut method.
Issue: SPR-14837
The createBinder method in BindingContext now returns the binder
instance rather than a Mono with the expectation that binder
initialization (e.g. @InitBinder) does not require blocking.
Issue: SPR-14543
HandlerMethodArgumentResolver is a non-blocking contract, however only
implementations that read the request body require blocking.
This commit introduces SyncMethodArgumentResolver as an extension of
the non-blocking contract that allows synchronous implementations to
use synchronous argument resolution.
There is also a SyncInvocableHandlerMethod extension that uses only
sync argument resolvers and allows a synchronous invocation.
Issue: SPR-14543
This commit introduces the `DispatcherServletCustomizer` callback
interface that can be used to customize the `DispatcherServlet` that a
`MockMvc` is using.
Previously, only the `dispatchOptions` flag can be customized. This
commit allows to customize any property of `DispatcherServlet` before it
is initialized.
Issue: SPR-14277
The ServerWebExchange now has a getFormData() method that delegates to
FormHttpMessageReader for the parsing and then caches the result so
it may be used multiples times during request processing.
Issue: SPR-14541
This commit introduces two new `WebClient` methods: `retrieveMono` and
`retrieveFlux`, both of which offer direct access to the response body.
More importantly, these methods publish a WebClientException if the
response status code is in the 4xx or 5xx series.
Issue: SPR-14852
Prior to this commit, when using @EnabledIf or @DisabledIf in Spring's
JUnit Jupiter support, the test's ApplicationContext was always eagerly
loaded, even if the ApplicationContext would never be used (i.e., the
test was disabled). This behavior can lead to undesirable side effects
-- for example, attempting to load an application context that requires
services only available on the CI server when the test is not actually
running on the CI server.
This commit addresses this issue by introducing new boolean
`loadContext` flags in @EnabledIf and @DisabledIf. By default these
flags are set to false which means that the user's test application
context will not be loaded to evaluate the expression. On the contrary,
a dummy application context will be loaded instead, and expressions
will be evaluated against that dummy context. Consequently, if the user
wishes to interact with properties from the Spring Environment or with
beans from the test application context, the `loadContext` must be
explicitly set to true.
In addition, expressions which evaluate to a String must now evaluate
to exactly "true" or "false" (ignoring case and surrounding whitespace).
Issue: SPR-14649
This commit further refines 240f254 to also support java.util.Optional
for synchronized cache access (i.e. when the `sync` attribute on
`@Cacheable` is set to `true`).
Issue: SPR-14853
This commit makes sure that the `unregister` order of registered
application contexts has no incidence on the removal of the LiveBeansView
MBean.
Rather than using the last application context's name to compute the
identity of the MBean to remove, the identity is stored when the MBean is
created.
This commit also adds missing tests.
Issue: SPR-14848
This commit introduces a couple of changes to BodyInserters:
- Refactored writeWithMessageWriters into BiFunction
- BodyInserters.fromResource now uses ResourceMessagewriter from context
- BodyInserters.fromServerSentEvents now uses SseHttpMessageWriter from context
Reactor recently added the `ScriptedSubscriber` in its new
`reactor-addons` module. This `Subscriber` revissits the previous
`TestSubscriber` with many improvements, including:
* scripting each expectation
* builder API that guides you until the final verification step
* virtual time support
This commit refactor all existing tests to use this new
infrastructure and removed the `TestSubscriber` implementation.
Issue: SPR-14800
This commit improves NoSuchBeanDefinitionException to expose a full
ResolvableType rather than a raw class if a lookup by type failed. This
allows to know more about the underlying type and is typically useful
when a collection or map is required as the relevant generic type is the
actual bean that wasn't found.
Issue: SPR-14831
At present Tomcat expects a WriteListener to be registered immediately
on the initial thread so for the time being this commit ensures the
WriteListener is registered unconditionally for every request.
Issue: SPR-14772, SPR-14803
This commit removes factory methods for `RequestMappingHandlerMapping`
and `RequestMappingHandlerAdapter` from `WebReactiveConfigurer`.
`WebReactiveConfigurer` should promote only common customizations;
those factory methods should be overridden when extending
`WebReactiveConfigurationSupport`, in advanced configuration scenarios.
This commit replaces the lazy URI and headers initialization in the
reactive ServerHttpRequest in favor of eager initialization at
construction time. Both the URI and headers are nearly guaranteed to
be accessed for every request (URI for application path, headers for
"Origin" header).
Query params are still lazily parsed but parsing is idemptotent and
in the unlikely case of concurrent access (it's the framework that
typically accesses query params) it maybe parsed twice but should
be side effect free still.
Cookies are also parsed lazily and since we delegate to the "native"
request, it depends on the underlying runtime whether synchronization
is needed. This commit adds synchronization for the HttpServletRequest.
At present RxNetty, Reactor, and Undertow implementations provide
thread-safe access to cookies.
This commit introduces support for running multiple HttpHandler's under
distinct context paths which effectively allows running multiple
applications on the same server. ContextPathIntegrationTests contains
an example of two applications with different context paths.
In order to support this the HttpHandler adapters for all supported
runtimes now have a common base class HttpHandlerAdapterSupport
which has two constructor choices -- one with a single HttpHandler and
another with a Map<String, HttpHandler>.
Note that in addition to the contextPath under which an HttpHandler is
configured there may also be a "native" contextPath under which the
native runtime adapter is configured (e.g. Servlet containers). In such
cases the contextPath is a combination of the native contextPath and
the contextPath assigned to the HttpHandler. See for example
HttpHandlerAdapterSupportTests.
Issue: SPR-14726
This commit adds a bodyToMono and bodyToFlux convenience method to
ClientResponse/ServerRequest, similar to the body(Publisher) method that
is on ClientRequest/ServerResponse.
This commit introduces the following changes to web.reactive.function:
- Added RouterFunction.andRoute(), a combination of RouterFunction.and()
with RouterFunctions.route()
- ServerRequest.pathVariable() returns String instead of
Optional<String>. An exception is thrown if the variable is not present.
- Added HandlerFilterFunction.andThen and HandlerFilterFunction.apply()
This commit removes the usage of Reactor adapters (about to
be moved from Reactor Core to a new Reactor Adapter module).
Instead, RxReactiveStreams is now used for adapting RxJava
1 and Flowable methods are used for RxJava 2.
Issue: SPR-14824
This commit changes web.reactive.function to reflect the introduction of
the new WebClient. Changes include:
- Request -> ServerRequest
- Response -> ServerResponse
- FilterFunction -> HandlerFilterFunction
- StrategiesSupplier -> HandlerStrategies
This commit refactors the web client to be more similar to
web.reactive.function. Changes include:
- Refactor ClientWebRequest to immutable ClientRequest with builder and
support for BodyInserters.
- Introduce ClientResponse which exposes headers, status, and support
for reading from the body with BodyExtractors.
- Removed ResponseErrorHandler, in favor of having a ClientResponse
with "error" status code (i.e. 4xx or 5xx). Also removed
WebClientException and subclasses.
- Refactored WebClientConfig to WebClientStrategies.
- Refactored ClientHttpRequestInterceptor to ExchangeFilterFunction.
- Removed ClientWebRequestPostProcessor in favor of
ExchangeFilterFunction, which allows for asynchronous execution.
Issue: SPR-14827
This commit moves the web.reactive.function.[BodyInserter|BodyExtractor]
to http.codec, so that they can be used from the client as well.
Furthermore, it parameterized both inserter and extractor over
ReactiveHttpOutputMessage and ReactiveHttpInputMessage respectively, so
that they can be limited to only be used on the client or server.
Typically the Mono<Void> from the HttpHandler also reflects the
completion of the request and response body processors and at that
point invoking AsyncContext#complete() from HandlerResultSubscriber
should be sufficient.
This commit explicitly propagates the AsyncListener.onComplete event
to the request and response body processors for added safety.
Technically as mentioned those processors should have completed but
depending on how the controller is written there is a possibility
the body processors may not have completed.
Issue: SPR-14772
ServerWebExchange now has a getPrincipal method and along with that a
ServerWebExchangeDecorator that can be used to wrap the exchange in
order to return the authenticated user.
Issue: SPR-14680
The documentation mentions various NativeJdbcExtractors that no longer
exist. To be specific CommonsDbcpNativeJdbcExtractor and
XAPoolNativeJdbcExtractor no longer exist.
This commit includes the following changes:
* remove CommonsDbcpNativeJdbcExtractor references from Asciidoctor
* remove CommonsDbcpNativeJdbcExtractor references from Javadoc
* remove XAPoolNativeJdbcExtractor references from Asciidoctor
Issue: SPR-14810
Closes gh-1205
String with version 5 the name of Java Platform, Enterprise Edition
changed from J2EE to Java EE. However a lot of the documentation still
uses the term J2EE.
This commit includes the following changes:
* replace J2EE with Java EE where appropriate
This is not a blind search and replace. The following occurrences
remain unchanged:
* references to old J2EE releases, most notably 1.3 and 1.4.
* references to "Expert One-On-One J2EE Design and Development"
* references to "Core J2EE patterns"
* XML namespaces
* package names
Issue: SPR-14811
See gh-1206
This commit improves the existing web reactive configuration
infrastructure with the following changes:
* renamed `WebReactiveConfiguration` to
`WebReactiveConfigurationSupport` and is is no longer a Configuration
class
* created the `WebReactiveConfigurer` interface; Configuration classes
implementing it will augment the web reactive configuration support
* created the `DelegatingWebReactiveConfiguration` and
`WebReactiveConfigurerComposite` to effectively tie those custom-defined
configurers to the main configuration support
* created the `@EnableWebReactive` to active that support in
configuration classes
Issue: SPR-14754
Now that OracleLobHandler has finally been removed it should also be
removed from the documentation.
This commit includes the following changes:
* remove OracleLobHandler references from Javadoc
* remove OracleLobHandler references from Asciidoctor
Issue: SPR-14809
Closes gh-1204
Problem:
The following exception is observed on an async timeout:
"java.lang.IllegalStateException: It is invalid to call
isReady() when the response has not been put into non-blocking mode"
Current Implementation:
The async operation events sent by the web container are not propagated
to the internal implementation. When timeout/error happens and if the
application does not complete the async operation, the web container
will complete it. At that point if the application tries to read/write,
the operation will fail with an exception (above) that there is not
async operation started.
Proposed Solution:
On async timeout or error, make calls to:
- AbstractRequestBodyPublisher.onError,
- AbstractResponseBodyProcessor.onError,
- AbstractResponseBodyFlushProcessor.onError
As a result of these calls the async operation will be completed and no
more invocations of read/write will be made.
This commit simplifies the logic for applying beforeCommit actions
replacing the use of chained Mono.then calls with a single
Flux.concat.
Also renamed writeStatusCode, writeHeaders, and writeCookies to
applyStatusCode, applyHeaders, and applyCookies respectively to
better reflect we're simply setting them on the underlying response
(not necessarily written yet).
Before this change the getHttpEntityType method in
HttpEntityMethodProcessor raised an ISE if the generic type cannot be
detected. That made sense for resolving a controller method argument
where the target body type is crucial. However for a return value
the generic type should not be required since we either have an
actual body or no body at all in which case it doesn't even matter.
This change relaxes the checks and defaults to Object.class for the
ResponseEntity generic type on the return value side.
Issue: SPR-14799
Prior to this commit, the redirectedUrl() and forwardedUrl() methods in
MockMvcResultMatchers supported fully constructed URLs and URLs
containing Ant-style path patterns. However, URI templates were not
supported for these result matchers even though the request path can be
built using URL templates -- for example, via the get() and post()
methods in MockMvcRequestBuilders.
This commit addresses this shortcoming by allowing users to supply a
URL template instead of a fully constructed URL to redirectedUrl() and
forwardedUrl(). To populate the URL template, template variables may be
supplied to redirectedUrl() and forwardedUrl() as var-args.
Issue: SPR-14790
Commit e65a1a4372 introduced support in PrintingResultHandler for only
printing the request or response body in the Spring MVC Test framework
if the content type is known to be text-based (e.g., plain text, HTML,
XHTML, XML, JSON, etc.). For unknown content types the body is assumed
to be text-based and is therefore always printed. The latter behavior,
however, is undesirable since the content may in fact not be text-based.
This commit addresses this issue by making the printing of the request
or response body an opt-in feature. Specifically, if a character
encoding has been set, the request or response body will be printed by
the PrintingResultHandler. Note, however, that the character encoding
is set to ISO-8859-1 in MockHttpServletResponse by default.
In addition, MockHttpServletRequest's getContentAsString() method now
throws an IllegalStateException if the character encoding has not been
set.
Issue: SPR-14776
This commit replaces direct use of Validator and ConversionService in
the reactive @RequestMapping infrustructure in favor of using the
BindingContext.
Issue: SPR-14541
This commit adds a BindingContext to be used in spring-web-reactive
@RequestMapping infrastructure (comparable to WebDataBinderFactory in
spring-web-mvc) for access to the default model, data binding,
validation, and type conversion purposes.
Issue: SPR-14541
Prior to this commit, PrintingResultHandler always printed the request
or response body regardless of its content type. For binary content,
however, the output was unreadable and therefore useless.
This commit addresses this issue by only printing the request or
response body if it is "printable" (i.e., if its content type is known
to be text-based such as plain text, HTML, XHTML, XML, JSON, etc.). If
the content type is unknown (e.g., unspecified for the HTTP request in
the test), it is assumed that the body is printable.
Issue: SPR-14776
Prior to this commit, `ResourceTransformer` implementations would
resolve internal links to other resources: both relative and absolute
request paths.
For relative request paths, those transformers would call
`ResourceTransformerSupport.resolveUrlPath` with the resource path,
as provided in the original file. This can cause problems when a
`CachingResourceResolver` is configured in the resolver chain, because
this resolver is caching resources, deriving the cache key from the
given resource path — this can cause collisions for cases like this:
resources/
|--foo/
| |--foo.css (imports style.css)
| |--style.css
|--bar/
| |--bar.css (imports style.css)
| |--style.css
The first "style.css" resolved resource is then cached and will be given
to any request asking for "style.css".
To avoid those issues, this commit improves the `ResourceTransformer`
implementations to calculate the absolute request path before asking the
chain to resolve the resource URL, thus avoiding duplications.
The resource chain will be then asked to resolve "/foo/style/css" or
"/bar/style.css".
Issue: SPR-14597
This is a port of Spring MVC CORS support for Spring Web Reactive:
- CORS classes keep the same name but are in the
web.cors.reactive package
- CorsConfiguration is reused because not tied to Servlet API
- CORS HandlerMapping integration is done at
AbstractHandlerMapping level
- AbstractUrlHandlerMapping and AbstractHandlerMethodMapping
have been slightly modified to call
AbstractHandlerMapping#processCorsRequest()
- Both global CORS configuration + @CrossOrigin support have
been implemented
Issue: SPR-14545
This commit configures a default SslContext if none has been provided.
This also enforces separate Netty bootstrap instances for cleartext and
TLS exchanges.
Issue: SPR-14744
Prior to this commit, the `HttpEntityMethodProcessor` would avoid
writing ETag/Last-Modified response headers before calling
`ServletWebRequest` to process conditional requests. This was done to
avoid duplicate response header values due to headers being already
written to the underlying servlet response.
This is still necessary for GET/HEAD requests, since this is properly
handled by `ServletWebRequest` for those cases. But
`HttpEntityMethodProcessor` should not make that decision for
PUT/PATCH/POST responses since developers are adding response headers on
purpose and should be in control of the situation — whereas
`ServletWebRequest` does not write those headers in those cases.
Issue: SPR-14767
Prior to this commit, the PrintingResultHandler used by the various
print() and log() methods in Spring MVC Test printed the response body
but not the request body.
Since request bodies are sometimes generated programmatically, however,
it can be beneficial to have the dynamically generated request body
logged as well.
This commit therefore prints the request body in PrintingResultHandler
by delegating to the recently introduced getContentAsString() method in
MockHttpServletRequest.
Issue: SPR-14717
In order to improve debugging and logging within test suites, this
commit introduces getContentAsByteArray() and getContentAsString()
methods in MockHttpServletRequest, analogous to the existing methods in
MockHttpServletResponse.
Issue: SPR-14717
This commit adds a new chain-based, interception contract to be used
with `WebClient`. This is the HTTP client equivalent of the `WebFilter`
contract already implemented in web reactive server.
A `ClientHttpRequestInterceptor` implementation can transform the
outgoing HTTP request (method, URI or headers) before delegating it to
the next interceptor in the chain, or bypass the request processing
altogether and return a (cached) HTTP response.
Issue: SPR-14502
This commit handles range requests in `ResourceWebHandler`, using the
`ResourceHttpMessageWriter` configured within the handler.
This `WebHandler` will add a `HTTP_RANGE_REQUEST_HINT` writer hint
containing all the HTTP Range information of the request.
Issue: SPR-14664
This new `HttpMessageWriter` leverages the `ResourceRegionEncoder` to
write `ResourceRegion` to HTTP responses, thus supporting HTTP Range
requests.
Whenever possible, this message writer uses the zero copy support for
single range requests.
This `HttpMessageWriter` is never used directly, but is used as a
delegate by the `ResourceHttpMessageWriter`. When provided with the
`BOUNDARY_STRING_HINT`, the `ResourceRegionHttpMessageWriter`
adapts its behavior in order to write a single/multiple byte ranges.
Issue: SPR-14664
This commit adds the necessary infrastructure for the support of HTTP
Range requests. The new `ResourceRegionEncoder` can write
`ResourceRegion` objects as streams of bytes.
The `ResourceRegionEncoder` relies on an encoding hint
`BOUNDARY_STRING_HINT`. If present, the encoder infers that multiple
`ResourceRegion`s should be encoded and that the provided boundary
String should be used to separate ranges by mime boundaries.
If that hint is absent, only a single resource region is encoded.
Issue: SPR-14664
This commit makes it possible, in addition to provide hints, to
perform additional operations with the request and the response
at ServerHttpMessageReader/Writer level.
AbstractServerHttpMessageReader/Writer now provide
convenient beforeRead/beforeWrite abstract methods for such need.
Issue: SPR-14557
Resetting the connection first before invoking a failure callback on
the application handler ensures that any checks to isConnected will
return false.
Issue: SPR-14721
This commit overrides the `checkResource` implementation in
`ScriptTemplateView` in order to check if the template file resource is
available and if the resolver can then proceed with rendering the
template.
Issue: SPR-14729
Cherry-picked from: 66b370e10
In order to simplify configuration for use cases involving @Bean where
only a bean name or aliases are supplied as an attribute, this commit
introduces a new 'value' attribute that is an @AliasFor 'name' in @Bean.
Issue: SPR-14728
Move the AbstractServletHttpHandlerAdapterInitializer together with
the other two base classes in spring-web-reactive. Since the
interface is in the web package, this avoids a package cycle.
Also add a mention in the reference.
Issue: SPR-14713
This commit introduces three new WebApplicationInitializers for use with
Spring Web Reactive:
- The AbstractServletHttpHandlerAdapterInitializer registers a
ServletHttpHandlerAdapter that wraps a user-provided HttpHandler.
- The AbstractDispatcherHandlerInitializer registers a
ServletHttpHandlerAdapter that wraps a DispatcherHandler (or any
WebHandler). The handler is provided with an application context.
- The AbstractAnnotationConfigDispatcherHandlerInitializer is a
subclass of the above, creating an
AnnotationConfigApplicationContext based no provided @Configuration
classes.
Issue: SPR-14713
This commit extracts the response body insertion logic into a separate
strategy interface: BodyPopulator. Standard populators can be found in
BodyPopulators.
This commit refactors the Router into a RoutingFunctions class, by:
- Renaming the class :)
- Moving all Configuration logic into a separate, top-level
Configuration class with mutable builder.
Since appcache manifests can have various file extensions, developers
should register the (file extension, media type) mapping in their Spring
MVC / Reactive Web configuration.
This commit adds javadoc on both `AppCacheManifestTransformer` variants
to explain how to do that.
Issue: SPR-14510
Improve RootBeanDefinition to specify an AnnotatedElement that holds
qualifier information. When such element is present, any qualifier that
it defines will be used to find a matching candidate.
Issue: SPR-14725
Rather than setting the status to 503 directly from the timeout
interceptor which no longer seems to work reliably with Servlet
containers like Jetty even performing an additional ERROR dispatch back
to the original URL, we know rather set the DeferredResult to an
AsyncTimeoutException, which results in a dispatch and standard
handling within Spring MVC. This should be a more reliable way of
dealing with timeouts.
Issue: SPR-14669
Added readableChannel() to Resource, which returns a
java.nio.ReadableByteChannel. The default implementation uses
Channels.newChannel() to create a channel based on what is returned from
getInputStream(). Subclasses have more effecient, file-based
implementations.
Issue: SPR-14698
Fixed bug where the returned Flux from DataBufferUtils.read() would be
completed prematurely if the channel was not ready to read, but did
not reach the end of the file either.
This commit changes the default file extension configured with
`AppCacheManifestTranformer`. This ResourceTransformer was previously
considering `.manifest` files by default, but this has been changed in
the official spec to `appcache`, in order not to clash with Microsoft's
unregistered application/manifest type.
Issue: SPR-14687
`ResolvedResource` is a rather generic name - changing the extended
interface to something more meaningful: `HttpResource`.
For now, implementations are linked with the resource handling chain,
but this aspect has been removed from the interface documentation.
Issue: SPR-14264
Prior to this commit, FreeMarkerView used the system default charset to
render. This commit switches this by defaulting to UTF-8, if no charset
is specified in the content type.
- Add contentType parameter to AbstractView.renderInternal, used to
determine the charset contained therein
- Adds a defaultCharset property to AbstractView and
ViewResolverSupport.
Changed View's render method from taking a HandlerResult to taking a
Map<String, ?>, in order to facilitate scenarios where a HandlerResult
is not available (i.e. web.reactive.function).
Two changes to web.reactive.function:
- Changed Response.stream method to allow for specific Publisher types
to be returned in Response.
- Router now stores HttpMessageReader|Writer retrieved from
Configuration in the attributes as supplier, not as stream, to allow
for multiple reads.
Prior to this commit, the resource handling chain and its
`ResourceResolvers` would use specific `Resource` implementations in
order to add resource metadata to the HTTP response. For example,
`VersionedResource` and `EncodedResource` are both adding specific HTTP
response headers.
This commit aims at making this mechanism more stable and reusable,
since the previous implementation would fail in case a resolved resource
would be both a `VersionedResource` wrapping a `EncodedResource` (or the
other way arount). Only one of the specific implementations would
contribute its metadata since the code supporting that in
`ResourceHttpRequestHandler` would only check for `instanceof` tests,
whereas those implementations are acutally delegating calls to
the wrapped resource.
Now both `VersionedResource` and `EncodedResource` have been replaced by
specific implementations of `ResolvedResource`, which directly provides
those HTTP response headers as part of `getResponseHeaders()`.
This commit applies the same changes for the web reactive
implementations and its `ResourceWebHandler`.
Issue: SPR-14264
Since SPR-14522, the web reactive framework supports checkNotModified
features. This commit aligns the existing MVC infrastructure with
web reactive's behavior.
Because of the new Servlet 3.0 baseline, some constraints
aren't relevant anymore and duplicate code has been removed in
`HttpEntityMethodProcessor`.
Issue: SPR-14659
A straight-forward port of the resource handling support in
spring-webmvc to spring-web-reactive. Primarily adapting contracts and
implementations to use the reactive request and response and the
reactive ResourceHttpMessageWriter.
Issue: SPR-14521
Whereas the existing TestContextConcurrencyTests verify support for
concurrency in the TestContextManager and TestContext, this commit
introduces SpringJUnit4ConcurrencyTests that verify support for
concurrent test execution in Spring's JUnit 4 support, namely in the
SpringRunner, SpringClassRule, and SpringMethodRule.
The tests executed by this new test class come from a hand-picked
collection of test classes within the test suite that is intended to
cover most categories of tests that are currently supported by the
TestContext Framework on JUnit 4.
Note, however, that the chosen test classes intentionally do not
include any classes that fall under the following categories.
- tests that make use of Spring's @DirtiesContext support
- tests that make use of JUnit 4's @FixMethodOrder support
- tests that commit changes to the state of a shared in-memory database
Issue: SPR-5863
This commit improves the exception message thrown when a test's
ApplicationContext is no longer active by explaining that the cause
may be due to parallel test execution.
Issue: SPR-5863
As per specification "The Subscription MUST allow the Subscriber to
call Subscription.request synchronously from within onNext or
onSubscribe". With the current implementation if Subscription.request
is called more than once when Subscriber.onSubscribe ISE will be
thrown - java.lang.IllegalStateException: DEMAND.
With this fix the implementation will not throw ISE and will allow
many invocations of Subscription.request when
Subscriber.onSubscribe.
This commit fixes `ResponseEntityResultHandler` so that it only tries to
call `writeBody` if the `ResponseEntity` is not null. In case the
response entity body is null, the response is flushed right away and the
request is signaled as handled.
Issue: SPR-14663
Prior to this commit, executing tests concurrently in the TestContext
Framework (TCF) was unsupported and typically lead to unpredictable
results.
This commit addresses this core issue by supporting concurrent
execution in the TestContextManager and the DefaultTestContext.
Specifically, the TestContextManager now uses ThreadLocal storage for
the current TestContext, thereby ensuring that any registered
TestExecutionListeners and the TestContextManager itself operate on a
TestContext specific to the current thread.
In order to avoid repeatedly incurring the costs of the overhead of the
TCF bootstrapping process, the original TestContext built by the
TestContextBootstrapper is used as a template which is then passed to
the copy constructor of the concrete implementation of the TestContext
to create the context for the current thread. DefaultTestContext now
implements such a copy constructor, and all concrete implementations of
TestContext are encouraged to do the same.
If the TestContext built by the TestContextBootstrapper does not
provide a copy constructor, thread-safety and support for concurrency
are left completely to the implementation of the concrete TestContext.
Note, however, that this commit does not address any thread-safety or
concurrency issues in the ContextLoader SPI or its implementations.
Issue: SPR-5863
This commit inlines the basic implementation of AttributeAccessorSupport
and converts the LinkedHashMap to a ConcurrentHashMap.
In addition, attributes are now included in toString().
Issue: SPR-5863
This change puts the MockHttpServerRequest/Response under
org.springframework.mock.http.server.reactive.test which
mirrors the arrangement we have with the Servlet mock equivalents
and sets up the addition of MockHttpServerRequest/Response in
spring-test.
Issue: SPR-14421
This commit documents the regexp support in `AntPathMatcher` when
matching for URL patterns. This support is also mentioned in places
where developers can register patterns for ViewControllers or resource
handlers.
Issue: SPR-14652
This commit avoid merging automatically the SSE stream with
Flux.never(). Since browsers automatically reconnect when
the HTTP connection is closed, it is now the user responsability
to optionally perform a concatWith(Flux.never()) on streams that
complete in order to avoid receiving the data multiple times on
client side.
The behavior with hot streams that never complete does not change.
Issue: SPR-14578
This commit adds a "spring-context-indexer" module that can be added to
any project in order to generate an index of candidate components defined
in the project.
`CandidateComponentsIndexer` is a standard annotation processor that
looks for source files with target annotations (typically `@Component`)
and references them in a `META-INF/spring.components` generated file.
Each entry in the index is the fully qualified name of a candidate
component and the comma-separated list of stereotypes that apply to that
candidate. A typical example of a stereotype is `@Component`. If a
project has a `com.example.FooService` annotated with `@Component` the
following `META-INF/spring.components` file is generated at compile time:
```
com.example.FooService=org.springframework.stereotype.Component
```
A new `@Indexed` annotation can be added on any annotation to instructs
the scanner to include a source file that contains that annotation. For
instance, `@Component` is meta-annotated with `@Indexed` now and adding
`@Indexed` to more annotation types will transparently improve the index
with additional information. This also works for interaces or parent
classes: adding `@Indexed` on a `Repository` base interface means that
the indexed can be queried for its implementation by using the fully
qualified name of the `Repository` interface.
The indexer also adds any class or interface that has a type-level
annotation from the `javax` package. This includes obviously JPA
(`@Entity` and related) but also CDI (`@Named`, `@ManagedBean`) and
servlet annotations (i.e. `@WebFilter`). These are meant to handle
cases where a component needs to identify candidates and use classpath
scanning currently.
If a `package-info.java` file exists, the package is registered using
a "package-info" stereotype.
Such files can later be reused by the `ApplicationContext` to avoid
using component scan. A global `CandidateComponentsIndex` can be easily
loaded from the current classpath using `CandidateComponentsIndexLoader`.
The core framework uses such infrastructure in two areas: to retrieve
the candidate `@Component`s and to build a default `PersistenceUnitInfo`.
Rather than scanning the classpath and using ASM to identify candidates,
the index is used if present.
As long as the include filters refer to an annotation that is directly
annotated with `@Indexed` or an assignable type that is directly
annotated with `@Indexed`, the index can be used since a dedicated entry
wil be present for that type. If any other unsupported include filter is
specified, we fallback on classpath scanning.
In case the index is incomplete or cannot be used, The
`spring.index.ignore` system property can be set to `true` or,
alternatively, in a "spring.properties" at the root of the classpath.
Issue: SPR-11890
This commit introduces a new, functional web programming model in the
org.springframework.web.reactive.function package. The key types
are:
- Request and Response are new Java 8-DSLs for access to the HTTP
request and response
- HandlerFunction represents a function to handle a request to a
response
- RoutingFunction maps a request to a HandlerFunction
- FilterFunction filters a routing as defined by a RoutingFunction
- RequestPredicate is used by Router to create RoutingFunctions
- RequestPredicates offers common RequestPredicate instances
- Renamed SseEvent to ServerSentEvent to make the name less redundant.
- ServerSentEvent is now immutable, having a builder to create new instances.
- Realigned the class properties to more closely match the events
described in the spec, so that `reconnectTime` becomes `retry`, and
`name` becomes `event`.
This commit introduces integration tests that verify the expected
behavior for @Nested tests in conjunction with the SpringExtension for
JUnit Jupiter, including automatic application of
TestExecutionListeners to the enclosing test instance of a @Nested
test instance.
Issue: SPR-14150
Due to restrictions imposed by JUnit 4, the SpringClassRule must be
declared as a public static field, which makes it impossible to be
declared directly within a nested (i.e., inner) test class.
This commit demonstrates a work-around that makes it possible to use
the SpringClassRule and SpringMethodRule in a nested (i.e., inner) test
class when using a custom JUnit 4 runner such as the
HierarchicalContextRunner from Stefan Bechtold.
The trick is to have inner test classes extend a class that properly
declares the SpringClassRule and SpringMethodRule. The
SpringRuleConfigurer in this commit serves as an example.
Note, however, that each such nested test class must declare its own
@ContextConfiguration. Furthermore, TestExecutionListeners in the
Spring TestContext Framework are not applied to the enclosing instance
of such an inner test class, meaning that @Autowired fields in the
enclosing instance will not be injected, etc.
Issue: SPR-14150
A little terminiology first:
* merge.from - a project that contains source that will be merged
into merge.into
* merge.into - a project that contains source code that will have
code from merge.from merged into it.
Previously a module that dependended on merge.into would not see
the merge.from module as a transitive dependency. This worked fine
from a Gradle build because all the code from merge.from is merged
into the merge.into jar. However, in an IDE it did not work because
the IDE does not assemble a jar.
This fix ensures that merge.from modules are automatically added
to the classpath of any module relying on the merge.into project.
Fixes SPR-14650
This commit picks up where SPR-14614 left off by introducing a new
@EnabledIf annotation to serve as a logical companion to @DisabledIf.
In addition, this commit extracts common logic from DisabledIfCondition
into a new AbstractExpressionEvaluatingCondition base class which the
new EnabledIfCondition also extends.
An @EnabledOnMac annotation is also included in the Javadoc as well as
in the test suite to demonstrate support for custom composed annotations.
Issue: SPR-14644
This commit updates the instructions on getting started with
Spring Web Reactive and also updates constructors and setters to
streamline the getting started procedure.
Issue: SPR-14640
This is a follow-up on commit 3b95e0b relaxing the expectation that a
ServletContext is present. Instead we check defensively and fall back
on PathExtensionContentNegotiationStrategy which can use JAF.
Issue: SPR-14577
Create an explicit heartbeat task with an experiration flag so that
it can be cancelled reliably vs relying on the ScheduledFutureTask
cancel method which may return true even if the task is already
running.
Issue: SPR-14356
Prior to this commit, exceptions thrown by the
`HandlerMethodArgumentResolver` would be wrapped into
`IllegalStateException`s.
This commit makes sure that a DEBUG log is written with the relevant
information and that the root cause is not wrapped into another
exception, so that the appropriate `ExceptionHandler` can be used to
deal with this error.
Issue: SPR-14618
This commit adds Smile and CBOR Jackson HttpMessageConverters
and make it possible to create Smile and CBOR ObjectMapper via
Jackson2ObjectMapperBuilder, which now allows to specify any
custom JsonFactory.
Like with JSON and XML Jackson support, the relevant
HttpMessageConverters are automaticially configurered by
Spring MVC WebMvcConfigurationSupport if jackson-dataformat-smile
or jackson-dataformat-cbor dependencies are found in the classpath.
Issue: SPR-14435
Prior to this commit, the DisabledIfCondition did not trim whitespace
from expressions configured via @DisabledIf. Consequently, results such
as " true " would evaluate to "false".
This commit fixes this problem by trimming all expressions configured
via @DisabledIf.
Issue: SPR-14614
This commit introduces tests for DisabledIfCondition that verify actual
condition evaluation results and exception handling; whereas, the
existing tests in DisabledIfTestCase only test the "happy paths" and
standard cases.
Issue: SPR-14614
- Extracted stand-alone DisabledIfCondition from the SpringExtension
so that the condition is only evaluated when necessary.
- Simplified implementation of DisabledIfCondition.
- Overhauled and extended logging in DisabledIfCondition.
- DisabledIfCondition now throws an IllegalStateException if @DisabledIf
is not present on the test element or if the expression does not
evaluate to a String or Boolean.
- Each generated ConditionEvaluationResult now includes the actual
expression in the default reason.
- @DisabledIf is now auto-configured to be evaluated by the
DisabledIfCondition since it is now meta-annotated with
@ExtendWith(DisabledIfCondition.class)
- Overhauled documentation for @DisabledIf and provided standard
examples as well as an @DisabledOnMac annotation to demonstrate
support for custom composed annotations.
Issue: SPR-14614
This commit introduces @DisabledIf annotation that takes SpEL as a
condition. The condition is evaluated at run time whether to disable
JUnit 5 (Jupiter) test method/class.
Issue: SPR-14614
When using a `RestTemplate` instance within a Spring MVC application,
client exceptions may propagate in the MVC stack and can be wrongly
mapped by server `ExceptionHandlers`, leading to a wrong HTTP response
sent to the MVC client.
The `RestTemplate` instance uses `HttpMessageConverter` to decode
the remote service responses; and when those fail decoding an HTTP
response, they can throw an `HttpMessageNotReadableException`. That
exception then bubbles up through the `HttpMessageConverterExtractor`,
`RestTemplate` and the whole MVC stack, later mapped to HTTP 400
responses, since those exceptions can also be throws by the server stack
when the incoming requests can't be deserialized.
This commit wraps all `IOException` and `HttpMessageNotReadableException`
instances thrown by the extractor into `RestClientException`` instances.
It's now easier to consistently handle client exceptions and avoid such
edge cases.
Issue: SPR-13592
This change adds support for a target type in JsonPath assertions in
Spring MVC Test.
The existing assertValue(String expression, Object expectedValue)
transparently falls back on using an alternative JsonPath API that
allows specifying the target type to coerce to.
There is also a new overloaded method
assertValue(String expression, Matcher<T> matcher, Class<T> targetType)
for use with Hamcrest matchers where the target type can be specified.
Issue: SPR-14498
HttpEntityMethodProcessor should not throw IllegalArgumentExceptions for
invalid If-None-Match headers.
For those cases, this commit makes sure that both
`HttpEntityMethodProcessor` and `ServletWebRequest` have a consistent
behavior and stop processing the request as conditional and leave the
handler handle it.
Issue: SPR-14559
This commit sorts `ClientHttpRequestInterceptor`s when those are set in
`InterceptingHttpAccessor` (which `RestTemplate` extends from).
Interceptors can now be annotated with `@Order` or implements `Ordered`
to reflect their order of execution for each request.
Issue: SPR-13971
This commit adds support for HTTP header field parameters encoding, as
described in RFC5987.
Note that the default implementation still relies on US-ASCII encoding,
as the latest rfc7230 Section 3.2.4 says that:
> Newly defined header fields SHOULD limit their field values to
US-ASCII octets
Issue: SPR-14547
Prior to this commit, extracting an HTTP response with an empty body
and no Content-Type header using the WebClient would:
* trigger the use of the Jackson2JsonDecoder
* throw a NoSuchElementException because of the use of `Flux.single()`
This commit changes this behavior to `Flux.singleOrEmpty()` to avoid
throwing exceptions for empty Flux instances.
Issue: SPR-14582
Since the upgrade to Gradle 3, our Bamboo build is failing because it
can't find test reports "at the usual location".
This commit restores the location that Gradle 2 was using until we
upgrade to a version of Bamboo that supports it.
Issue: SPR-14569
Previously the IDE (STS) was resolving a different reactor-core
version (3.0.0.BUILD-SNAPSHOT) than the build (3.0.0.RELEASE). This
discrepancy was due to the fact that reactor-netty now brings in
reactor-core 3.0.0.RELEASE. Gradle's version conflict resolution is to use
the latest version. However, the optional dependency on reactor-core
3.0.0.BUILD-SNAPSHOT was making the build path of the IDE use the SNAPSHOT.
This fix leverages a resolutionStrategy to ensure a consistent version of
reactor-core is used throughout the entire project. It also bumps up the
reactor-core version to 3.0.0.RELEASE to be consistent with reactor-netty.
Care is taken to only change 3.x vesion since 2.x is still used within
the codebase.
Since we have a dedicated section regarding Ehcache that is only
applicable to Ehcache 2.x, this commit clarifies that Ehcache 3.x is
JSR-107 compliant and the JCache support should be used with it
rather than attempting to configure the Ehcache 2.x support.
Commit 240f254 has introduced support for `java.util.Optional` in the
cache abstraction. If such type is present, the contained value is cached
if it is present.
This new feature slightly changed the semantic of `#result` that was
documented up till this commit as the "return value of the method
invocation". This is no longer true as `#result` for `Optional<T>`
refers to the `T` instance and not the `Optional` instance.
This commit clarifies both the javadoc and the documentation.
Issue: SPR-14587
Previously invoking HtmlUnitRequestBuilder merge caused the pathInfo of
the parent to be corrupted. This could additional invocations with the
same parent.
This fix ensures that the parent is no longer directly used. Instead,
we create a copy of the parent by merging the parent that was passed in
with the copy.
Fixes SPR-14584
reactor.test.TestSubscriber will not be part of Reactor Core
3.0.0 since it needs to be refactored to fit all the needs
expressed by the users. It is likely to be back later in one
of the Reactor Core 3.0.x releases.
This commit anticipate this removal by temporarily copying
TestSubscriber in spring-core test classes. As soon as
the new TestSubscriber will be available in Reactor Core,
Spring Framework reactive tests will use it again.
There is really no need for a result handler dedicated to a void
return value and it's actually problematic to have it.
Each result handler treats void as necessary. For an @ResponseBody
method it means an empty body. For view resolution it means no specific
value was returned and we should procede with selecting a default view
name. Having a dedicated void result handler can interfere with this
especially since view resolution needs to be last in order.
At the same time there are cases when no result handling is needed
and the response is fully handled within the HandlerAdapter. This is
the case with WebHandler and the SimpleHandlerAdapter. For that case
we simply return mono.then(aVoid -> Mono.empty()) which effectively
returns an empty Mono and no result handling follows. The
HandlerAdapter already says you can return no values at all if the
response is fully handled.
With the current state machine
- the implementation can hang after the last element when executing
on Jetty.
- in some cases there will be no flush after the last
Publisher<DataBuffer>.
AbstractResponseBodyProcessor.onError and
AbstractResponseBodyFlushProcessor.onError will be invoked when:
- The Publisher wants to signal with onError that there are failures.
Once onError is invoked the Subscription should be considered canceled.
- The internal implementation wants to signal with onError that there
are failures. In this use case the implementation should invoke
Subscription.cancel()
DataSourceUtils moved to main core.io.buffer package.
Consistently named Jackson2JsonDecoder/Encoder and Jaxb2XmlDecoder/Encoder.
Plenty of related polishing.
Hibernate 5.2's HibernateException extends PersistenceException, leading to a different constructor compiled into the bytecode, breaking compatibility with Hibernate 5.0 at runtime.
Issue: SPR-13827
xmlunit 2.1.0 is the latest release for xmlunit.
Most of the xmlunit functionality used within spring-framework
was done through the xmlunit 1.x helper class
`org.custommonkey.xmlunit.XMLAssert`.
As of xmlunit 2.0.0 most of the XML comparison methods are done
through hamcrest matchers exposed by the xmlunit-matchers
library. In some cases during the migration, the matchers
had to be customized with custom `NodeMatcher` or
`DifferenceEvaluator` instances in order to keep the assertions
correct (they were performed with xmlunit 1.x previously).
Issue: SPR-14043
This commit adds support for Google Protobuf 3.0.0 and make some changes
in the additional formats support:
* "com.googlecode.protobuf-java-format:protobuf-java-format" is no
longer required and its required version has been raised to 1.3+
(this lib adds support for JSON, XML, HTML formats)
* "com.google.protobuf:protobuf-java-util" is also now supported for
JSON format
Issue: SPR-13589
This commit changes the reactive flushing mechanism to use a newly
introduced writeAndFlushWith(Publisher<Publisher<DataBuffer>>) on
ReactiveHttpOutputMessage instead of using the FlushingDataBuffer.
Issue: https://github.com/spring-projects/spring-reactive/issues/125
This commit ensures that a valid port is given to the underlying Netty
client when no port is defined in the URL itself.
By default, port 80 is used by the Reactor Netty client.
Issue: SPR-14477
The `WebClient` has a new exception hierarchy:
* `WebClientException` is the root of all exceptions thrown by the
`WebClient`
* `WebClientResponseException` are all exceptions associated with
specific HTTP response status codes
* `WebClientErrorException` and `WebServerErrorException` are
respectively for 4xx and 5xx HTTP status codes
`ResponseExtractor` implementations are adapted to optionally throw
exceptions if it's impossible to extract the relevant parts of the
response (e.g. extracting the response body if the response is a 404).
This commit also introduces `ResponseErrorHandler`s that take care of
the whole exception mapping infrastructure. Since
`WebClientResponseException`s provide the status, headers and response
body, we also need a dedicated mechanism to extract information from the
response body at that level.
The `BodyExtractors` are responsible for extracting that information
from the exception, given they are provided with all the information
they need; in that case, message decoders are required.
To convey all this new information downstream, the `WebClient` now wraps
the message converters and response error handler instances into a
dedicated `WebClientConfig` object.
- Added Woodstox before Aalto in the spring-web build, so that Woodstox
is used as StAX implementation, and not the less featured Aalto.
- Hardcoded Aalto dependency in XmlEventDecoder, instead of relying on
the StAX XMLInputFactory.
Prior to this commit, a dynamic test in
FailingBeforeAndAfterMethodsSpringExtensionTestCase was failing but for
the wrong reason. Namely, the @Configuration class was private which
resulted in an IllegalStateException being thrown, when in fact
an AssertionFailedError was expected.
This commit addresses this by introducing an explicit check for an
AssertionFailedError.
Issue: SPR-4365
Prior to this commit, if multiple TestExecutionListener 'after' methods
threw an exception, only the first such exception was rethrown.
Subsequent exceptions were logged, but there was no way to access or
process them other than via the log file.
This commit addresses this shortcoming by making use of the support for
suppressed exceptions introduced in Java 7. Specifically, if multiple
TestExecutionListener 'after' methods throw an exception, the first
exception will be rethrown with subsequent exceptions suppressed in the
first one.
Issue: SPR-14459
Moved ResponseBodyProcessor creation from constructor to
writeWithInternal(), in preparation of supporting both
Publisher<DataBuffer> as well as Publisher<Publisher<DataBuffer>>.
In preparation of supporting both Publisher<DataBuffer> and
Publisher<Publisher<DataBuffer>> as response body, moved
RequestBodyPublisher and ResponseBodyProcessor into
ServletServerHttpRequest and ServletServerHttpResponse respectively.
This commit makes use of the new Supplier<String> variants of utility
methods in org.springframework.util.Assert within the spring-test
module.
Issue: SPR-14450
This commit makes use of the new Supplier<String> variants of utility
methods in org.springframework.util.Assert within the spring-core
module.
Issue: SPR-14450
Prior to this commit, utility methods in
org.springframework.util.Assert accepted String arguments for custom
error messages. Such Strings are evaluated (e.g., concatenated)
eagerly, and for performance reasons, it was therefore not always
possible to make use of these utility methods. Consequently, there are
several places in the code base that "inline" identical functionality
in order to lazily evaluate error message concatenation and avoid an
unnecessary performance penalty. This leads to verbose code like the
following.
if (!contextPath.startsWith("/")) {
throw new IllegalArgumentException("contextPath '" + contextPath +
"' must start with '/'.");
}
if (contextPath.endsWith("/")) {
throw new IllegalArgumentException("contextPath '" + contextPath +
"' must not end with '/'.");
}
This commit addresses this shortcoming by introducing Supplier<String>
variants of all utility methods in org.springframework.util.Assert that
allow custom error messages to be evaluated lazily via a lambda
expression that is only evaluated if the assertion fails. This results
in a simplification of the previous examples as follows.
Assert.isTrue(contextPath.startsWith("/"), () -> "contextPath '" +
contextPath + "' must start with '/'.");
Assert.isTrue(!contextPath.endsWith("/"), () -> "contextPath '" +
contextPath + "' must not end with '/'.");
Issue: SPR-14450
This commit introduces 'before' and 'after' test execution callbacks in
the Spring TestContext Framework. Specifically, this set of commits
introduces the following.
- beforeTestExecution() and afterTestExecution() callbacks in the
TestExecutionListener API
- beforeTestExecution() and afterTestExecution() callbacks in
TestContextManager
- RunBeforeTestExecutionCallbacks and RunAfterTestExecutionCallbacks
JUnit 4 statements that are used by the SpringJUnit4ClassRunner
- Documentation in the class-level Javadoc for SpringMethodRule stating
that before/after test execution callbacks cannot be supported with
JUnit 4 Rules
- Support for JUnit Jupiter's BeforeTestExecutionCallback and
AfterTestExecutionCallback extension APIs in the SpringExtension for
JUnit 5
- Support for before/after test execution callbacks in
AbstractTestNGSpringContextTests for TestNG
Issue: SPR-4365
This commit replaces the current helper methods in
RequestMappingIntegrationTests with generic helper methods to perform
HTTP GET and POST requests.
This results in more transparent code that shows the exact HTTP
inputs and outputs and is also more flexible to change for
variations in testing.
This commit adds the required infrastructure to build HTTP requests as
well as extracting relevant information from HTTP responses using the
RxJava 1.x API, where Observable and Single don't extend Publisher.
This commit refactors the `ClientHttpRequestFactory` into an
`ClientHttpConnector` abstraction, in order to reflect that
`ClientHttpRequest`s only "exist" once the client is connected
to the origin server.
This is why the HTTP client is now callback-based, containing all
interactions with the request within a
`Function<ClientHttpRequest,Mono<Void>>` that signals when it's done
writing to the request.
The `ClientHttpRequest` contract also adopts `setComplete()`
and promotes that method to the `ReactiveHttpOutputMessage` contract.
This commit also adapts all other APIs to that change and fixes a few
issues, including:
* use `HttpMessageConverter`s instead of `Encoders`/`Decoders`
* better handle type information about request content publishers
* support client cookies in HTTP requests
* temporarily remove the RxNetty client support
Reactor's `DependencyUtils` has been renamed to `Converters` and
all the `from` converter methods have been disambiguated to
`fromPublisher`, `toPublisher`.
This commit removes `GuavaCache` and support classes. Caffeine supersedes
the caching support in the Google Guava library with an actively maintained
Java 8+ version in standalone form.
As it is the only Guava feature Spring framework integrates with, this
commit removes effectively any reference to Guava.
Issue: SPR-13797
This commit adds support for handling an empty request body with both
HttpEntity where the body is not required and with @RequestBody where
the body is required depending on the annotation's required flag.
If the body is an explicit type (e.g. String, HttpEntity<String>) and
the body is required an exception is raised before the method is even
invoked or otherwise the body is passed in as null.
If the body is declared as an async type (e.g. Mono<String>,
HttpEntity<Mono<String>>) and is required, the error will flow through
the async type. If not required, the async type will be passed with no
values (i.e. empty).
A notable exception is rx.Single which can only have one value or one
error and cannot be empty. As a result currently the use of rx.Single
to represent the request body in any form effectively implies the body
is required.
Before this change decodeToMono always created a StringBuilder to
aggregate resulting in an "" (empty string) rather than an empty
Mono for an empty input stream.
Now we aggregate in the DataBuffer instead and then decode to String.
The RequestBodyArgumentResolver has been refactored to have a shared
base class and tests with the new HttpEntityMethodArgumentResolver.
An HttpEntity argument is not expected to have an async wrapper because
the request headers are available immediately. The body however can be
asynchronous, e.g. HttpEntity<Flux<String>>.
SPR-14055 introduced first-class support for the Java 8 Parameter API.
This commit therefore replaces the MethodParameterFactory with use of
the new SynthesizingMethodParameter.forParameter(Parameter) factory
method.
Issue: SPR-13575
This commit changes the AbstractResponseBodySubscriber into a
AbstractResponseBodyProcessor<DataBuffer, Void>, so that the processor
can be used as a return value for writeWith.
Additional, this commit no longer closes the response after an eror
occurred.
This fixes#59.
When the thread is writing to the response in
RECEIVED.onWritePossible(), the execution may stop because isReady()
returned false. In this case the buffer is partially written.
When there is partially written case:
1. The state will be changed from WRITING to RECEIVED
2. A check for "write possible" will be performed:
- If onWritePossible event has been already called by the web
container while in WRITING state then this check will trigger
RECEIVED.onWritePossible() because isReady() will be true and the
writing will continue.
- Otherwise the writing will be resumed when the web container sends
onWritePossible event.
This commit adds a test runtime dependency on log4j 2 for every project
and migrates all log4j.properties files to log4j2-test.xml files.
Issue: SPR-14431
This commit also removes the corresponding deprecated Servlet MVC variant and updates DispatcherServlet.properties to point to RequestMappingHandlerMapping/Adapter by default.
Issue: SPR-14129
This commit introduces initial support for JUnit Jupiter (i.e., the new
programming and extension models in JUnit 5) in the Spring TestContext
Framework.
Specifically, this commit introduces the following.
- SpringExtension: an implementation of multiple extension APIs from
JUnit Jupiter that provides full support for the existing feature set
of the Spring TestContext Framework. This support is enabled via
@ExtendWith(SpringExtension.class).
- @SpringJUnitConfig: a composed annotation that combines
@ExtendWith(SpringExtension.class) from JUnit Jupiter with
@ContextConfiguration from the Spring TestContext Framework.
- @SpringJUnitWebConfig: a composed annotation that combines
@ExtendWith(SpringExtension.class) from JUnit Jupiter with
@ContextConfiguration and @WebAppConfiguration from the Spring
TestContext Framework.
Issue: SPR-13575
Before this commit, it was not possible to set the status code of an
HTTP response without throwing an exception if it was already
committed. The consequence was a lot of errors in the logs for long
lived HTTP exchanges like Server-Sent Events for example.
After this commit, ServerHttpResponse#setStatusCode() returns
true if the operation succeeded and false if the status code has not
been set because the response has already been committed.
In term of implementation, that makes status code managed
consistently with headers and cookies:
AbstractServerHttpResponse#setStatusCode() stores the status
code that will be effectively set later in the response lifecycle by
the HTTP server via AbstractServerHttpResponse#writeStatusCode()
when the response will be committed.
When using the ConversionService to check and bridge to and from
reactive types we now generallly provide the full type information
available from method signatures. However that full type information
is not always necessary such as when we perform additional checks on
the generics of the reactive type (e.g. Mono<ResponseEntity>).
This allows us to switch to use DefaultFormattingConversionService
instead of GenericConversionService while also ensuring that the
CollectionToObjectConverter doesn't think it can convert List<?> to
any reactive type.
The ObjectToObjectConverter can also interfere because it is smart
enough to find the "from(Publisher<?>)" method on Flux and Mono.
To make up for that on the response side we now check if a type
is assignable to Publisher first in which case it is a simple cast.
In turn that means we don't need a PublisherToFluxConverter which can
be problematic in its own right because it can convert from Mono to
Flux which technically doesn't lose data but switches stream semantics.
Issue: #124, #128
HandlerAdapter's should always be able to provide a MethodParameter
which in turn ensures that HandlerResultHandler's have full type
information from method declarations.
This commit also introduces ResolvableMethod for use in tests to make
it easy to obtain MethodParameter return types.
Issue: #128
This commit adds a Decoder#decodeOne() method in order
to handle correctly the streaming versus one value
deserialization based on the type provided by the user.
For example, if a List parameter is provided in a controller
method, Jackson will be called once, while if the user provides
a Flux or an Observable parameter, Jackson will be called for
each element.
This commit replaces Reactive Streams converters for RxJava1 and
CompletableFuture with Reactor specific ones. The results in conversion
that preserves stream semantics, i.e. Mono vs Flux.
For example this is allowed:
Flux -> Observable
Mono -> Single
Mono -> CompletableFuture
This is not allowed:
Flux -> Single
Mono -> Observable
Flux -> CompletableFuture
As a result it is now possible to check through the ConversionService
if a target type to convert to is a stream of many or of one which is
useful for decoding purposes.
The commit also adds PublisherToFluxConverter to allow conversion from
raw Publisher to Flux. The reverse is not necessary since Flux is a
Publisher and it's a no-op conversion.
The DefaultWebSessionManager now uses Mono.defer to protect the call
to getSession from parsing session cookies immediately. This allows
pre-initializing the Mono<WebSession> upfront vs using a lock.
When in state DATA_AVAILABLE if there are simultaneous invocations of
AbstractRequestBodyPublisher.RequestBodySubscription.request and
ReadListener.onDataAvailable, the first one will process the available
data, the second one should not throw an exception because thus it will
signal to web container that there are problems while there are not.
Refactored Undertow support to register a response listener only when
the body is written to, as opposed to registering it at startup. The
reason for this is that getting the response channel from the
HttpServerExchange commits the status and response, making it impossible
to change them after the fact.
Fixed issue #119.
When there are simultaneous invocations of onWritePossible, only the
first one should succeed. This can happens when
AbstractResponseBodySubscriber.onNext and
WriteListener.onWritePossible() are called respectively by the
application and the web container.
Originally handleNoMatch looked for partial matches based on URL
pattern, HTTP method, consumes, produces, and params in that order
but without narrowing down the set of partial matches resulting in
potentially inaccruate response status codes
Commit 473de0 added an improvement to narrow the set with partial
matches for URL pattern and HTTP method matches.
This commit overhauls handleNoMatch so that the narrowing down of
matches happens at each stage resulting in more accurate error
reporting for request mappings with fine-grained conditions.
Issue: SPR-14397
This commit fixes MessagingMessageConverter to no longer expose the lazy
message resolution algorithm. This restores proper behaviour for
converters used outside of that context.
Instead, such arrangement is now private to
AbstractAdaptableMessageListener (as it should).
Issue: SPR-14389
The `CacheResolver` and `ErrorHandler` features introduced in 4.1 were
not properly enabled in AspectJ mode. This commit adds more tests from
the regular proxy-based mode and align the AspectJ caching configuration.
Issue: SPR-14413
This commit adds a `ClientHttpRequestInterceptor` that applies a BASIC
authorization header for each request.
It can be used as follows:
```
BasicAuthorizationInterceptor basicAuthorization =
new BasicAuthorizationInterceptor("user", "secret");
restTemplate.getInterceptors().add(basicAuthorization);
```
Issue: SPR-14412
Reactored Servlet 3.1 and Undertow request support
(AbstractResponseBodySubscriber) to use an internal state machine,
making thread-safity a lot easier.
As of 4.3 ResourceHttpRequestHandler delegates to the configured
ContentNegotiationManager, or one created internally, to look up
the media type for are resource.
This commit ensures the internally created ContentNegotiationManager is
correctly injected with the ServletContext through which it can perform
lookups as before.
Also the ServletPathContentNegotiationStrategy now checks the
ServletContext first and then delegates to its parent the
PathContentNegotiationStrategy and not vice versa. This is
consistent with how handleNoMatch (also in the same class) works
and also matches how ResourceHttpRequestHandler worked before 4.3.
Issue: SPR-14368
This commit sets the response content type to
"text/event-stream;charset=UTF-8". Even if the SSE spec says that the
encoding should always be UTF-8 and that specifying the charset is
optional, we're setting it in all cases, since some containers might use
the default encoding "ISO-8859-1" and confuse HTTP clients.
Issue: SPR-14407
Currently ResponseEntityResultHandler is ordered lower than
ResponseBodyResultHandler by default whch means a ResponseEntity
should not be picked by the ResponseBodyResultHandler.
However as it is easy to have both ResponseEntity and @ResponseBody
e.g. in @RestControler (or even by mistake) and in general it makes
sense for ResponseBodyResultHandler to explicitly recognize and
ignore the ResponseEntity return type.
Before this commit only ResponseEntity with async body was supported,
e.g. ResponseEntity<Mono<String>>
This commit also adds suppport for an asyn wrapper around,
e.g. Mono<ResponseEntity<String>.
Introduce separate test classes for each base class in the hierarchy
above @ResponseBody and ResponseEntity result handlers.
Also start porting existing unit test cases for @ResponseBody and
ResponseEntity return value handlers.
Reactored Servlet 3.1 and Undertow response support into an
AbstractResponseBodySubscriber that uses an internal state machine,
making thread-safity a lot easier.
Flux<SseEvent> is Spring Web Reactive equivalent to Spring MVC
SseEmitter type. It allows to send Server-Sent Events in a reactive way.
Sending Flux<String> or Flux<Pojo> is equivalent to sending
Flux<SseEvent> with the data property set to the String or
Pojo value. For example:
@RestController
public class SseController {
@RequestMapping("/sse/string")
Flux<String> string() {
return Flux.interval(Duration.ofSeconds(1)).map(l -> "foo " + l);
}
@RequestMapping("/sse/person")
Flux<Person> person() {
return Flux.interval(Duration.ofSeconds(1)).map(l -> new Person(Long.toString(l), "foo", "bar"));
}
@RequestMapping("/sse-raw")
Flux<SseEvent> sse() {
return Flux.interval(Duration.ofSeconds(1)).map(l -> {
SseEvent event = new SseEvent();
event.setId(Long.toString(l));
event.setData("foo\nbar");
event.setComment("bar\nbaz");
return event;
});
}
}
This commit updates AbstractHandlerExceptionResolver to only log at the
WARN level exceptions that are actually resolved by the
ExceptionResolver.
In case developers wish to log each time an ExceptionResolver is called,
a DEBUG level log is still available.
Issue: SPR-14392
Prior to this commit, any attempt to include a bean of type
ServletServerContainerFactoryBean in the WebApplicationContext for an
integration test class annotated with @WebAppConfiguration in
conjunction the Spring TestContext Framework (TCF) would have resulted
in an IllegalStateException stating that "A ServletContext is required
to access the javax.websocket.server.ServerContainer instance."
In such scenarios, the MockServletContext was in fact present in the
WebApplicationContext; however there was no WebSocket ServerContainer
stored in the ServletContext.
This commit addresses this issue by introducing the following.
- MockServerContainer: a private mock implementation of the
javax.websocket.server.ServerContainer interface.
- MockServerContainerContextCustomizer: a ContextCustomizer that
instantiates a new MockServerContainer and stores it in the
ServletContext under the attribute named
"javax.websocket.server.ServerContainer".
- MockServerContainerContextCustomizerFactory: a
ContextCustomizerFactory which creates a
MockServerContainerContextCustomizer if WebSocket support is present
in the classpath and the test class is annotated with
@WebAppConfiguration. This factory is registered by default via the
spring.factories mechanism.
Issue: SPR-14367
When comparing multiple matching @RequestMapping's, the HTTP method
condition has the lowest precedence. It's mainly about ensuring an
explicit mapping wins over an implicit (i.e. no method) one.
As of 4.3 HTTP HEAD is handled automatically for controller methods
that match to GET. However an explicit mapping HTTP HEAD allows an
application to take control.
This commit ensures that for HTTP HEAD requests the HTTP method
condition is checked first which means that an explicit HEAD mapping
now trumps all other conditions.
Normally we look for the most specific matching @RequestMapping.
For HTTP HEAD we now look for the most specific match among
@RequestMapping methods with a HEAD mapping first.
Issue: SPR-14383
This commit also fixes an issue in the HTTP client that used the
wrapper type instead of the element type. As a consequence, due
to type erasure, we now have to specify the type of the content
in DefaultHttpRequestBuilder#contentStream().
Even before this change SockJS sessions always cancelled the heartbeat
task first prior to sending messages. However when the heartbeat task
is already in progress, cancellation of it is not enough and we must
wait until the heartbeat is sent.
This commit adds a heartbeat write lock which is obtained and held
during the sending of a heartbeat. Now when sessions send a message
they still cancel the heartbeat task but if that fails they also wait
for the heartbeat write lock.
Issue: SPR-14356
ReflectionTestUtils invokes toString() on target objects in order to
build exception and logging messages, and prior to this commit problems
could occur if the invocation of toString() threw an exception.
This commit addresses this issue by ensuring that all invocations of
toString() on target objects within ReflectionTestUtils are performed
safely within try-catch blocks.
Issue: SPR-14363
In the process of upgrading the build to use Gradle 2.14, the
setFieldOnLegacyEntityWithSideEffectsInToString() test method in
ReflectionTestUtilsTests began to fail. The reason is that the log
level for ReflectionTestUtils is now DEBUG by default with Gradle 2.14.
The apparent cause is that log4j was present on the test runtime
classpath for the spring-test module with all previous versions of
Gradle (via a transitive optional dependency from another project that
spring-test depends on). Thus the configuration in log4j.properties in
spring-test was previously honored, but with Gradle 2.14 a different
commons logging implementation is picked up.
Thus, in addition to upgrading the build to Gradle 2.14, this commit
introduces an explicit test runtime dependency on log4j in the
spring-test module.
The discovered bug in ReflectionTestUtils regarding DEBUG log level
will be addressed separately.
Issue: SPR-14362
Renamed getSupportedMimeTypes() to getEncodableMimeTypes and
getDecodableMimeTypes. This will allow for both Encoder and Decoder to
be implemented in the same class.
This issue fixes#113.
The Pojo test class from the codec package will end up in spring-core.
This commit ensures it is used only from classes that also belong to
spring-core.
After the fix for ReactiveX/RxNetty#509 we can remove the workaround
to concatenate with an empty Observable for the request body and
upgrade to the latest RxJava 1.1.5.
Issues: #103
ViewResolutionResultHandler and ResponseBodyResultHandler now share
a common base class ContentNegotiatingResultHandlerSupport that
supports content negotiation.
For view resolution we compare against the supported media types of
resolved View instances, which may include default View's delegating
to an HttpMessageConverter (e.g. JSON, XML, rendering).
View now returns Mono<Void> rather than Flux<DataBuffer> which aligns
more closely with the reactive HttpMessageConverter vs the Encoder.
The change was prompted by the upcoming implementation of a View that
delegates to an existing HttpMessageConverter e.g. for JSON, XML.
The resulting change also brings the reactive View closer in spirit to
the View from spring-webmvc which returns void.
The ContentNegotiatingResultHandlerSupport base class encapsulates the
logic for content negotiation needed for both @ResponseBody and view
resolution result handling.
Before this change Consumes/ProducesRequestCondition shared a common
match method in the package private AbstractMediaTypeExpression. The
benefit, two lines of code, was negligible but was forcing each
condition into parsing the content type of the request body or
evaluating the content type for the response respectively.
This change removes the shared match method and brings it down into
each sub-class resulting in a performance improvement as well as in
simpler code including exception handling.
Issue: SPR-14299
Previously MockMvcWebConnection did not update the cookie manager with the
cookies from MockHttpServletResponse. This meant that newly added cookies
are not saved to the cookie manager and thus are not presented in the next
request.
This commit ensures that MockMvcWebConnection stores the response cookies
in the cookie manager.
Issue: SPR-14265
This commit adds support for Model-related return values types such as
Map, Model, @ModelAttribute annotated, and non-simple types, which
helps to clarify the logic in ViewResolutionResultHandler.
In order to be more "reactive", changed StringDecoder's default from
merging all buffers in the stream to a single buffer into splitting the
buffers along newline (\r, \n) characters.
This commit introduces DataBuffer.indexOf(IntPredicate) and
lastIndexOf(IntPredicate), for finding the index of a byte in a
DataBuffer.
It also introduces DataBufferUtils.tokenize, which tokenizes a
DataBuffer into separate tokens, given a delimiter function.
While View and ViewResolver play the same role as in spring-webmvc they
are now abstracted behind the HandlerResultHandler abstraction so that
top-level contracts don't reference them and the DispatcherHandler is
also unaware of their existence.
Furthermore view resolution and response body handling which are now at
the same level of abstraction (each is a HandlerResultHandler) will
also share code for content negotiation, so it makes sense for them to
be side by side.
This commit moves the reactive.view package to reactive.result.view
with the View and ViewResolver contracts (previously in the top-level
reactive package) also moving there.
When a null is returned from an @ResponseBody method, rather than
returning Mono.empty() immediately, convert it to Mono.empty() and
apply the same processing.
Currently that doesn't make a practical difference but it's more
accurate to do it this way. Eventually it may mean the possibility
to turn empty values into something through an extension point
as we do with ResponseBodyAdvice in Spring MVC today.
Normally heartbeats keep connections from hanging. However in some
cases a connection may hang before a CONNECTED frame is received
and heartbeats are put in place. This commit adds a change to enforce
a 60 limit on receiving the CONNECTED frame.
Issue: SPR-14266
Since the user controls the value of `spring.status.value`, you wouldn't want to echo unescaped values here in this form. Otherwise one could submit a value of, say, `"/> <script>alert("pwned")</script>`.
Prior to Java 8 it never really made much sense to author integration
tests using interfaces. Consequently, the Spring TestContext Framework
has never supported finding test-related annotations on interfaces in
its search algorithms.
However, Java 8's support for interface default methods introduces new
testing use cases for which it makes sense to declare test
configuration (e.g., @ContextConfiguration, etc.) on an interface
containing default methods instead of on an abstract base class.
This commit ensures that all non-repeatable, class-level test
annotations in the Spring TestContext Framework can now be declared on
test interfaces. The only test annotations that cannot be declared on
interfaces are therefore @Sql and @SqlGroup.
Issue: SPR-14184
Prior to this commit the SpEL compiler would generate bad bytecode
if the left hand operand of an instanceof was a primitive or
if the right hand operand was a primitive type reference.
With the fixes primitives on the left hand side are now
correctly boxed and special handling is in place for when the
right hand side is a primitive type reference. Using a primitive
type reference on the right always causes the instanceof
check to return false.
Additionally a guard has been added such that compilation is
not allowed when the right hand side of an expression
is not a type reference. If it is, for example, a variable
reference that evaluates to a type reference then that
cannot be expressed in bytecode so compilation is not performed.
Issue: SPR-14250
Prior to this commit, the latest optimizations introduced in SPR-13913
would prevent matching when patterns contained spaces. Indeed, the
optimized path would not fully tokenize the paths nor trim the tokens,
as the "longer" code path does.
This commit disables this optimized path when the `trimTokens` option is
set to `true`.
Also, the `trimTokens` setting is now set to `false` by default.
Issue: SPR-14247
Prior to this commit, information regarding avoiding false positives
when testing with JPA had already been added to the Testing chapter of
the reference manual. However, the example did not work properly and
the accompanying text mixed concepts from Hibernate and JPA.
This commit fixes the @Autowired/@PersistenceContext bug, updates the
text, and marks each test as @Transactional in order to avoid any
misinterpretation.
Issue: SPR-9032
Prior to this commit, @BeforeTransaction and @AfterTransaction could
only be declared on methods within test classes. However, JUnit 5 as
well as some existing third-party Runner implementations for JUnit 4
already support Java 8 based interface default methods in various
scenarios -- for example, @Test, @BeforeEach, etc.
This commit brings the Spring TestContext Framework up to date by
supporting the declaration of @BeforeTransaction and @AfterTransaction
on interface default methods.
Issue: SPR-14183
This commit updates the Testing chapter in the reference manual to
refer explicitly to JUnit 4 instead of just "JUnit" (where appropriate)
in order to avoid confusion with forthcoming support for JUnit 5.
SendTo and SendToUser are treated as mutually exclusive. The addition of
type-level support in 4.3. RC1 however did not consider the possibility
to mix and match of the two betwee type and method level.
This commit consolidates the detection of SendTo and SendToUser
annotations and considers them all together.
Issue: SPR-14238
Prior to this commit, setting the `forceEncoding` option would force
encoding on both requests and responses.
This commit adds two new setters and a new constructor to differentiate
both options: forcing the encoding on the request and/or on the
response.
You can now define this filter programmatically using those options or
update your servlet XML configuration like:
```
<filter>
<filter-name>characterEncodingFilter</filter-name>
<filter-class>o.sf.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<init-param>
<param-name>forceRequestEncoding</param-name>
<param-value>true</param-value>
</init-param>
<init-param>
<param-name>forceResponseEncoding</param-name>
<param-value>false</param-value>
</init-param>
</filter>
```
Issue: SPR-14240
Prior to this commit, the `ResourceHttpMessageConverter` would support
all HTTP Range requests and `MethodProcessors` would "wrap" controller
handler return values with a `HttpRangeResource` to support that use
case in Controllers.
This commit refactors that support in several ways:
* a new ResourceRegion class has been introduced
* a new, separate, ResourceRegionHttpMessageConverter handles the HTTP
range use cases when serving static resources with the
ResourceHttpRequestHandler
* the support of HTTP range requests on Controller handlers has been
removed until a better solution is found
Issue: SPR-14221, SPR-13834
This commit makes sure that HTTP request headers containing ETag values
are properly parsed and not simply tokenized using a "," separator.
Indeed, ETags can legally contain separator characters such as " " and
",".
Issue: SPR-14216
Prior to this change, getting header values with `HttpHeaders` when
headers are multi-valued would cause issues.
For example, for a given HTTP message with headers:
Cache-Control: public, s-maxage=50
Cache-Control: max-age=42
Getting a `List` of all values would return <"public", "s-maxage=50">
and getting the header value would return "public, s-maxage=50".
This commit takes now into account multi-valued HTTP headers and adds
new getters/setters for "If-Match" and "If-Unmodified-Since" headers.
Note that for ETag-related headers such as "If-Match" and
"If-None-Match", a special parser has been implemented since ETag values
can contain separator characters.
Issue: SPR-14223, SPR-14228
Resources are now retrieved using the application context in order to
support natively non-classpath locations like /WEB-INF/...
As a consequence of this refactoring, ScriptTemplateView#createClassLoader()
protected method as been removed, since it did not make sense anymore with
this new resource loading implementation.
Issue: SPR-14210
Prior to this change, setting both "If-None-Match" and
"If-Unmodified-Since" conditional request headers would check for both
conditions to be met.
This commit fixes this behavior to follow the RFC7232 Section 6:
> entity tags are presumed to be more accurate than date validators
So in case both conditions are present, the "If-None-Match" condition
takes precedence.
Issue: SPR-14224
This commit introduces a pooled data buffer as a subtype of DataBuffer,
as well as various utility methods related to reference counting.
Additionally, Crelease calls have been introduced throughout the
codebase to properly dispose of pooled databuffers.
Previously MockWebResponseBuilder would use the cookie domain of the cookie
received from MockMvc response. This caused problems because the cookie
domain can be null, but HtmlUnit forbids a null domain.
This commit defaults the domain of the cookie to the domain of the
WebRequest.
Issues SPR-14169
It's handy to know in advance whether or not expression that is
passed to CronSequenceGenerator or CronTrigger constructor would
not results in IllegalArgumentException. The only way to do it
now is to try\catch an instance creation but it's kinda ugly.
Rename two classes each adapting to WebHandler to avoid confusing them:
1. HttpWebHandlerAdapter adapts from the low level HttpHandler to any
WebHandler (e.g. DispatcherHandler).
2. SimpleHandlerAdapter adapts the plain WebHandler for use within the
DispatcherHandler.
This commit also fixes an issue in WebHttpHandlerBuilder to ensure that
WebExceptionHandler's are inserted before and not after WebFilter's.
The renaming makes it clear this exception is for use where 400 error
applies within a Spring web application where the error may be
associated with a MethodParameter, a BindingResult, and so on.
There is no need for BadRequestStatusException which can be expressed
with ResponseStatusException(HttpStatus.BAD_REQUEST, "reason").
This commit wraps up the previous commits:
- It uses HttpMessageConverter in the web.reactive.server package instead of Encoder/Decoder.
- It introduces tests for the Resource @ResponseBodies.
This commit introduces a reactive version of the HttpMessageConverter.
During the implementation of zero-copy support, it became apparent that
it was ueful to have a common abstraction between client and server that
operated on HttpMessages rather than DataBuffers.
Two HttpMessageConverter implementations are provided:
- The CodecHttpMessageConverter, based on Encoder/Decoder.
- The ResourceHttpMessageConverter, using zero-copy if available.
This commit introduces support for zero-copy file transfers in the HTTP
response, through the ZeroCopyHttpOutputMessage subinterface of
ReactiveHttpOutputMessage.
This commit introduces two DataBuffer improvements:
- The capability to read a Flux<DataBuffer> from an input stream or
channel.
- The capability to limit a Publisher<DataBuffer> to publish up until a
given maximum byte count.
Now that we have a CompositeContentTypeResolverBuilder with built-in
defaults, we switch to those defaults in places where a
ContentTypeResolver is used.
Rename to MappingContentTypeResolver and replace "fileExtension" with
"key" in methods to be more general (e.g. file extension or query
param). Also switch from List to Set for the return values.
This commit introduces @Ignore'd tests for future support for declaring
@BeforeTransaction and @AfterTransaction on interface default methods.
Issue: SPR-14183
Prior to this commit, the new match algorithm wouldn't work for multiple
consecutive path separators.
This commit separately matches path segments and path separators and
allows for multiple, consecutive path separators.
Issue: SPR-14141
A pretty complete equivalent to the same in spring-webmvc except for
CORS checks, and custom HTTP methods. Another notable difference is
that the "params" condition works on query params strictly.
Previously using the Gradle Daemon with import eclipse scripts would cause
issues with the merge plugin. Specifically, projects would randomly not
be associated to the classpath.
This change explicitly adds --no-daemon in the import scripts to ensure
that the problem does not occur.
Issue SPR-14102
Spring uses lots of forbidden references. The current Eclipse settings
set forbiddenReference=error This was not ideal because there were lots of
errors in the workspace.
This commit changes forbiddenReference=warning since we nee to allow
forbidden references.
Previously HtmlUnitRequestBuilder did not decode parameter names. This
means if a parameter like row[0] was submittted it would be encoded as
row%5B0%5D When the HttpServletRequest was created the parameter name would
not be decoded so the parameter name row[0] would not be found.
This commit ensures that HTTP parameter names are decoded.
Issue SPR-14177
This commit makes sure to reject an `@EventListener` annotated method
that also uses `@Async`. In such scenario, the method is invoked in a
separate thread and the infrastructure has no handle on the actual reply,
if any.
The documentation has been improved to refer to that scenario.
Issue: SPR-14113
This commit adds AbstractHandlerMethodMapping, a starting point for
AbstractHandlerMapping, and HttpRequestPathHelper with a similar
purpose to UrlPathHelper but based with ServerWebExchange as input.
- correct name of HttpHandlerHandlerAdapter to WebHandlerHandlerAdapter
- shorten SimpleHandlerResultHandler to SimpleResultHandler
- add HandlerResult constructor without Model
- update tests
This commit adds the "*/*" media type in the list of compatible media
types for the StringDecoder. This allows this decoder to decoder
payloads of any media type as long as the target type is String.
Fixes#87
This commit introduces a new method in TestPropertySourceUtils that
allows properties files to be added directly to the environment without
the need for a ConfigurableApplicationContext upfront; however, a
ResourceLoader is still necessary.
Issue: SPR-14131
This commit underlines the fact that the request created by a
ClientHttpRequestFactory should be augmented with a message body using
the `ClientHttpRequest#setBody` method before it is executed.
See #82
This commit makes messageEncoders a required argument for building a
client request - those are needed to actually encode the body object as
a reactive stream to be written to the HTTP request body.
Removed raw types usage in DefaultHttpRequestBuilder.
DefaultHttpRequestBuilder now uses a UriTemplateHandler to expand URI
templates + variables into a concrete URI.
Fixes#80, fixes#85, fixes#86
This commit introduces the new `WebClientException` for wrapping
client-side exceptions.
This exception is now thrown when now message encoder can be found for
writing the request body as an HTTP request message.
Fixes#83
This commit adds generics support for WebResponseExtractors.
Types should be described using a ResolvableType, which can be
created with static methods like:
// for the type Event<Registration>
ResolvableType.forClassWithGenerics(Event.class, Registration.class)
Fixes#89
- Introcuces XmlEventDecoder which decodes from DataBuffer to
javax.xml.stream.events.XMLEvent. It uses the Aalto async XML API if
available, but falls back to a blocking default if not.
- Refacors Jaxb2Decoder to use said XmlEventDecoder, and split the
stream of events into separate substreams by using the JAXB annotation
value, one stream for each part of the tree that can be unmarshaled to
the given type.
- Various improvements in the JAXB code.
Previous refactoring (fcf6ae and also 43d937) in the SockJsSession
hierarchy consolidated access to the request and response in the
base class AbstractHttpSockJsSession in order to keep synchronization
concerns there. However that also unintentionally removed the call to
resetRequest() after sending a heartbeat for any of the
PollingSockJsSession classes. In general a polling session should call
resetRequest after every frame written.
This commit brings back the writeFrame override in PollingSockJsSession
with an extra call to resetRequest().
Issue: SPR-14107
Prior to this commit, the size of the ApplicationContext cache in the
Spring TestContext Framework could grow without bound, leading to
issues with memory and performance in large test suites.
This commit addresses this issue by introducing support for setting the
maximum cache size via a JVM system property or Spring property called
"spring.test.context.cache.maxSize". If no such property is set, a
default value of 32 will be used.
Furthermore, the DefaultContextCache has been refactored to use a
synchronized LRU cache internally instead of a ConcurrentHashMap. The
LRU cache is a simple bounded cache with a "least recently used" (LRU)
eviction policy.
Issue: SPR-8055
Commit 48236b from 2014 introduced a logging improvement to avoid
logging each removed session per line and instead log one line at
the end with all removed sessions ids. However that list of removed
session ids wasn't populated. This commit fixes that.
Issue: SPR-14111
This commit documents the @Ignore'd test to explain that Spring does not
support a hybrid approach for annotation attribute overrides with
transitive implicit aliases.
Issue: SPR-13554
OkHttp3 introduces a new package and API that is incompatible with
previous versions. This commit adds a new
OkHttp3ClientHttpRequestFactory and supporting classes.
This commit reverts the recently added merged annotation support for
Spring's JMX annotations by once again using the simpler searches for
repeatable annotations in AnnotationUtils.
Issue: SPR-13973
Prior to this commit, the `HttpInvokerServiceExporter` would close
its `ObjectOutputStream`, which itself issues duplicate flushes on the
underlying `OutputStream`. Duplicate flushes can lead to multiple,
separate TCP packets where those should be gathered writes.
This commit wraps the underying stream with a decorator that guards
against flush calls that are duplicated with the one done in `close`.
Issue: SPR-14040
Prior to this commit, HTTP clients relying on the JDK HTTP client would
not properly reuse existing TCP connections (i.e. HTTP 1.1 persisten
connection). The SimpleClientHttpResponse would close the actual connection once the
response is handled.
As explained in the JDK documentation
(http://docs.oracle.com/javase/8/docs/technotes/guides/net/http-keepalive.html)
HTTP clients should do the following to allow resource reuse:
* consume the whole HTTP response content
* close the response inputstream once done
This commit makes sure that the response content is
totally drained and then the stream closed (and not the connection).
Issue: SPR-14040
Prior to this commit, binding a `@ModelAttribute` object as a Controller
handler paramater would instantiate the object and set all its
properties, fetching data from the request. When no data is available,
the WebDataBinder tries to bind default "empty" values:
* Boolean.FALSE for boolean types
* empty arrays for array types
* null by default
This commit adds the new default empty values:
* empty Collections for Collection types
* empty Maps for Map types
Rather than using empty implementations provided by `Collections.empty`
(which are not mutable), we're using the closest possible target type
and real implementations, provided by the `CollectionFactory`.
Issue: SPR-13502
This commit introduces a boolean alwaysProcesses() method in the
Processor API which allows for simplification across all search
algorithms within AnnotatedElementUtils.
Specifically, it is no longer necessary for process() methods to verify
that the supplied annotation is actually the sought target annotation.
In addition, duplicated code has been extracted into common methods
(e.g., hasMetaAnnotationTypes()) and common Processor implementations
(e.g., AlwaysTrueBooleanAnnotationProcessor).
This commit picks up where 2535469099 left off with added support for
"get" search semantics for merged repeatable annotations.
Specifically, this commit introduces a new
getMergedRepeatableAnnotations() method in AnnotatedElementUtils.
Issue: SPR-13973
This commit picks up where a5139f3c66 left off with added support for
"get" search semantics for multiple merged annotations.
Specifically, this commit introduces a new getAllMergedAnnotations()
method in AnnotatedElementUtils.
Issue: SPR-13486
Prior to this commit, AnnotationUtils supported searching for
repeatable annotations even if the repeatable annotation was declared
on a custom stereotype annotation. However, there was no support for
merging of attributes in composed repeatable annotations. In other
words, it was not possible for a custom annotation to override
attributes in a repeatable annotation.
This commit addresses this by introducing
findMergedRepeatableAnnotations() methods in AnnotatedElementUtils.
These new methods provide full support for explicit annotation
attribute overrides configured via @AliasFor (as well as
convention-based overrides) with "find semantics".
Issue: SPR-13973
This commit resolves a few comments brought forward during a review
meeting, specifically:
- It renames AbstractResponseBodyPublisher to
AbstractRequestBodyPublisher.
- It separates out registration logic into a register method.
- It moves the RequestBodyPublisher and ResponseBodySubscriber for the
Servlet 3.1 support back into ServletHttpHandlerAdapter.
Prior to this commit, HTTP Range requests were only supported by the
ResourceHttpRequestHandler when serving static resources.
This commit improves the ResourceHttpMessageConverter that
now supports partial writes of Resources.
For this, the `HttpEntityMethodProcessor` and
`RequestResponseBodyMethodProcessor` now wrap resources with HTTP
range information in a `HttpRangeResource`, if necessary. The
message converter handle those types and knows how to handle partial
writes.
Controller methods can now handle Range requests for
return types that extend Resource or HttpEntity:
@RequestMapping("/example/video.mp4")
public Resource handler() { }
@RequestMapping("/example/video.mp4")
public HttpEntity<Resource> handler() { }
Issue: SPR-13834
Just like SPR-13252 addressed this issue for the "Pragma" header, this
issue resets the HTTP 1.0 "Expires" header.
When such a header has been set (by a filter, for example) and HTTP
caching has been configured at the WebContentGenerator, this header
value is reset to "". In this case, "Cache-Control" and "Expires" might
have inconsistent values and we consider that the HTTP caching
configuration should take precedence.
Depending on the servlet container chosen to deploy the application,
this might result in empty "" header values or no header set at all.
Issue: SPR-14053
Prior to this commit, @Cacheable, @CacheEvict, @CachePut, and @Caching
could be used to create custom stereotype annotations with hardcoded
values for their attributes; however, it was not possible to create
composed annotations with attribute overrides.
This commit addresses this issue by refactoring
SpringCacheAnnotationParser to use the newly introduced
findAllMergedAnnotations() method in AnnotatedElementUtils. As a
result, @Cacheable, @CacheEvict, @CachePut, and @Caching can now be
used to create custom composed annotations with attribute overrides
configured via @AliasFor.
Issue: SPR-13475
Prior to this commit it was possible to search for the 1st merged
annotation above an annotated element. It was also possible to search
for annotation attributes aggregated from all annotations above an
annotated element; however, it was impossible to search for all
composed annotations above an annotated element and have the results as
synthesized merged annotations instead of a multi-map of attributes.
This commit introduces a new findAllMergedAnnotations() method in
AnnotatedElementUtils that finds all annotations of the specified type
within the annotation hierarchy above the supplied element. For each
such annotation found, it merges that annotation's attributes with
matching attributes from annotations in lower levels of the annotation
hierarchy and synthesizes the results back into an annotation of the
specified type. All such merged annotations are collected and returned
as a set.
Issue: SPR-13486
This commit introduces tests that verify the status quo for finding
multiple merged composed annotations on a single annotated element.
Issue: SPR-13486
Prior to this commit, it was possible that implicit aliases and
transitive implicit aliases (configured via @AliasFor) might not be
honored in certain circumstances, in particular if implicit aliases
were declared to override different attributes within an alias pair in
the target meta-annotation.
This commit addresses this issue by ensuring that all aliased
attributes in the target meta-annotation are overridden during the
merge process in AnnotatedElementUtils.
In addition, concrete default values for attributes in a
meta-annotation declaration can now be effectively shadowed by
transitive implicit aliases in composed annotations.
Issue: SPR-14069
JSON payloads are sometimes prepended with a static string prefix
to prevent Cross Site Scripting Inclusion attacks (XSSI).
Prior to this commit, doing so would fail the MockMvc
`JsonPathResultMatchers` since they're considering the whole response as
the JSON payload.
This commit adds a new `JsonPathResultMatchers.prefix` method that
configures the matchers to check for the presence of that string (i.e.
fail if it's not there) and only consider the rest of the response body
as the JSON payload for other assertions.
Issue: SPR-13577
Previously MockMvc builders failed to share the WebConnection used for
managing cookies in the MockMvcWebConnection. This meant that the various
CookieManagers would have different states.
This commit ensures that the WebConnection is set on the
MockMvcWebConnection.
Fixes SPR-14066
This commit introduces a test to demonstrate that inlined properties
override properties loaded from Properties files in
@TestPropertySource.
Issue: SPR-14068
Currently there are clashes between io.netty:netty-common:4.1.0.Beta7 and
io.netty:netty-all:4.1.0.CR3 which can cause errors in the build related
to "VerifyError: Bad type on operand stack".
One solution would be to exclude the jars that duplicate the classes.
However, this can be fragile since additional dependencies may be added
that bring in the dependency transitively.
This commit locks the version for any artifiact with the group "io.nettty"
to ensure the correct version of netty is used.
* SPR-14050:
Fully test proxy support in ReflectionTestUtils
Polishing
Document proxy support in ReflectionTestUtils
Fix bugs in ReflectionTestUtils related to proxies
Polishing
Support proxied objects in ReflectionTestUtils
This commit adds support for unwrapping proxies in the setField() and
getField() methods in ReflectionTestUtils.
Instead of always accessing fields directly on the supplied
targetObject (which may be a proxy), AopTestUtils is now used to obtain
the potential ultimateTargetObject which is then used for accessing
fields.
Issue: SPR-14050
Before this commit the DefaultUserDestinationResolver did not support
well broker destinations that use dot as separator with a built in
assumptions that the destinations it resolves must start with slash.
This change adds PathMatcher property that is used to determine if
an alternative path separator is in use and if so the leading slash is
left out.
Issue: SPR-14044
This commit primarily allows for a `SynthesizingMethodParameter` to be
created for a `Constructor` parameter but also introduces an additional
overloaded constructor from `MethodParameter`.
Issue: SPR-14054
Previously, a package private `@ManagedResource` annotated bean was
registered to the JMX domain even if any attempt to invoke an operation
on it will fail since it has to be public.
This commit validates that any `@ManagedResource` annotated bean is
public and throws an InvalidMetadataException otherwise. Note that the
actual bean type does not have to be public as long as the class
annotated with `@ManagedResource` in the hierarchy is pubic and no extra
operations or attributes are defined on the child.
Issue: SPR-14042
The DeferredResult~ and the ResponseBodyEmitterReturnValueHandler now
each expose an adapter mechanism for plugging in other async return
value types. As a result the ListenableFutureReturnValueHandler and
CompletionStageReturnValueHandler are no longer needed and are now
deprecated.
Issue: SPR-14046
Allow third-parties to contribute ContextCustomizers that can customize
ApplicationContexts created by the Spring TestContext Framework (TCF)
before they are refreshed.
A customizer may be provided via a ContextCustomizerFactory which is
registered with `spring.factories`. Each factory is consulted whenever
a new ApplicationContext needs to be created by the TCF. Factories may
inspect various details about the test and either return a new
ContextCustomizer or null.
ContextCustomizers are similar to ApplicationContextInitializers and
may perform any number of tasks, including bean registration, setting
of active profiles, etc.
Issue: SPR-13998
The MultiServerUserRegistry now supports scenarios where the same user
is connected to multiple servers. For such cases the SimpUser returned
from the registry exposes all sessions across all servers.
Issue: SPR-13800
Add a ServletTestExecutionListener.ACTIVATE_LISTENER attribute which
can be set on the TestContext to trigger activation of the listener
even if a `@WebAppConfiguration` is not present.
Issue: SPR-14035
This commit adds a new "validator" XML attribute to the
`<websocket:message-broker/>` element. This allows configuring a
specific Validator to be used for payload validation.
Issue: SPR-13996
Previously, the generic type of a simple pojo event implementing
ResolvableTypeProvider wasn't detected properly. This commit fixes the
logic when the generic type is not provided to reuse what
PayloadApplicationEvent is already doing anyway.
Issue: SPR-14029
Prior to this commit, the @ContextConfiguration annotation was required
to be present even if default XML files, Groovy scripts, or
@Configuration classes were detected; however, in such cases the
@ContextConfiguration was typically declared empty and therefore
seemingly unnecessary boilerplate.
This commit permits @ContextConfiguration to be omitted whenever it can
be reasonably deduced. Consequently, integration tests such as the
following are now supported.
@RunWith(SpringRunner.class)
public class MyTest {
@Autowired String myBean;
@Test public void example() { /* ... */ }
@Configuration
static class Config {
@Bean String myBean() {
return "Hello";
}
}
}
Issue: SPR-13955
Prior to this commit, the springUrl Velocity macro would only prepend
the context to the given URL; this means that the
ServletHttpResponse.encodeUri method is not called and neither the
ResourceUrlProvider.
This commit changes this macro to use RequestContext.getContextUrl which
prepends the context and encodes the URI.
Issue: SPR-14027
Update @WebAppConfiguration so that it no longer directly specifies
a TestContextBootstrapper. This allows third parties to use the
annotation in combination with their own bootstrapper.
BootstrapUtils now provides the detection logic for when
WebTestContextBootstrapper should be used.
Issue: SPR-13991
WebResponseExtractor uses Mono.when with the response status, headers,
and the decoded body. However when the response body stream is empty
then when completes empty too.
This change adds defaultIfEmpty handling for en empty response body.
This commit picks up where 8ff9e818a5
left off.
Specifically, this commit introduces support that allows a single
element attribute to override an array attribute with a matching
component type when synthesizing annotations (e.g., in annotations
synthesized from attributes that have been merged from the annotation
hierarchy above a composed annotation).
Issue: SPR-13972
The ResourceHttpRequestHandler now relies on the conifgured
ContentNegotiationManager to determine the content type for resource
requests rather than implementing that internally.
First we check against the matched resource based on the resource file
extension. Then we expand the check against the request with any
configured content negotiation strategy.
Issue: SPR-13658
This commit updates the WEBJARS_LOCATION in WebJarResourceResolver to
avoid getting duplicate slashes in resolved resources locations such
as `/webjars//bootstrap/3.3.2/js/bootstrap.min.js`.
Issue: SPR-14018
There is now an HttpCookie (simple name-value pair) and separately a
ServerHttpCookie sub-class with additional attributes that a server
can send to clients.
HttpHeaders is no longer the place to access cookies. Instead there is
a read-only HttpCookie map on ServerHttpRequest and a mutable
ServerHttpCookie map on ServerHttpResponse.
Cookies are stored in a map that preserves their order.
The DefaulUriTemplateHandler now provides a strictEncoding property
which if turned on encodes everything outside the reserved char set.
This is in contrast to the default policy of encoding only illegal
charaters depending on the URI component type.
Issue: SPR-11652
This commit adds a newline char at the beginning of textarea tags
values. As per the HTML 4.01 spec (and browsers behavior), a line break
following a start tag is ignored.
This can lead to Spring's textarea tag to ignore a line break char at
the beginning of a tag value.
See https://www.w3.org/TR/html401/appendix/notes.html#notes-line-breaks
Issue: SPR-13503
This commit changes the visibility of the getTestContext() method in
TestContextManager from 'protected' to 'public' in order to support
test method injection in JUnit 5 and similar use cases.
Issue: SPR-14011
Prior to this change, SPR-13867 made sure that any class extending
WebContentGenerator would not overwrite existing HTTP "Cache-Control"
response headers - set by a filter, a Controller handler, etc.
This caused issues with resource handling, since specifying a cache
configuration there would not overwrite default headers set by filters,
for example by Spring Security.
This commit restricts the previous changes to the
RequestMappingHandlerAdapter, in order to avoid overwriting header set
by a filter or a Controller handler in those cases.
Issue: SPR-14005
This commit demonstrates how to register one or more @Configuration
classes via an ApplicationContextInitializer in a composed annotation so
that certain @Configuration classes are always registered whenever the
composed annotation is used, even if the composed annotation is used to
declare additional @Configuration classes.
The new Filter is simply a new way of packaging the ability to extract
X-Forwarded-* headers already available via UriComponentsBuilder.
The Filter wraps the request and the effect is that anything using the
request will see the original schem, host, and port.
Issue: SPR-13614
Prior to this commit, `ServletWebRequest.checkNotModified` would only
support conditional GET/HEAD requests with "If-Modified-Since" and/or
"If-None-Match" request headers. In those cases, the server would return
"HTTP 304 Not Modified" responses if the resource didn't change.
This commit adds support for conditional update requests, such as
POST/PUT/DELETE requests with "If-Unmodified-Since" request headers.
If the underlying resource has been modified since the specified date,
the server will return a "409 Precondition failed" response status
to prevent concurrent updates.
Even if the modification status of the resource is reversed here
(modified vs. not modified), we're keeping here the same intent for the
return value, which signals if the response requires more processing or
if the handler method can return immediately:
```
if (request.checkNotModified(lastModified)) {
// shortcut exit - no further processing necessary
return null;
}
```
Issue: SPR-13863
Before this commit, specifying the charset to use with produces or
consumes @RequestMapping attributes resulted in default charset
loss. That was really annoying for JSON for example, where using
UTF-8 charset is mandatory in a lot of use cases.
This commit adds a defaultCharset property to
AbstractHttpMessageConverter in order to avoid losing the
default charset when specifying the charset with these
@RequestMapping attributes.
It changes slightly the default behavior (that's why we have waited
4.3), but it is much more error prone, and will match with most
user's expectations since the charset loss was accidental in most
use cases (users usually just want to limit the media type supported
by a specific handler method).
Issue: SPR-13631
This commit introduces the following common composed annotations for
@RequestMapping in Spring MVC and Spring MVC REST.
- @GetMapping
- @PostMapping
- @PutMapping
- @DeleteMapping
- @PatchMapping
Issue: SPR-13992
Prior to this commit, the TransactionalTestExecutionListener required
@Transactional test methods to be public; however, neither TestNG nor
JUnit 5 require that @Test methods are public. Consequently, non-public
transactional test methods silently run *without* a transaction.
This commit removes the 'public' restriction on transactional test
methods by setting the 'publicMethodsOnly' flag in
AnnotationTransactionAttributeSource to false.
Issue: SPR-14000
In order to align with the relaxed programming models of TestNG and the
upcoming JUnit 5 (with regard to method visibility), this commit
removes the requirement that @BeforeTransaction and @AfterTransaction
methods must be 'public'.
Issue: SPR-13997
This commit introduces a SpringRunner extension of
SpringJUnit4ClassRunner that is intended to be used as an 'alias' for
SpringJUnit4ClassRunner, primarily in order to simplify configuration
of JUnit 4 based integration tests.
Developers can use this alias as follows:
@RunWith(SpringRunner.class)
public class MySpringIntegrationTests { ... }
Issue: SPR-13954
MockRestServiceServer now provides static methods for builder-style
creation of MockRestServiceServer. This includes an option ignore
the order of declaration expected requests.
Issue: SPR-11365
This commit factors out the logic to declare and manage expectations
including matching them to requests and verifying at the end behind
a commong abstraction.
MockRestServiceServer delegates to the new abstraction and is no longer
aware of how that's done. There are two implementations, one for
ordered and another for unordered expectation.
Issue: SPR-11365
Before this commit RequestMatcherClientHttpRequest served both as
API to define request expectations, i.e. ResponseActions, as well as
the implementation of ClientHttpRequest representing actual requests.
DefaultResponseActions replaces this class as a simple holder of
expected requests and mock responses. MockRestServiceServer is then
responsible to match request expectations and create a mock response.
Issue: SPR-11365
Claneup of the Servlet 3.1 support:
- moved RequestBodyPublisher to ServletServerHttpRequest
- moved ResponseBodySubscribera to ServletServerHttpResponse
- response body is now copied to ServletOutputStream in chunks, rather
than one big byte[]
The CORS pre-flight request matching logic for all request conditions
was added (in 4.2) to RequestMappingInfo. However the logic for
default handling of all HTTP OPTIONS requests for 4.3 unintentionally
overrode some of the pre-flight request handling thus causing issues.
This commit moves CORS pre-flight matching logic into each respective
RequestMethodCondition implementations so each has to consider in one
place what happens for pre-flight and for all other requests.
Issue: SPR-13130
Previously, a ConfigurationClass created from AnnotationMetadata
and a ConfigurationClass created from a class would have subtly
different descriptions. Given a class named com.example.Foo, the
former’s description would be “com.example.Foo”, whereas the latter’s
description would be “class com.example.Foo”.
This commit updates ConfigurationClass to make the description
consistent, preferring the description without “class” in it.
Closes gh-970
The test failure was caused by the previous commit. The Message
resolver now supports payload conversion so it can raise a
MessageConversionException, not MethodArgumentTypeMismatchException.
Refine the optimizations made in 6f55ab69 in order to restore binary
compatibility and resolve a regression.
Tests of the form pathMatcher.match("/foo/bar/**", "/foo/bar") should
return true as this was the behavior in Spring 4.2.
Issue: SPR-13913
The MessageMethodArgumentResolver now also supports applying a
MessageConverter to the payload.
This is effectively a shortcut for declaring a method with an @Payload
argument + MessageHeaders and then creating a new message from the two.
Issue: SPR-13288
Commit ccd17d introduced a regression where a custom HTTP method
would no longer match for an empty @RequestMapping condition.
The previous behavior should now be restored. Effectively
RequestMethodRequestCondition as before will now match to any HTTP
method (even unknown/custom ones) if the methods condition is empty.
The only exception is HTTP OPTIONS for which we provide default
handling as a fallback (i.e. when not mapped explicitly).
Issue: SPR-13130
This commit adds weak ETag support in ShallowEtagHeaderFilter.
This improves the behavior of the filter in tow ways:
* weak ETags in request headers such as `W/"0badc0ffee"` will be
compared with a "weak comparison" (matching both weak and strong ETags
of the same value)
* when enabled with the "writeWeakETag" init param, the filter will
write weak Etags in its HTTP responses
Issue: SPR-13778
This change makes clear that this is the intent of the CacheControl API
not to provide a way to configure both "no-cache" and "no-store"
directives for the "Cache-Control" header.
Issue: SPR-13780
Check that the path is valid and resolvable before checking that the
http method is supported. For invalid or unresolvable paths, always
respond with a 404.
This commit changes the OkHttpClientHttpRequestFactory to use the
synchronous OkHttp API for non-async requests, as opposed to
synchronizing the async API (which it used to do).
Issue: SPR-13942
This commit speeds up the AntPathMatcher implementation by
pre-processing patterns and checking that candidates are likely
matches if they start with the static prefix of the pattern.
Those changes can result in a small performance penalty for positive
matches, but with a significant boost for checking candidates that don't
match. Overall, this tradeoff is acceptable since this feature is often
used to select a few matching patterns in a much bigger list.
This will lead to small but consistent performance improvements in
Spring MVC when matching a given request with the available routes.
Issue: SPR-13913
This commit adds a View and ViewResolver contracts to support HTML
template based rendering.
ViewResolverResultHandler applies view resolution by iterating the
resolvers to resolve to a view and then use it to render.
A model is created and passed to argument resolvers including a new
ModelArgumentResolver. The model is then exposed for result handling
as a field in HandlerResult.
Rename result to returnValue and resultType to returnValueType to
reflect what they represent.
The returnValue getter is also wrapped as Optional since the value
returned from a handler may be null (e.g. void method, null value).
Before this commit the concurrent session wrapper mainly protected the
sending of messages. The close itself however may also cause a message
to be sent as is the case of the SockJS protocol.
This change protects the close and checks if the session has exceeded
send time or buffer limits in which case the close status is changed
to SESSION_NOT_RELIABLE (introduced in commit cbd5af3a) which in turn
signals that extra care should be exercised when closing the session.
Issue: SPR-13904
This turned into the extraction of a common AbstractResourceBasedMessageSource base class which not only features addBasenames but also getBasenameSet and setCacheMillis.
Issue: SPR-10314
Prior to this commit, the transaction manager and data source look-up
algorithms in the Spring TestContext Framework were not capable of
retrieving 'primary' beans of those types, even though 'primary' beans
are supported in production as well as for injecting dependencies into
test instances. Specifically, if there was more than one transaction
manager or data source bean and one of them was flagged as 'primary',
the retrieveTransactionManager() and retrieveDataSource() methods in
TestContextTransactionUtils would simply return null for such beans.
This commit updates TestContextTransactionUtils by adding support for
looking up primary transaction managers and data sources.
Issue: SPR-13891
Prior to this commit, a @Transactional integration test would silently
be executed without a transaction if the transaction manager could not
be retrieved from the application context -- for example, it no such
bean was defined or if multiple beans were present but none satisfied
the qualifier.
This commit addresses this issue by throwing an IllegalStateException
if the PlatformTransactionManager cannot be retrieved for a
@Transactional test.
Issue: SPR-13895
This commit adds `RxJava1WebResponseExtractors`, a static factory of
`WebResponseExtractor`s that are based on the RxJava1 composition API.
All extracted types are based on the `Single` and `Observable` types.
This commit adds the `WebClient`, which relies on several parts of our
infrastructure:
* a `ClientHttpRequestFactory` to drive the underlying client library
* a `HttpRequestBuilder` builder API to create the client request
* a `WebResponseExtractor` to extract the "low-level"
`ClientHttpResponse` into a higher level representation such as a
decoded body
The `WebResponseExtractors` helper class contains many extractor
implementations all based on the `Flux`/`Mono` composition API.
This commit adds the `ClientHttpRequest` and `ClientHttpResponse`
implementations for the RxNetty HTTP client.
This client library is based on the `Single` and `Observable`
composition API, so this has to be converted to the `Flux`/`Mono`
variants.
This commit introduces the `ClientHttpRequest` and `ClientHttpResponse`
implementations for the Reactor-Net HTTP client. This client is already
based on the `Flux` and `Mono` contracts.
This commit also adds a `AbstractClientHttpRequest` to support the
`ClientHttpRequest` implementations; it mirrors the
`AbstractServerHttpResponse` contract with a `beforeCommit` to register
`Supplier`s that should be notified before the request is committed.
This commit adds a `DefaultHttpRequestBuilder` and its companion static
builders in `HttpRequestBuilders`. This allows to build client requests
with a friendly builder API, inspired by Spring's MockMvc API.
This commit adds the base contracts for the Web client.
The "Reactive" prefixes of the previously commited contracts has been
removed to match the server ones.
Both the `ClientHttpRequest` and the `ServerHttpResponse` extend
`ReactiveHttpOutputMessage`, which now has a `beforeCommit` method,
necessary in both client and server implementations.
`HttpRequestBuilder` will be used by the developers to create requests
with a nice builder API. `ClientHttpRequestFactory` will provide support
for many HTTP client libraries in this new client.
Custom argument resolvers configured in the MVC Java config or the
MVC namespace are now injected in both the RequestMappingHandlerAdapter
as well as in the ExceptionHandlerExceptionResolver.
Issue: SPR-12058
WebServerExchange -> ServerWebExchange
Follows the same convention as in the http package also better allowing
the possibility for a client equivalent in the future.
WebToHttpHandlerBuilder -> WebHttpHandlerBuilder
WebToHttpHandlerAdapter -> WebHttpHandlerAdapter
More consistent with Spring conventions.
Introduce adapter and handler sub-packages under web.server following a
review prompted by the addition of the session package and the package
cycle it brought in based on dependency on session.WebSessionManager.
This commit adds initial support for a maintaining a server-side
session with attributes across HTTP requests. The WebSession
abstraction can be accessed via WebServerExchange from a WebFilter or
the target WebHandler.
The session sub-package contains additional abstractions for creating
and managing sessions providing a basis for extensibility (e.g. Spring
Session). Those include WebSessionManager, SessionIdStrategy, and
SessionStore along with a cookie-based session id strategy and an
in-memory session store in use by default.
Note that the current API does not provide a way to invalidate or
re-create the session from server side code.
setComplete replaces writeHeaders as a more general lifecycle method
to perform any kind of handling at the end of request processing, for
example to ensure headers are written if not already.
beforeCommit provides an extension point for an action to be invoked
just before the response is committed, e.g. adding headers/cookies.
Added DataBuffer and DataBufferAllocator, and provided a default NIO
ByteBuffer-based implementation of those, as well as a Netty
ByteBuf-based version.
Since the build has been upgraded to Gradle 2.10, it's showing the
following message:
"The 'sonar-runner' plugin has been deprecated and is scheduled to be
removed in Gradle 3.0. please use the official plugin from SonarQube"
This commit makes use of the "org.sonarqube" Gradle plugin and uprgrades
the Jacoco agent version to 0.7.5.
See: https://sonar.spring.io/updatecenter/updates
See: https://jira.sonarsource.com/browse/SONARJAVA-1091
Closes gh-949
This is in line with the current behavior of HttpServlet that would
have been in used with dispatchOptionsRequest on the DispatcherSerlvet
set to false (the default prior to 4.3).
Issue: SPR-13130
The WebContentGenerator now maintains an additional property that
sub-classes can use for an "Allow" header in response to an HTTP
OPTIONS request. This property is pre-initialized once at startup
and does not have to rely on getSupportedMethods in addition to
adding HTTP OPTIONS if not explicitly listed.
Issue: SPR-13130
AbstractJackson2HttpMessageConverter now implements its own
TypeVariable resolution algorithm since in Jackson 2.7 it is now
deprecated and has not the same behavior .
See https://github.com/FasterXML/jackson-databind/issues/1087
for more details.
The dependency on jackson-datatype-jdk7 has been removed since
it is now provided by default in the jackson-databind module.
Issues: SPR-13483, SPR-13728
This commit updates the javadoc of
`RequestMappingHanderAdapter.setCacheSecondsForSessionAttributeHandlers`
to explain how one can disable that feature and prevent "Cache-Control"
directives from being added when `@SessionAttributes` annotations are
used on Controllers.
Issue: SPR-13598
Prior to this change, configuring a `FixedVersionStrategy` like so
would configure a single "/js/**" path pattern:
```
versionResourceResolver.addFixedVersionStrategy("v1.0.0","/js/**");
```
This commit makes sure that for each path pattern, its prefixed version
is added to the map. For example, the previous configuration also
adds "/v1.0.0/js/**".
Issue: SPR-13883
Prior to this change, the `RequestMappingHandlerAdapter` would first add
a "Cache-Control" HTTP header to the response (depending on its
`WebContentGenerator` configuration and `@SessionAttributes` on the
handler class); then, the Adapter would delegate the actual handler the
processing of the request.
This leads to issues, as the handler does not have full control to the
response and has to deal with pre-existing headers in the response. This
means that the Adapter and the handler can add incompatible
Cache-Control directives without knowing it, since one cannot see the
headers added by the other until the response is committed.
This commit switches the order of execution: first, the handler is
called (possibly adding HTTP headers), then the RMHA processes the
response and adds "Cache-Control" directives *only if there's no
Cache-Control header already defined*.
Issue: SPR-13867
This change exposes protected methods for instantiating sub-classes of
RequestMappingHandlerAdapter and ExceptonHandlerExceptionResolver
similar to the existing method for RequestMappingHandlerMapping.
Prior to this change SpEL did not have an syntactic
construct enabling easy access to a FactoryBean. With this
change it is now possible to use &foo in an expression when
the factory bean should be returned.
Issue: SPR-9511
Spring MVC Test now parses application/x-www-form-urlencoded request
content and populates request parameters from it.
This can be useful when running client-side tests against a MockMvc
via MockMvcClientHttpRequestFactory.
Issue: SPR-13733
Prior to this change, the `ResourceUrlEncodingFilter` would try to
lookup resources URLs as soon as the given URL would be longer than the
expected context+servlet prefix path. This can lead to
OutOfBoundsExceptions when the provided URL does not start with that
prefix and still has the required length.
This commit makes sure that all candidate URLs for resources lookup are
prefixed with the cached servlet and context path. This underlines the
fact that the `ResourceUrlEncodingFilter` does not support relative URLs
for now and delegates to the native servlet implementation in that case.
Issue: SPR-13861
Prior to this commit, Spring MVC Test only supported HTTP methods GET,
POST, HEAD, OPTIONS, PUT, PATCH, DELETE, TRACE and multipart file
upload. This change adds generic methods to MockMvcRequestBuilders in
order to allow testing of arbitrary HTTP methods in a Spring MVC
application.
Issue: SPR-13719
This commit allows to create a Quartz trigger implementation via
either `CronTriggerFactoryBean` or `SimpleTriggerFactoryBean` even if no
job detail is provided.
Issue: SPR-13604
Previously, if a database needs to be initialized with several scripts
and many (or all) use a custom separator, said separator must be repeated
for each script.
This commit introduces a `separator` property at the parent element level
that can be used to customize the default separator. This is available
for both the `initialize-database` and `embedded-database` elements.
Issue: SPR-13792
Support of @JsonView on @JmsListener annotated method that uses the
jackson converter. Also update MappingJackson2MessageConverter to offer
a public API to set the JSON view to use to serialize a payload.
Issue: SPR-13237
This change updates all cases where callbacks are invoked to catch and
suppress errors (since there is not match to do with and error from
a callback be it success or failure).
Also updated is the contract itself to clarify this and emphasize the
callbacks are really notifications for the outcome of the
ListenableFuture not the callbacks themselves.
Issue: SPR-13785
Before this change AsyncRestTemplate had two anonymous implementations
of ListenableFuture that were adapting the result. Those have been
replaces with ListenableFutureAdapter.
This commit is preparation for SPR-13785.
Previously, any `javax.jms.Message` was converted eagerly to the Message
abstraction. This leads to unnecessary conversion if the Payload is not
requested by the underlying method (i.e. if the `javax.jms.Message` is
injected directly).
This commit returns a `Message` implementation that holds the
`javax.jms.Message` and lazily resolve the payload or the headers on
demand (that is the first time they are requested).
Issue: SPR-13777
Before this change use of ExceptionHandlingWebHandler did ensure no
error signals are allowed to escape (hence relying on runtime
behavior).
This change ensures the same is done even when
ExceptionHandlingWebHandler is not configured for use, at the lowest
level which is the WebToHttpHandlerAdapter.
When decoding buffers as plain strings, the StringDecoder returns a
Publisher that may produce one or more `onNext` events.
This is perfectly valid, but leads to errors when trying to convert the
resulting Publisher into a `reactor.Mono` or `rx.Single`.
If the original Publisher emits 2 or more `onNext` signals,
converting to:
* `rx.Single` will throw an error saying that the underlying Observable
"emitted too many elements"
* `reactor.Mono` may contain only the first emitted element
This commit adds a `AbstractRawByteStreamDecoder` that takes a
`SubscriberBarrier` to apply splitting/aggregation operations on the
received elements.
The `StringDecoder` class now inherits from this abstract class and
uses one of the provided `SubscriberBarrier` implementations to
buffer all received elements in a single buffer.
Before this commit, a handler method returning a stream with a JSON
content-type was producing a JSON object for single element streams
or a JSON array for multiple elements streams.
This kind of dynamic change of the output based on the number of
elements was difficult to handle on client side and not consistent
with Spring MVC behavior.
With this commit, we achieve a more consistent behavior by using
the Mono semantics to control this behavior. Mono (and Promise/Single)
are serialized to JSON object and Flux (and Observable/Stream) are
serialized to JSON array.
HttpCookie is now immutable with factory methods to create a client
cookie (name-value) vs a server cookie (name-value + attributes)
including a builder for the latter.
This commit brings back the writeHeaders method on ServerHttpResponse
that was once added (2a6a4f) and then removed (9c7151).
This version is a little simpler since writeHeaders doesn't explicitly
flush/send headers which runtimes are expected to do by default.
Instead the main purpose of writeHeaders now is to ensure changes made
via HttpHeaders are applied to the underlying runtime response at some
point and we now do that once at the very end.
This approach provides the most flexibility (vs keeping HttpHeaders in
sync) because it allows a full and consistent set of mutative
operations for both headers and cookies (to be added) regardless of the
API exposed by the underlying runtime.
This change adds a WebServerExchange and updates all contracts at the
the same level (i.e. org.springframework.web.server) as well as the
org.springframework.web.reactive level to use it so that all
framework-related code will have access to server-side processing
features such as request attributes (and others to come).
This change separates out lower-level HTTP adapter code from the more
(framework-specific) HTTP processing into a separate package under
org.springframework.web.server (not under org.springframework.http).
Flux and Mono are used both for implementation and exposed at API
level to express 1 versus N semantic and to provide default Rx
operators:
- Flux<T> for multiple values Publisher (issue #48)
- Mono<T> for single value Publisher (issue #50)
- Mono<Void> for Publisher with no value (issue #49)
Prior to this change, a resource handler chain configured with a
`VersionResourceResolver` would add the resource version to the request
attributes when serving that resource. This approach would not work when
a `CachingResourceResolver` is configured and the resource is already
cached. Indeed, that code path is not executed when the resource is
resolved from the cache.
This commit adds a new `VersionedResource` interface that's used by the
`VersionResourceResolver`, adding a `getVersion()` method that returns
the version string for that resource. This way, the version information
is cached with the resource itself and the request attributes are no
longer used for this.
Issue: SPR-13817
For those runtimes that don't directly support Reacitve Streams this
commit separates more formally Reactive Streams bridge code out of
the request and response implementations which become simple adapters
to the ServerHttpRequest/Response contracts like their RxNetty and
Reactor Net counterparts.
ServerHttpResponse implementations now immediately propagate
HttpHeaders changes as they so there is no need to call applyHeaders().
The writeHeaders from ServerHttpResponse is also removed. RxNetty and
Reactor Net both support implicitly completing if the handler
completes without explicitly writing the headers or the response body.
Since ListenableFuture callbacks are invoked after the future is set,
we cannot rely on callbacks having taken place right after a call
to future.get(). This change adds a CountdownLatch to detect when
the callbacks were invoked.
Issue: SPR-12538
AsyncRequestExecution now properly supports decoration of the
request (URI, HTTP method, and headers).
Removed a no-op IdentityListenableFutureAdapter.
Use Spring Framework coding style.
Issue: SPR-12538
ConcurrentMapCacheManager and ConcurrentMapCache now support the
serialization of cache entries via a new `storeByValue` attribute. If it is
explicitly enabled, the cache value is first serialized and that content
is stored in the cache.
The net result is that any further change made on the object returned
from the annotated method is not applied on the copy held in the cache.
Issue: SPR-13758
Previously, if a `@Cacheable` method was accessed with the same key by
multiple threads, the underlying method was invoked several times instead
of blocking the threads while the value is computed. This scenario
typically affects users that enable caching to avoid calling a costly
method too often. When said method can be invoked by an arbitrary number
of clients on startup, caching has close to no effect.
This commit adds a new method on `Cache` that implements the read-through
pattern:
```
<T> T get(Object key, Callable<T> valueLoader);
```
If an entry for a given key is not found, the specified `Callable` is
invoked to "load" the value and cache it before returning it to the
caller. Because the entire operation is managed by the underlying cache
provider, it is much more easier to guarantee that the loader (e.g. the
annotated method) will be called only once in case of concurrent access.
A new `sync` attribute to the `@Cacheable` annotation has been addded.
When this flag is enabled, the caching abstraction invokes the new
`Cache` method define above. This new mode bring a set of limitations:
* It can't be combined with other cache operations
* Only one `@Cacheable` operation can be specified
* Only one cache is allowed
* `condition` and `unless` attribute are not supported
The rationale behind those limitations is that the underlying Cache is
taking care of the actual caching operation so we can't really apply
any SpEL or multiple caches handling there.
Issue: SPR-9254
Previously, if a managed bean had only one non-default constructor, we
should still annotate it with `@Autowired` to properly use constructor
injection. Not doing so resulted in an error as the container was
trying to call the default (non-existing) constructor.
This commit updates this behaviour to automatically applyed the
autowiring semantic to any bean that has only one constructor. As
before, if more than one constructor is defined, `@Autowired` must be
specified to teach the container the constructor it has to use.
Issue: SPR-12278
In several places in the spring-webmvc module, URL patterns / objects
relationships are kept in `HashMap`s. When matching with actual URLs,
the algorithm uses a pattern comparator to sort the matching patterns
and select the most specific. But the underlying collection
implementation does not keep the original order which can lead to
inconsistencies.
This commit changes the underlying collection implementation to
`LinkedHashmap`s, in order to keep the insert order if the comparator
does not reorder entries.
Issue: SPR-13798
The DispatcherHandler now has an errorMapper property that is a
function for transforming errors. By default this property is set to an
instance of DispatcherHandlerExceptionMapper which wraps "standard"
framework exceptions and @ResponseStatus-annotated exceptions as
ResponseStatusException.
This makes it easy to handle the exceptions downstream uniformly.
This change adds a ResponseStatusException to associate an exception
with a status code at runtime. Along with that is an
ResponseStatusExceptionHandler that handles ResponseStatusException
by setting the response status.
Before this change the compilation of a method reference or property/field
access was not properly cleaning up the stack if compilation meant
calling a static method or accessing a static field. In these cases there
is no need for a target object on the stack and it should be removed if
present. For a simple expression it is harmless since the end result of
the expression is the thing on the top of the stack, but for nested
expressions if the inner expression suffered this issue, the outer
expression can find itself operating on the wrong element.
The particular issue covered the case of a static field access but this
fix (and associated tests) cover static method, property and field access.
Issue: SPR-13781
JIRA: https://jira.spring.io/browse/SPR-13784
JDK8 and Apache Commons Codec support the RFC 4648
"URL and Filename Safe" Base64 alphabet.
Add methods to `Base64Utils` to support this feature.
General improvements e.g. make use of Java 8 Stream. The main reason
for the refactoring however to tighten error handling. To that extent:
InvocableHandlerMethod turns all exceptions into Reactive Streams
error signals, in effect never allowing any Exceptions to bubble up.
HandlerMethodArgumentResolver may throw an Exception for sync resolution
or produce an error signal via the returned Publisher. Either way the
exception is consistently wrapped with helpful method argument details.
For the latter case using a custom mapError operator.
HandlerMethodArgumentResolver no longer needs to return Optional for
nullable argument values. Instead (for now) the defaultIfEmpty operator
of reactor.rx.Stream operator is used to ensure a default constant value
(called "NO_VALUE") is produced. That way an argument resolver may
produce 0..1 values where 0 means it did not resolve to any value and
that results in null passed as the argument value.
If a HandlerMethodArgumentResolver produces more than one value, all
additional values beyond the first one will be ignored with the help
of a custom "first" operator.
As HandlerMethod is invoked within the map operator, checked exceptions
are not allowed but instead of wrapping it in a runtime exception what
we really need is to unwrap the target exception for exception
resolution purposes. To this end concatMap is used to produce a nested
Publisher or an error Publisher with the unwrapped target exception.
Related to that InvocableHandlerMethod now returns
Publisher<HandlerResult> instead of Publisher<Object> so that no longer
needs to be externally mapped from Object to HandlerResult.
InvocableHandlerMethodTests provides tests for the above scenarios and
verifies the details of resulting error signals.
This change also removes reactor-stream variants of the request and
response since the request and response aren't used directly by
application code and get passed through reactor.Publishers anyway.
Fixed a bug where the URL content negotiation "format" parameter values
were case sensitive and only lowercase values were accepted. For
example, URL query parameter format=json returned the appropriate JSON
response but format=JSON resulted in a
HttpMediaTypeNotAcceptableException and returned:
406 - The resource identified by this request is only capable of
generating responses with characteristics not acceptable according to
the request "accept" headers.
When the MappingMediaTypeFileExtensionResolver is constructed, it is
passed a map containing the media type key to MediaType mappings
defined in the ContentNegotiationConfigurer. In the constructor of
MappingMediaTypeFileExtensionResolver, the keys are converted to
lowercase and the mappings of keys to MediaTypes are added to the
ConcurrentMap<String, MediaType> mediaTypes using the lowercase
version of the keys. However, when retrieving the MediaType from a key
in the lookupMediaType method, no conversion to lowercase is performed
so any value for the URL "format" parameter other than the lowercase
version will not return the proper MediaType result.
On May 1st, 2014, a change was made to
ParameterContentNegotiationStrategy to handle cases where the content
negotiation format URL parameter does not result in a match for a
MediaType. If no match is found, a HttpMediaTypeNotAcceptableException
is thrown resulting in the 406 response above. Prior to this commit, a
null was returned instead of throwing an exception so this issue was
hidden and appeared to function correctly.
To make the media type lookup case insensitive, added a line to the
lookupMediaType method in MediaTypeFileExtensionResolver to first
convert the extension (media type key) to lowercase prior to attempting
to retrieve it from the mediaTypes map.
Issue: SPR-13747
This commit reworks the arrangement to a centralized cache, avoiding any extra reflection attempts if a cache entry is known already. In the course of this, it also enforces toXXX methods to be declared as non-static now (which is the only sensible arrangement anyway).
Issue: SPR-13703
Prior to this change, the resource handling FixedVersionStrategy would
be applied on all links that match the configured pattern. This is
problematic for relative links and can lead to rewritten links such as
"/fixedversion/../css/main.css" which breaks.
This commit prevents that Strategy from being applied to such links.
Of course, one should avoid to use that VersionStrategy with relative
links, but this change aims at not breaking existing links even if it
means not prefixing the version as expected.
Issue: SPR-13727
The recent commit 971f04 replaced the use of a NAMES_PATTERN regex in
favor of direct parsing in order to deal with nested curly braces.
The change also incorrectly replicated this logic which removes a
trailing slash after Pattern quoting (and not before):
https://github.com/spring-projects/spring-framework/blob/cca037a74df9b87f99858154b47696a9eccf69c8/spring-web/src/main/java/org/springframework/web/util/UriTemplate.java#L207-L210
After some more investigation there doesn't appear to be any scenario
where the quoted pattern would end with a trailing slash. It should
always end with \E (end of quote) or a ")" (end of group). Nor are
there any failing tests so this commit removes the logic altogether.
Issue: SPR-13705
This commit refines getMergedBeanDefinition's scope adaptation algorithm for inner beans, never leaving a custom scope within a containing bean of a different scope. The inner bean's scope will either be aligned with the containing bean's scope (matching the effective state) or be switched to prototype in case of an outer singleton (indicating that no singleton state management is desired).
Issue: SPR-13739
Also switches 4.2.4's new formatter implementations to package visibility, just in case they'll be superseded by another variant in the future.
Issue: SPR-13730
When the plus operator is used between strings in a SpEL
expression and that expression is compiled, it is
important to include a cast if computation of any of
the operands isn't obviously leaving strings on the
stack. Likewise if the stack contents are known to
be strings, a cast should not be included.
Issue: SPR-12426
Prior to this commit, range requests would be served by
ResourceHttpRequestHandler by partially reading the inputstream of
static resources. In case of resources contained in ZIP/JAR containers,
InputStreams may not fill the entire read buffer when calling
`inputStream.read(byte[])`. This was the case when using Spring Boot's
ZipInflaterInputStream - this would then not read the entire file
content and would close the response without writing the expected body
length indicated in the "Content-Length" header.
This commit makes sure that the whole resource is read.
Issue: SPR-13661
This is needed in order to be able to use Spring Reactive in standalone
applications. These are temporary classes that will return in
src/test/java when Spring Boot support for Reactive applications will
be implemented.
Prior to this commit, when adding a ShallowEtagHeaderFilter to an
application, the ServletResponse would be wrapped by a
ContentCachingResponseWrapper. When any part of the Spring
infrastructure calls `flushBuffer` on the wrapped response, the call is
delegated to the actual response, which is committed. It's not possible
to alter the response (headers, content) anymore - the ETag filter can't
act.
This change prevents the `flushBuffer` call to be delegated and only
commits the underlying response once the cached content is copied to the
actual response stream.
Issue: SPR-13717
With this change the MapAccessor now extends CompilablePropertyAccessor
rather than just PropertyAccessor. This means that any expression that
ends up using the MapAccessor is now compilable for fast performance.
Issue: SPR-13638
reactive.codec -> core.codec
reactive.io -> util
These may very well not be the final locations. For now they simply
express that there are classes that belong somewhere in core, i.e.
they are lower level dependencies than web.
RequestMappingHandlerMapping currently picks the first match and does
have logic to deal with selecting the best match. This caused a
random test failure depending on which controller method was matched
first. This change removes the test.
The web related code is now under org.springframework.web.reactive.
This is parallel to org.springframework.web (the top-level package of
spring-webmvc).
This change allows to be able to check generic type on the return value
at HandlerAdapter and ResultHandler level. For example, it allows to do
a Publisher<Void> check in SimpleHandlerResultHandler.
"Content-Type" is just a single MediaType.
For the response, the MediaType must be fully selected before
selecting and encoder.
The ResponseBodyResultHandler now includes actual content negotiation
with a potential 406 response.
This commit introduces the following changes:
- MessageToByteEncoder/Decoder renamed to Encoder/Decoder
- JsonObjectEncoder/Decoder are now used directly in
JacksonJsonEncoder/Decoder
- Codec uses MimeType instead of MediaType since they
are not specific to HTTP
- Default MimeType are now managed thanks to
Encoder/Decoder#getSupportedMimeTypes()
- AbstractEncoder/Decoder takes care of generic MimeType related behavior
Even though the JSR-107 spec forbids to store null values, our cache
abstraction allows that behaviour with a special handled (and this is
the default behaviour).
While this was working fine with our own set of annotations, the
JSR-107 interceptor counterpart was interpreting the spec sensu strictu.
We now allow for that special case as well.
Issue: SPR-13641
This commit expands the range of whitelisted extensions by checking
if an extension can be resolved to image/*, audo/*, video/*, as well
as any content type that ends with +xml.
Issue: SPR-13643
Prior to this change, the HttpEntityMethodProcessor would try to process
conditional requests that are undefined by the spec, such as:
* an HTTP GET request with "If-None-Match:*"
* a request with both "If-None-Match" and "If-Match"
* a request with both "If-None-Match" and "If-Unmodified-Since"
This commit skips the processing of those requests as conditional
requests and continues with normal request handling.
Issue: SPR-13626
The URI template is now manually parsed vs using a regex to extract
URI variable names and to create a pattern for matching to actual URLs.
This provides more control to deal with nested curly braces.
Issue: SPR-13627
The goal is to avoid String name comparisons in favor of annotation type identity checks wherever possible. Also, we avoid double getDeclaredAnnotations/getAnnotations checks on anything other than Classes now, since we'd just get the same result in a fresh array.
Issue: SPR-13621
Improve the performance of the `getMergedAnnotationAttributes` and
`isAnnotated` methods in `AnnotatedElementUtils` by returning
immediately when the element had no annotations.
Issue: SPR-13621
Add new MediaType.APPLICATION_JSON_UTF8 and
MediaType.APPLICATION_JSON_UTF8_VALUE constants for
"application/json;charset=UTF-8" content type in order to make it
easier to override @RequestMapping "produces" attribute without
losing the default JSON charset (UTF-8).
Issue: SPR-13600
Refine the approach of having <mvc:view-resolvers> detect and use the
ContentNegotiationManager instance registered with
<mvc:annotation-driven> introduced in the last commit.
Issue: SPR-13559
The <mvc:annotation-driven> element now adds an alias when a
ContentNegotiationManager bean is registered with a custom name.
This helps <mvc:view-resolvers> to more reliably find such a custom
ContentNegotiationManager.
Issue: SPR-13559
Prior to this change, serving resources with ResourceHttpRequestHandler
could result in NPE when requesting an existing folder located in a JAR.
This commit swallows those exceptions, as it is not possible to foresee
those cases without reading the actual resource. This result in a HTTP
200 response with a zero Content-Length instead of a HTTP 500 internal
exception.
Issue: SPR-13620
This commit introduces the following changes:
- Publisher -> Observable/Stream/etc. conversion is now managed
in a dedicated ConversionService instead of directly in
RequestBodyArgumentResolver and ResponseBodyResultHandler
- More isolated logic that decides if the stream should be
serialized as a JSON array or not
- Publisher<ByteBuffer> are now handled by regular
ByteBufferEncoder and ByteBufferDecoder
- Handle Publisher<Void> return value properly
- Ensure that the headers are properly written even for response
without body
- Improve JsonObjectEncoder to autodetect JSON arrays
Previously, the only way to add the collection converters to a registry
was to add *all* default converters. A new "addCollectionConverters"
public method is now available to only register them.
Issue: SPR-13618
When the cacheLimit is reached and there is an eviction from the
updateCache, the accessCache is now also updated.
This change also ensures that adding a destination to the cache is
protected with synchronization on the updateCache.
Issue: SPR-13555
As of Tyrus 1.9, `TyrusEndpointWrapper`'s constructor has a new Boolean
argument (which is mandatory).
This commit reflectively chooses the right constructor method for Tyrus
1.9+ versions.
Issue: SPR-13566
This commit removes duplicate slashes in the resolved lookup path when
calling `UrlPathHelper.getLookupPathForRequest`. This is especially
necessary when the path is cleaned from semicolon content and leaves
duplicate slashes in the request path.
Issue: SPR-13455
Replace Streams fail, empty and Stream map with Publishers.error, empty and map.
Replace Streams calls by Publishers.flatMap, just and Publishers.from
Precise cancel and size to toReadQueue to simulate Promise
Update build
The inner MimeTypeResolver class is no longer necessary in the
MockServletContext since the Java Activation Framework (JAF) is a
standard part of Java SE since Java 6.
Prior to this commit, HtmlUnitRequestBuilder stored empty query
parameters declared without an equals sign as null (i.e., query
parameters such as 'error' in 'http://example.com/login?error').
This commit addresses this issue by ensuring that
HtmlUnitRequestBuilder treats all empty query parameter values as empty
strings. Consequently, query strings such as '?error' and '?error=' now
both result in 'error' being stored as an empty string.
Issue: SPR-13524
This commit updates HandlerAdapter#handle() to return HandlerResult
instead of Publisher<HandlerResult>. A new SimpleHandlerResultHandler
class has been introduced for handlers returning Publisher<Void>.
The Javadoc wrongly referred to a behaviour that is not (and should not
be) implemented. List items are split into indexed keys and the
comma-separated value is not retained.
Issues: SPR-13257
We can't compile directly against NettyClientSocketOptions method which
changed signatures in 2.0.6. This change ensures the method is invoked
reflectively instead.
Prior to this commit, HtmlUnitRequestBuilder would incorrectly attempt
to decode null values for query parameters (i.e., query parameters such
as 'error' in 'http://example.com/login?error') which resulted in a
NullPointerException since URLDecoder.decode() does not support null
values.
This commit fixes this issue by ensuring that HtmlUnitRequestBuilder
only attempts to decode non-null query parameter values.
Issue: SPR-13524
SpringJUnit4ClassRunner, SpringClassRule, and SpringMethodRule now
throw an IllegalStateException with a meaningful message if JUnit 4.9
is not present in the classpath (specifically if
org.junit.runners.model.MultipleFailureException cannot be loaded).
Issue: SPR-13521
This commit adds support for origins with a trailing slash or a path,
in order to avoid printing a stacktrace in the logs when
WebUtils#isSameOrigin(HttpRequest) parses such invalid Origin header
value.
Issue: SPR-13478
This commit migrates all remaining tests from JUnit 3 to JUnit 4, with
the exception of Spring's legacy JUnit 3.8 based testing framework that
is still in use in the spring-orm module.
Issue: SPR-13514
This commit introduces a new ScriptRenderException in order to:
- Print in the resulting error page the reason of the script failure
- Not print the whole stacktrace in the logs
The ScriptRenderException thrown in ScriptTemplateView#renderMergedOutputModel()
is wrapped into a ServletException in order to avoid printing 2 times the messages in
the logs (throwing directly a ScriptRenderException would make it wrapped in a
NestedServletException that contains a getMessage() override not needed in this
context)
Issue: SPR-13488
ResponseBodyEmitter now registers by default to receive callbacks
on timeout/completion and sets its internal "complete" flag to true
in order to prevent proactively further use of the emitter.
Issue: SPR-13498
Prior to this commit, HttpEntityMethodProcessor would process
conditional requests even if those aren't GET requests.
This is an issue for POST requests with "If-None-Match: *" headers and
many other use cases, which should not receive an HTTP 304 Not Modified
status in response.
This commit only triggers ETag/Last-Modified conditional requests bits
for GET requests.
Issue: SPR-13496
As of Undertow 1.3.0, several APIs have been changed: replacing Xnio's
Pool/Pooled references to Undertow's new ByteBufferPool abstraction.
This move has been made, as part of
https://issues.jboss.org/browse/UNDERTOW-522, to prepare deprecations in
the Xnio API.
This commit adds a new strategy to deal with both 1.0-1.2 and 1.3
Undertow generations.
Issue: SPR-13366
The MockHttpServletRequestBuilder now uses java.net.URI internally
rather than UriComponents.
This means that for the MockMvcRequestBuilders method variants that
accept a java.net.URI we can use it as is. The difference is almost
none but it does mean that you can create a URI with double slashes
(for testing purposes) and have it remain that way.
Issue: SPR-13435
Some converters (Jackson, Gson, Protobuf) already do this. It is now
also done in AbstractMessageConverterMethodArgumentResolver which
enforces a consistent behavior across controller method arguments.
Issue: SPR-12745
Also revised StandardScriptFactory for finer-grained template methods, added further configuration variants to StandardScriptEvaluator, and identified thread-local ScriptEngine instances in ScriptTemplateView by appropriate key.
Issue: SPR-13491
Issue: SPR-13487
This commit makes ThreadLocal<ScriptEngine> engineHolder ScriptTemplateView
field static in order to limit the maximum number of ScriptEngine instances
to the number of threads, regardless of the number of view instances.
Issue: SPR-13487
This commit introduces ignored, failing tests that demonstrate that the
@Cache* annotations are not yet supported as merged composed annotations.
Issue: SPR-13475
This commit introduces support for attribute overrides for
@ResponseStatus when @ResponseStatus is used as a meta-annotation on
a custom composed annotation.
Specifically, this commit migrates all code that looks up
@ResponseStatus from using AnnotationUtils.findAnnotation() to using
AnnotatedElementUtils.findMergedAnnotation().
Issue: SPR-13441
This commit adds support for Publisher based codecs that allows to convert
byte stream to object stream and vice & versa.
Jackson, JAXB2 and String codec implementations are provided.
After this change, with Nashorn it is possible to use either
render(template, model) or render(template, model, url).
With JRuby or Jython, specifying the 3 parameters is mandatory.
Issue: SPR-13453
This change adds a new `getDateHeader` method that converts date header
Strings to long values - making tests more readable.
This feature is also documented in the "what's new section" for 4.2.
Prior to this commit, requests with an empty body and no Content-Type
header set would fail with a HttpMediaTypeNotSupportedException when
mapped to a Controller method argument annotated with
@RequestBody(required=false).
In those cases, the server implementation considers with an
"application/octet-stream" content type and polls messageconverters for
conversion. If no messageconverter is able to process this request, a
HttpMediaTypeNotSupportedException is thrown.
This change makes sure that such exceptions are not thrown if the
incoming request has:
* no body
* no content-type header
In this case, a null value is returned.
Issue: SPR-13147
Includes a revision for consistent and defensive Servlet 3.0 method calls across Spring's web abstraction (in particular, also working in debug mode where method references may get resolved early, so ternary expressions are to be avoided).
Issue: SPR-13420
This commit improves the documentation in the reference manual for the
HtmlUnit & Selenium WebDriver integration in the Spring MVC Test
framework by mentioning the group and artifact IDs required for this
functionality.
Issue: SPR-13299
This commit picks up where 3eacb837c2
(SPR-13345) left off by adding support for transitive implicit aliases
configured via @AliasFor.
Issue: SPR-13405
Spring Framework 4.2 introduced support for aliases between annotation
attributes that fall into the following two categories.
1) Alias pairs: two attributes in the same annotation that use
@AliasFor to declare that they are explicit aliases for each other.
2) Meta-annotation attribute overrides: an attribute in one annotation
uses @AliasFor to declare that it is an explicit override of an
attribute in a meta-annotation.
However, the existing functionality fails to support the case where two
attributes in the same annotation both use @AliasFor to declare that
they are both explicit overrides of the same attribute in the same
meta-annotation. In such scenarios, one would intuitively assume that
two such attributes would be treated as "implicit" aliases for each
other, analogous to the existing support for explicit alias pairs.
Furthermore, an annotation may potentially declare multiple aliases
that are effectively a set of implicit aliases for each other.
This commit introduces support for implicit aliases configured via
@AliasFor through an extensive overhaul of the support for alias
lookups, validation, etc. Specifically, this commit includes the
following.
- Introduced isAnnotationMetaPresent() in AnnotationUtils.
- Introduced private AliasDescriptor class in AnnotationUtils in order
to encapsulate the parsing, validation, and comparison of both
explicit and implicit aliases configured via @AliasFor.
- Switched from single values for alias names to lists of alias names.
- Renamed getAliasedAttributeName() to getAliasedAttributeNames() in
AnnotationUtils.
- Converted alias map to contain lists of aliases in AnnotationUtils.
- Refactored the following to support multiple implicit aliases:
getRequiredAttributeWithAlias() in AnnotationAttributes,
AbstractAliasAwareAnnotationAttributeExtractor,
MapAnnotationAttributeExtractor, MergedAnnotationAttributesProcessor
in AnnotatedElementUtils, and postProcessAnnotationAttributes() in
AnnotationUtils.
- Introduced numerous tests for implicit alias support, including
AbstractAliasAwareAnnotationAttributeExtractorTestCase,
DefaultAnnotationAttributeExtractorTests, and
MapAnnotationAttributeExtractorTests.
- Updated Javadoc in @AliasFor regarding implicit aliases and in
AnnotationUtils regarding "meta-present".
Issue: SPR-13345
Prior to this commit, ServletWebRequest would call
HttpServletResponse.getStatus(), which is a Servlet 3.x method.
This commit checks if this method is available before calling it, thus
keeping Servlet 2.5 compatibility.
Issue: SPR-13396
Related to that, HibernateTransactionManager specifically checks for active physical connections on reset as of Hibernate 5.
Issue: SPR-13269
Issue: SPR-13002
Xnio 3.4.0 will introduce a new source of ByteBuffers: ByteBufferPool.
Previously this feature was offered by Pooled/Pool/ByteBufferSlicePool;
those classes are now marked as deprecated.
As of 1.3.0.Beta9, Undertow still implements the following method in its
ClientConnection interface, using those deprecated types:
Pool<ByteBuffer> getBufferPool();
This commit prepares compatibility by suppressing warnings in order to
avoid build failures in our build. Once appropriate changes are made in
Undertow, a specific implementation with new types could be introduced.
Issue: SPR-13366
Before this commit UriComponents was capable of expanding URI vars that
may have contained a regular expressions (as supported with
@RequestMapping for example). However if the regular expressions
contained any nested "{}" the expand did not work correctly.
This commit sanitizes a URI template source removing any content
between nested "{}" prior to expanding. This works since we only care
about the URI variable name.
Issue: SPR-13311
Just enough for a test with an @ResponseBody method that accepts an
@RequestParam String arg and returning Publisher<String> or String.
See RequestMappingIntegrationTests.
Prior to this change, VersionResourceResolver and VersionStrategy would
resolve static resources using version strings. They assist
ResourceHttpRequestHandler with serving static resources. The
RequestHandler itself can be configured with HTTP caching strategies to
set Cache-Control headers.
In order to have a complete strategy with Cache-Control and ETag
response headers, developers can't reuse that version string information
and have to rely on other mechanisms (like ShallowEtagHeaderFilter).
This commit makes VersionResourceResolver use that version string to set
it as a request attribute, which will be used by the
ResourceHttpRequestHandler to write an ETag response header.
Issue: SPR-13382
Prior to this change, ResourceUrlEncodingFilter and ResourceUrlProvider
would try to resolve the resource path using the full request URL (i.e.
request path and request parameters), whereas the request path is the
only information to consider.
This would lead to StringIndexOutOfBoundsExceptions when the path +
request params information was given to the AntPathMatcher.
This commit makes the appropriate change to both
ResourceUrlEncodingFilter and ResourceUrlProvider, in order to only
select the request path.
Issue: SPR-13374
This commit introduces the following changes:
- Content type can now be properly configured
- Default content type is "text/html"
- Content type and charset are now properly set in the response
Issue: SPR-13379
This commit adds support for simple URL handler mapping (exact path
match) and an adapter for the HttpHandler interface to be used to
handle the request.
The SimpleUrlHandlerMappingIntegrationTests then maps the URLs
"/foo" and "/bar" to two different handlers.
This is a refactoring of the existing "echo" integration test with the
goal to make it easier to add further integration tests.
The HttpServer abstraction is on the test source side for now.
Introduce http and dispatch packages under org.springframework.web to
separate HTTP-specific adapter code from higher level web framework
code. Move classes into their respective locations.
Prior to this change, trying to set an unquoted ETag with
`ResponseEntity`'s API would throw an `IllegalArgumentException`.
This commit automatically quotes ETag values set using ResponseEntity.
Issue: SPR-13378
In an attempt to make our Jetty-based integration tests more robust,
this commit discontinues use of SocketUtils for picking a random,
available port and instead lets the Jetty Server pick its own port.
The StompSubProtcolHandler now checks the outcome of the send to the
inbound client channel. If the message was prevented from being sent,
e.g. as part of authorization, events are not published
Issue: SPR-13339
Before this commit RequestPartServletServerHttpRequest simply did an
instanceof check for MultipartHttpServletRequest. That hasn't failed
because request wrapping typically happens in filters before the
DispatcherServlet calls the MultipartResolver.
With Spring MVC Test and the Spring Security integraiton however,
this order is reversed since there we prepare the multipart request
upfront, i.e. there is no actual parsing.
The commit unwraps the request if necessary.
Issue: SPR-13317
Prior to this commit, EmbeddedDatabaseFactory logged the name of an
embedded database just before it was created; however, the name alone
is not sufficient for connecting to the database via external tools
such as the H2 Web Console.
This commit updates EmbeddedDatabaseFactory to make it easier to
connect to embedded databases via external tools by logging the
complete connection URL for an embedded database as it's being created.
In addition, EmbeddedDatabaseFactory now logs when an embedded database
is being shut down.
Issue: SPR-13370
Instead of having to use the default constructor then calling
setObjectMapper(ObjectMapper), these constructors allow
MappingJackson2JsonView and MappingJackson2XmlView to be created and
configured with the desired object mapper in one step.
HandlerMapping, HandlerAdapter, HandlerResultHandler (+ HandlerResult)
as the basic request handling contracts. DispatcherHandler to drive
overall request handling.
DispatcherApp provides minimal implementations of the above contracts
enough to put together a running example that returns
200 text/plain "Hello world".
This commit introduces new `isEmpty()` and `isNotEmpty()` methods in
`JsonPathResultMatchers` and `JsonPathRequestMatchers` which delegate
to the new `assertValueIsEmpty()` and `assertValueIsNotEmpty()` methods
in `JsonPathExpectationsHelper`, respectively.
Issue: SPR-13352
Commit fffdd1e9e9 introduced additional
JsonPath result matchers in JsonPathResultMatchers for server-side
testing of MVC controllers.
This commit introduces comparable methods in JsonPathRequestMatchers
for client-side testing with a RestTemplate.
- isString()
- isBoolean()
- isNumber()
- isMap()
Issue: SPR-13320
Prior to this commit, the exists() method in JsonPathExpectationsHelper
correctly asserted that the evaluated JsonPath expression resulted in a
value (i.e., that a non-null value exists); however, if the value was
an empty array, the exists() method always threw an AssertionError.
The existing behavior makes sense if the JsonPath expression is
'indefinite' -- for example, if the expression uses a filter to select
results based on a predicate for which there is no match in the JSON
document, but the existing behavior is illogical and therefore invalid
if the JsonPath expression is 'definite' (i.e., directly references an
array in the JSON document that exists but happens to be empty). For
example, prior to this commit, the following threw an AssertionError.
new JsonPathExpectationsHelper("$.arr").exists("{ 'arr': [] }");
Similar arguments can be made for the doesNotExist() method.
After thorough analysis of the status quo, it has become apparent that
the existing specialized treatment of arrays is a result of the fact
that the JsonPath library always returns an empty list if the path is
an 'indefinite' path that does not evaluate to a specific result.
Consult the discussion on "What is Returned When?" in the JsonPath
documentation for details:
https://github.com/jayway/JsonPath#what-is-returned-when
This commit addresses these issues by ensuring that empty arrays are
considered existent if the JsonPath expression is definite but
nonexistent if the expression is indefinite.
Issue: SPR-13351
Prior to this commit, a JsonPath assertion that a path expression
evaluated to an array in JsonPathExpectationsHelper (and therefore
indirectly in JsonPathResultMatchers in Spring MVC Test) would
incorrectly fail if the array was present in the JSON content but empty.
This commit fixes this issue by removing the "not empty" check for
arrays and lists.
Issue: SPR-13320
SocketUtils is used to find available ports on localhost; however,
prior to this commit, SocketUtils incorrectly reported a port as
available on localhost if another process was already bound to
localhost on the given port but not to other network interfaces. In
other words, SocketUtils determined that a given port was available for
some interface though not necessarily for the loopback interface.
This commit addresses this issue by refactoring SocketUtils so that it
tests the loopback interface to ensure that the port is actually
available for localhost.
Issue: SPR-13321
This commit introduces an additional test case to ensure that explicit
local attribute aliases (configured via @AliasFor) do not accidentally
override attributes of the same names in meta-annotations (i.e., by
convention).
Issue: SPR-13325
This commit adds RxNetty integration that includes RxNetty-based
implementations of ServerHttpRequest and ServerHttpResponse as well as
an adapter from the RxNetty RequestHandler to the HttpHandler contracts.
Only byte[] is supported at the moment for reading and writing with a
corresponding copy to and from Netty ByteBuf.
This commit introduces HTTP request and response abstractions along
with Servlet-based implementations similar to the ones in the http
package of spring-web but using Reactive Streams.
In turn HttpHandler now accepts the request and response types and
returns Publisher<Void> that reflects the end of handling.
The write method on the response also returns Publisher<Void> allowing
deferred writing. At the moment however the underlying Servlet 3.1
support only supports a single publisher after which the connection
is closed.
Only simple byte[] is supported for reading and writing.
Prior to this commit, attempting to synthesize an annotation from a map
of annotation attributes that contained nested maps instead of nested
annotations would result in an exception.
This commit addresses this issue by properly synthesizing nested maps
and nested arrays of maps into nested annotations and nested arrays of
annotations, respectively.
Issue: SPR-13338
It is a configuration error if an alias is declared via @AliasFor for
an attribute in a meta-annotation and the meta-annotation is not
meta-present. However, prior to this commit, the support for validating
the configuration of @AliasFor in AnnotationUtils currently silently
ignored such errors.
This commit fixes this by throwing an AnnotationConfigurationException
whenever a required meta-annotation is not present or meta-present on
an annotation that declares an explicit alias for an attribute in the
meta-annotation.
Issue: SPR-13335
For Tomcat, failures occur if HttpHandlerServlet buffer size is
significantly less than the Tomcat input buffer size.
Also on command line Jetty tests fail with port unavailable unless
the server from the Tomcat tests is also destroyed.
Prior to this commit, MockHttpServletRequestBuilder always supplied an
array of cookies to the MockHttpServletRequest that it built, even if
the array was empty.
However, this violates the contract of HttpServletRequest. According to
the Servlet API, the getCookies() method "returns null if no cookies
were sent."
This commit ensures that MockHttpServletRequestBuilder no longer
configures an empty array of cookies in the mock request that it builds.
Issue: SPR-13314
This commit introduces the following methods in JsonPathResultMatchers
in the Spring MVC Test framework.
- isString()
- isBoolean()
- isNumber()
- isMap()
In addition, this commit overhauls the Javadoc in
JsonPathResultMatchers and JsonPathExpectationsHelper.
Issue: SPR-13320
This commit aims to improve the space and time performance of
NumberUtils by invoking valueOf() factory methods instead of the
corresponding constructors when converting a number to a target class.
Prior to this commit, an explicit override for an attribute in a
meta-annotation configured via @AliasFor could potentially result in an
incorrect override of an attribute of the same name but in the wrong
meta-annotation.
This commit fixes the algorithm in getAliasedAttributeName(Method,
Class) in AnnotationUtils by ensuring that an explicit attribute
override is only applied to the configured target meta-annotation
(i.e., configured via the 'annotation' attribute in @AliasFor).
Issue: SPR-13325
This change ensures that an onError outcome from an async request is
also routed to onCompletion handlers registered with
StandardServletAsyncWebRequest.
Issue: SPR-13292
Prior to this commit, the `ResponseStatusExceptionResolver` would use:
* `HttpServletResponse.sendError` if both a status and a reason are set
on the `@ResponseStatus` annotation
* `HttpServletResponse.setStatus` if only a status is set on the
`@ResponseStatus` annotation
This is actually a change of behavior, since this Resolver was using
`sendError` in all cases previously.
Because this change can create issues such as
https://github.com/spring-projects/spring-boot/issues/3623
this commit rollbacks those changes and clarifies the behavior on the
javadoc of the annotation itself.
Issue: SPR-11193, SPR-13226
SPR-11512 introduced support for annotation attribute aliases via
@AliasFor, requiring the explicit declaration of the 'attribute'
attribute. However, for aliases within an annotation, this explicit
declaration is unnecessary.
This commit improves the readability of alias pairs declared within an
annotation by introducing a 'value' attribute in @AliasFor that is an
alias for the existing 'attribute' attribute. This allows annotations
such as @ContextConfiguration from the spring-test module to declare
aliases as follows.
public @interface ContextConfiguration {
@AliasFor("locations")
String[] value() default {};
@AliasFor("value")
String[] locations() default {};
// ...
}
Issue: SPR-13289
Before this change, XhrTransport implementations had to be configured
with the headers to use for HTTP requests other than the initial
handshake.
After this change the handshake headers passed to SockJsClient by
default are used for all other HTTP requests related to the SockJS
connection (e.g. info request, xhr send/receive). A property on
SockJsClient allows restricting the headers to use for other HTTP
requests to a subset of the handshake headers.
Issue: SPR-13254
This commit fixes numerous references to 'legacy' packages within the
Javadoc for the Spring MVC Test framework.
In addition, this commit improves examples in Javadoc, adds links to
related classes where appropriate, and removes unnecessary imports for
types that are only referenced within documentation.
Issue: SPR-13284
This commit introduces a dedicated build() method in
MockMvcHtmlUnitDriverBuilder to replace createDriver(). In addition,
the configureDriver() method has been renamed to withDelegate() and now
returns the builder for further customization.
This commit also overhauls the Javadoc for static factory methods and
the class-level Javadoc in MockMvcHtmlUnitDriverBuilder for greater
clarity to end users.
Issues SPR-13158
This commit introduces a dedicated build() method in
MockMvcWebClientBuilder to replace createWebClient(). In addition, the
configureWebClient() method has been renamed to withDelegate() and now
returns the builder for further customization.
This commit also overhauls the constructor and class-level Javadoc in
MockMvcWebClientBuilder for greater clarity to end users.
Issues SPR-13158
This commit renames the configureWebClient() method in
WebConnectionHtmlUnitDriver to modifyWebClientInternal() in order to
better convey the relationship to HtmlUnitDriver#modifyWebClient().
Issues SPR-13158
Some of the HtmlUnit Tests required an internet connection. This
caused failures when running offline.
This commit adds Assume PERFORMANCE to those tests so they are
only ran when the PERFORMANCE group is selected.
Issue: SPR-13158
* SPR-13158:
Polish MockMvc HtmlUnit Support
Ensure spring-test builds against HttpComponents 4.5
Upgrade to HtmlUnit 2.18 GA
Mention HtmlUnit support in the What's New section
Introduce support for HtmlUnit in Spring MVC Test
This commit introduces integration between MockMvc and HtmlUnit, thus
simplifying end-to-end testing when using HTML-based views and enabling
developers to do the following.
- Easily test HTML pages using tools such as HtmlUnit, WebDriver, & Geb
without the need to deploy to a Servlet container
- Test JavaScript within pages
- Optionally test using mock services to speed up testing
- Share logic between in-container, end-to-end tests and
out-of-container integration tests
Issue: SPR-13158
Since @TransactionConfiguration is now deprecated, this commit also
deprecates TransactionConfigurationAttributes with the intention of
completely removing TransactionConfigurationAttributes once
@TransactionConfiguration has been removed.
Issue: SPR-13277
Due to common usage of @Rollback(false), this commit introduces a new
@Commit annotation that more clearly conveys the intent of the code
while retaining the run-time semantics.
@Commit is in fact meta-annotated with @Rollback(false).
Issue: SPR-13279
Since Spring Framework 2.5, @Rollback has been supported on test
methods, with class-level rollback settings configured via
@TransactionConfiguration; however, allowing @Rollback to be declared
on test classes with method-level declarations overriding class-level
declarations would prove more intuitive than having to declare both
@TransactionConfiguration and @Rollback. Furthermore, the
transactionManager flag in @TransactionConfiguration was made
superfluous many years ago with the introduction of support for a
qualifier in @Transactional.
This commit enables @Rollback to be declared at the class level for
default rollback semantics within test class hierarchies and deprecates
@TransactionConfiguration in favor of @Rollback and @Transactional
qualifiers.
Issue: SPR-13276, SPR-13277
AbstractMessageConverter provides overloaded methods with a conversion hint, MappingJackson2MessageConverter takes that hint into account, and SimpMessagingTemplate transformes such a hint in the given headers map into an explicit argument invocation argument.
Issue: SPR-13265
Prior to this change, calling the `setDateHeader` method on a
Spring Test MockHttpServletResponse instance would just store the given
long value in a Map, not writing it as a formatted date String.
Also, calling `getDateHeader` on a MockHttpServletRequest would not
support date strings and could not parse those values.
This can be problematic when testing features related to date headers
such as "Expires", "If-Modified-Since", "Last-Modified", etc.
This commit adds formatting and parsing capabilities to Servlet Mocks
for date strings in HTTP headers.
When formatting dates to Strings, the date format used is the one
preferred by the HTTP RFC. When parsing date Strings, multiple date
formats are supported for better compatibility.
Issue: SPR-11912
SPR-13211 introduced support for reusing mock requests in Spring MVC
Test if the request was created by the the Spring TestContext
Framework. Unfortunately, that change makes it impossible for
MockMvc.perform() to be invoked multiple times within the same test
method without side effects. For example, session attributes and
request parameters are transparently and unexpectedly retained for
subsequent invocations of perform(), causing certain categories of
tests to fail.
This commit reverts the changes introduced in SPR-13211 and introduces
a new MockMvcReuseTests class to serve as regression tests within
Spring's test suite.
Issue: SPR-13260, SPR-13211
HTTP headers such as "Expires", "Last-Modified" all use date
strings like "Tue, 21 Jul 2015 10:00:00 GMT". Prior to this commit,
there was no way to match those header values, besides formatting dates
manually.
This commit introduces a new HeaderResultMatcher to test those date
headers using a long timestamp:
```
this.mockMvc.perform(get("/persons/1").header("If-Modified-Since", now))
.andExpect(status().isNotModified())
.andExpect(header().dateValue("Last-Modified", timestamp));
```
Issue: SPR-13263
Prior to this change, calling the `setDateHeader` method on a
MockHttpServletResponse instance (internal implementation for testing
the spring-web module) would just store the given long value in a Map,
not writing it as a formatted date String.
This can be problematic when testing features related to date headers
such as "Expires", "If-Modified-Since", "Last-Modified", etc.
This commit formats long dates into date Strings using the date format
recommended by the RFC and the GMT time zone.
As filter-based libraries and projects (such as Spring Security) may
use the "Pragma" header in HTTP responses, WebContentGenerator should
make sure that such headers are overwritten to avoid clashes with
the HTTP caching headers set by the HTTP caching configuration.
Issue: SPR-13252
Prior to this commit, the Spring MVC Test Framework always created a
new MockHttpServletRequest, disregarding any mock request already
present in Spring Web's RequestContextHolder -- for example, one
created by the ServletTestExecutionListener in the Spring TestContext
Framework (TCF).
This commit modifies MockHttpServletRequestBuilder so that it reuses a
mock request created by the TCF. However,
MockMultipartHttpServletRequestBuilder continues to always create a new
MockMultipartHttpServletRequest since a MockHttpServletRequest created
by the TCF is not directly compatible with a
MockMultipartHttpServletRequest. Furthermore, in order to avoid
unforeseen side effects, MockHttpServletRequestBuilder will always
create a new MockHttpServletRequest if a mock request is present in the
RequestContextHolder but not created by the TCF.
Issue: SPR-13211
When resolving resources, the PathResourceResolver creates a Resource
instance and checks whether this resource `exists()` and `isReadable()`.
While that last call returns false for folders on the file system, both
calls return true for folders located inside JARs.
If a JAR location is configured as a resource location, then
PathResourceResolver can resolve folders in JARs as valid locations and
candidates for paths resolution.
Prior to this change, the PathResourceResolver would resolve "" as a
valid resource path (here, the "/META-INF/resources/webjars" if
configured, for example) and return a "" path for this resource,
effectively turning all "/" URLs into empty ones "".
This commit fixes the resolveUrlPathInternal implementation by not
allowing empty paths as valid resource paths.
Issue: SPR-13241
This commit adds a new sharedEngine property to ScriptTemplateConfigurer
and ScriptTemplateView in order to support non thread-safe ScriptEngine
implementations like Nashorn.
When this flag is set to false, the engine is retrieved from a
ThreadLocal<ScriptEngine> field instead of a ScriptEngine one.
Also as part of this commit, all the initialization logic has been moved from
ScriptTemplateConfigurer to ScriptTemplateView since the script engine can
now be lazily initialized multiple time in the view when sharedEngine is
set to false.
Issue: SPR-13034
Some databases such as Oracle permit double quoted column aliases that
contain case-sensitive characters, single quotes, and other special
characters; however, prior to this commit, SqlScripts interpreted a
single quote nested within double quotes as the start of a string
literal resulting in improper parsing.
This commit addresses this issue by ensuring that double quoted strings
such as column aliases are properly parsed even when containing single
quotes.
Issue: SPR-13218
When using an Apache Http components based infrastructure, a null header
value is handled as the empty string. The exact same infrastructure using
HttpURLConnection generates a header with no colon. This is actually not
proper HTTP and some components fail to read such request.
We now make sure to call HttpURLConnection#addRequestProperty with the
empty String for a null header value.
Issue: SPR-13225
Browsers like Chrome or Safari include an Origin header for same-origin
POST/PUT/DELETE requests, not only for cross-origin requests.
Before this commit, these same-origin requests would have been detected
as potential cross-origin requests, and rejected if the same-origin domain
is not part of the configured allowedOrigins.
This commit avoid to reject same-origin requests by reusing the logic
introduced in Spring 4.1 for detecting reliably Websocket/SockJS
same-origin requests with the WebUtils.isValidOrigin() method. This
logic has been extracted in a new WebUtils.isSameOrigin() method.
Issue: SPR-13206
When using the Spring TestContext Framework (TCF) to load a
WebApplicationContext and the Spring MVC Test Framework (MockMvc) to
test a controller, two instances of MockHttpServletRequest will be
created. Due to an ordering issue with regard to population of the
RequestAttributes, it is therefore possible that a filter accesses the
mocked request managed by the TCF, while the controller accesses the
mocked request managed by MockMvc, and this leads to test failures if
the controller expects data from the filter to be present in the
request.
This commit fixes this bug by ensuring that the RequestAttributes
backed by the mocked request managed by MockMvc are stored in the
RequestContextHolder before any filters are invoked by MockMvc.
Issue: SPR-13217
This commit introduces the following changes:
- The new CorsConfigurationMapping class allows to share the mapped
CorsConfiguration logic between AbstractHandlerMapping and CorsFilter
- In AbstractHandlerMapping, the Map<String, CorsConfiguration>
corsConfiguration property has been renamed to corsConfigurations
- CorsFilter allows to process CORS requests at filter level, using any
CorsConfigurationSource implementation (for example
CorsConfigurationMapping)
Issue: SPR-13192
By default, RedirectViews have http10Compatible set to true, which means
that they use HTTP 302 as a default HTTP response status. Setting this
property to false make RedirectViews use HTTP 303 by default.
Now when set to false, RedirectViews also don't use the
RESPONSE_STATUS_ATTRIBUTE request attribute as a response HTTP if it is
available.
This commit makes both configuration choices behave the same regarding
this request attribute: use it as a response status if it's available.
Issue: SPR-13208
In addition to specifying the event type to listen to via a method
parameter, any @EventListener annotated method can now alternatively
define the event type(s) to listen to via the "classes" attributes (that
is aliased to "value").
Something like
@EventListener({FooEvent.class, BarEvent.class})
public void handleFooBar() { .... }
Issue: SPR-13156
As of SPR-11792, WebContentGenerator and WebContentInterceptor offer
new APIs and new behavior regarding HTTP caching, including the use of a
new CacheControl class.
Those changes broke part of the behavior in WebContentInterceptor. This
class allows to override the global Cache configuration at the Generator
level, using specific mappings. Prior to this change, those mappings
would not properly apply the HTTP caching configuration when using
deprecated configuration settings in WebContentGenerator.
This change fixes those backwards compatibility issues for
WebContentInterceptor users.
Issue: SPR-13207
This commit adds additional tests to RequestContextHolderTests that
verify proper support for the MockHttpServletRequest managed by Spring
MVC Test in the following scenarios:
- request-scoped service invoked by controller
- session-scoped service invoked by controller
- custom filter that sets request attributes
Issue: SPR-13211
Conversion and validation documentation related to Spring MVC is now
consolidated in the Spring MVC chapter with references to and from
the Validation and Data Binding chapter.
Examples have been updated to include MVC Java config as well.
When using Appache Commons FileUpload, multi parts with binary data
(i.e. that are not actual files) are saved and then accessed as
String request parameters.
Before this change however the RequestPartServletServerHttpRequest
used a fixed encoding (UTF-8) while the parsing code in
CommonsFileUploadSupport/Resolver used the encoding from the
content-type header, or the request, or the FileUpload component.
This change does a best effort to determine the encoding of the
request parameter using a similar algorithm as the parsing side
that should work the same unless the encoding comes from the
FileUpload component which is not accessible.
Issue: SPR-13096
Add section on Spring MVC TEst vs full integation testing and provide
reference to Spring Boot's @WebIntegrationTest as an alternative.
Issue: SPR-13169
After SPR-12884 (4.2 RC1) introduced support for a selector header
expression on SUBSCRIBE frames, messages from the destination cache
are further filtered based on the selector expression. While adding a
test to find subscriptions at the same time as unsubscribing, a
potential NPE was exposed. This commit fixes the NPE.
Issue: SPR-13204
Before this change <websocket:decorator-factory> decorated to
the SubProtocolWebSocketHandler RootBeanDefinition rather than
using a RuntimeBeanReference, which led to a separate instance
of SubProtocolWebSocketHandler to be created.
Issue: SPR-13190
SPR-12429 introduced various `BEFORE_*` modes in `@DirtiesContext`. To
support these new modes, `DirtiesContextTestExecutionListener` (DCTEL)
was updated to support both `BEFORE_*` and `AFTER_*` modes. However,
there is a problem with having DCTEL support `BEFORE_*` modes since it
is typically configured to execute after the
`DependencyInjectionTestExecutionListener` (DITEL), and this leads to
several undesired side effects:
- The test's `ApplicationContext` is closed by DCTEL *after*
dependencies have been injected into the test instance.
- Injected dependencies may therefore attempt to interact with an
`ApplicationContext` that is no longer _active_.
- If a test has its `ApplicationContext` injected as a dependency,
interaction with the context will likely fail since the context has
been closed.
- Any `TestExecutionListeners` registered after DCTEL will get a _new_
`ApplicationContext` if they invoke `getApplicationContext()` on the
`TestContext`.
This commit fixes these issues by introducing a new
`DirtiesContextBeforeModesTestExecutionListener` (DCBMTEL) that is
registered by default before DITEL. The previous support for `BEFORE_*`
modes has been moved from DCTEL to DCBMTEL. In addition, an
`AbstractDirtiesContextTestExecutionListener` has been extracted from
DCTEL in order to avoid code duplication.
Issue: SPR-13180
This commit moves the check whether an HTTP method supports request
body up to the base class so that all sub-classes can benefit (not just
@RequestBody).
Issue: SPR-13176
Since the changes introduced in SPR-12778, some `@RequestBody` args
would not be properly processed in some cases:
* requests with an empty body
* no Content-Type header defined
This typically happens when GET requests are mapped on a handler dealing
with POST requests and HTTP bodies.
This change makes sure that the `RequestResponseBodyMethodProcessor` is
only involved for requests that:
* have a Content-Type defined
* OR are HTTP requests eligible for an HTTP body (PUT, POST, PATCH)
Issue: SPR-13176
Fixesspring-projects/spring-boot#3313
Beginning with Java 6, the JavaBeans Activation Framework (JAF) is part
of the JDK. Thus, there is no longer a need to explicitly include a
dependency on `activation.jar` when using Spring's email support in
Spring Framework 4.0 and higher which anyway requires Java 6 or higher.
This commit therefore removes the JAF requirement from the reference
manual.
This split avoids a package tangle (between core and core.annotation) and also allows for selective use of raw annotation exposure versus synthesized annotations, with the latter primarily applicable to web and message handler processing at this point.
Issue: SPR-13153
Prior to this commit, `HttpEntityMethodProcessor` would rely on
`ServletWebRequest` to process conditional requests and with incoming
`"If-Modified-Since"` / `"If-None-Match"` request headers.
This approach is problematic since in that class:
* response is wrapped in a `ServletServerHttpResponse`
* this wrapped response does not write response headers right away
* `ServletWebRequest.checkNotModified` methods can't apply their
logic with incomplete response headers
This solution adds some minimal code duplication and applies
the conditional request logic within the Processor.
A possible alternative would be to improve the
`ServletServerHttpResponse$ServletResponseHttpHeaders` implementation
with write methods - but this solution would only work for Servlet 3.x
applications.
Issue: SPR-13090
Prior to this commit, the Spring MVC Test framework only provided
support for printing debug information about the MvcResult to STDOUT.
This commit introduces support for logging `MvcResult` details at
`DEBUG` level via the Apache Commons Logging API. In addition, this
commit introduces additional `print(..)` variants for printing debug
information to custom output streams and writers.
Specifically, `MockMvcResultHandlers` has been augmented with the
following new static methods:
- `log()`
- `print(OutputStream)`
- `print(Writer)`
Issue: SPR-13171
Prior to this commit, when rendering cookies via `andDo(print())` in
Spring MVC Test, the output for the `MockHttpServletResponse` would
look something like the following:
Cookies = [javax.servlet.http.Cookie@25084a1e]
The reason is that the Cookie class in javax.servlet-api-3.0.1.jar does
not implement toString(). Consequently, nothing about the cookie's
name, value, etc., is displayed, thereby making the debug output for
cookies next to useless.
This commit improves on this by implementing custom toString() logic
for cookies in debug output in Spring MVC Test. For example, the output
now looks like this (without the newlines):
Cookies = [[Cookie@47faa49c name = 'enigma', value = '42', \\
comment = [null], domain = [null], maxAge = -1, \\
path = [null], secure = false, version = 0, \\
httpOnly = false]]
In addition, this commit fixes a minor bug for FlashMap debug output if
the FlashMap is empty.
Issue: SPR-13168
Add a section on Groovy Markup Template support and
reorder sections in the View Technologies chapter, to have in order:
* Thymeleaf
* Groovy Markup Template
* Velocity and Freemarker
* JSPs
* Script Templates
* other views...
Issue: SPR-12829
This commit introduces the following changes:
- In AbstractMessageConverterMethodProcessor, the type aware variant of
canWrite() is now called when the converter implements
GenericHttpMessageConverter.
- The Javadoc has been updated in GenericHttpMessageConverter to make it clear
that the type aware canRead() and canWrite() methods should perform the same
checks than non type aware ones.
- AbstractGenericHttpMessageConverter now implements default type aware
canRead() and canWrite() methods than just call the non type aware variants.
Due to this, if subclasses just override the non type aware variants,
they still have the right behavior.
Issue: SPR-13161
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
Prior to this change, `XpathResultMatchers` and more generally the
`MockHttpServletResponse` would default to ISO-8859-1 encoding even when
it's not supposed to. The Servlet/HTTP specs mention this encoding
for all `text/*` mime types when decoding bodies to Strings, but this
issue is about XML Parsers.
XML Parsers should use the encoding:
* defined in the `Content-Type` response header (if available)
* written in the XML declaration of the document
* "guessed" by a built-in auto-detection mechanism
This commit changes the following:
* XPathMatchers now feed the XML parser with byte arrays instead of
decoded Strings
* the response should be written to `MockHttpServletResponse` using
its OutputStream, and not a PrintWriter which defaults to ISO-8859-1
Issue: SPR-12676
This commit improves SPR-13090 and avoids adding duplicate ETag and
Last-Modified headers in HTTP responses.
Previously, those were added twice to the response since:
* we're adding all ResponseEntity headers to the response
* the `checkNotModified` methods automatically add those headers
Issue: SPR-13090
Add JmsResponse that can be used as return type of any JMS listener
method to indicate not only the response but also the actual destination
to which the reply should be sent.
Issue: SPR-13133
Before this change HandlerMethodReturnValueHandler's were invoked in a
specific order (type-based, annotation-based, custom). However handlers
that deal with asynchronous return value handling need to always be
considered first. This affects custom handlers in particular since they
are normally ordered last.
This change introduces an AsyncHandlerMethodReturnValueHandler
sub-interface with a single method to determine if the return value is
asynchronous and if it is to look for a matching handler only among
those that are of type AsyncHandlerMethodReturnValueHandler.
Issue: SPR-13083
This commit introduces the following changes in AbstractHandlerExceptionResolver:
- warnLogger used to log exception is enabled by default
- the exception message is now logged instead of the whole exception stacktrace
- warn logging is only performed if doResolveException() returns a non-null
ModelAndView, in order to avoid logging multiple times the error
Issue: SPR-13100
Before this change a missing path variable value resulted in a 400
error where in fact the error is due to a mismatch between the
declared @PathVariable and the URI template, i.e. a 500 error.
This change introduced a MissingPathVariableException as a sub-class
of ServletRequestBindingException (the exception previously thrown)
and results in a response status code of 500 by default.
Issue: SPR-13121
Ever since @ActiveProfiles was introduced, the declared active profiles
for integration tests have been sorted in order to support unique cache
key generation; however, there are use cases for which the original
ordering should be retained.
For example, Spring Boot's ConfigFileApplicationListener loads
configuration files for active profiles in the order returned by
Environment.getActiveProfiles(), with the assumption that the ordering
matches the order in which the developer declared the active profiles.
This commit maintains the uniqueness of active profiles declared via
@ActiveProfiles but no longer sorts them.
Issue: SPR-12492
In AnnotatedElementUtils, all methods pertaining to merging annotation
attributes have been renamed to "getMerged*()" and "findMerged*()"
accordingly. Existing methods such as getAnnotationAttributes(..) have
been deprecated in favor of the more descriptive "merged" variants.
This aligns the naming conventions in AnnotatedElementUtils with those
already present in AnnotationReadingVisitorUtils.
The use of "annotationType" as a variable name for the fully qualified
class name of an annotation type has been replaced with
"annotationName" in order to improve the readability and intent of the
code base.
In MetaAnnotationUtils.AnnotationDescriptor, getMergedAnnotation() has
been renamed to synthesizeAnnotation(), and the method is now
overridden in UntypedAnnotationDescriptor to always throw an
UnsupportedOperationException in order to avoid potential run-time
ClassCastExceptions.
Issue: SPR-11511
Prior to this commit, there existed several isEmpty() methods scattered
across various utilities such as ObjectUtils, CollectionUtils, and
StringUtils; however, each of these methods requires a cast to the type
supported for that particular variant.
This commit introduces a general-purpose isEmpty(Object) method in
ObjectUtils that transparently supports multiple object types in a
central location without the need for casts or juggling multiple
utility classes.
Issue: SPR-13119
The modifications to DefaultMockMvcBuilder performed in conjunction
with SPR-12553 introduced a breaking change: the WebApplicationContext
supplied to DefaultMockMvcBuilder's constructor was *always* stored in
the ServletContext as the root WebApplicationContext, overwriting a
root WebApplicationContext that had been set by the user or by the
Spring TestContext Framework (TCF) -- for example, in
AbstractGenericWebContextLoader. Consequently, the changes in SPR-12553
cause tests that use @ContextHierarchy to fail if web components rely
on the correct WebApplicationContext being stored under the
WebApplicationContext#ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE key.
This commit reverts the breaking changes introduced in SPR-12553: if
the root WebApplicationContext has already been set in the
ServletContext of the WebApplicationContext supplied to
DefaultMockMvcBuilder, no action is taken.
Furthermore, this commit introduces new code to address the initial
intent of SPR-12553. Specifically, if the root WebApplicationContext
has NOT been set in the ServletContext of the WebApplicationContext
supplied to DefaultMockMvcBuilder, the application context hierarchy
will be traversed in search of the root WebApplicationContext, and the
root WebApplicationContext will then be stored under the
ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE key.
Issue: SPR-13075, SPR-12553
Prior to this change, the `"Last-Modified"` and "`Etag`" support had
been improved with SPR-11324: HTTP response headers are now
automatically added for conditional requests and more.
This commit fixes the format of the "`Last-Modified`" and "`ETag`"
values, which were using an epoch timestamp rather than an HTTP-date
format defined in RFC 7231 section 7.1.1.1.
Also, Conditional responses are only applied when the given response
applies, i.e. when it has an compatible HTTP status (2xx).
Issue: SPR-13090
This commit introduces support for RFC 7239: Forwarded HTTP Extension in
the UriComponentsBuilder. Unfortunately, RFC 7239 is not a complete
replacement for the X-Forwarded-* headers: specifically, there is not
direct replacement for X-Forwarded-Port. The JIRA contains more
information.
Issue: SPR-11856
Provide a mean to detect the actual ResolvableType based on a instance as
a counter measure to type erasure.
Upgrade the event infrastructure to detect if the event (or the payload)
implements such interface. When this is the case, the return value of
`getResolvableType` is used to validate its generic type against the
method signature of the listener.
Issue: SPR-13069
This commit introduces the following changes:
- configureCors(CorsConfigurer configurer) is renamed to
addCorsMappings(CorsRegistry registry)
- enableCors(String... pathPatterns) is renamed to
addMapping(String pathPattern)
- <cors /> element must have at least one <mapping /> child
element in order to be consistent with XML based configuration
and have more explicit configuration
Issues: SPR-12933, SPR-13046
While working on SPR-12532, an extra IdentityWrapper was added to work
around a backward compatible issue between commons pool 1.x and 2.x. This
issue (POOL-283) has actually been fixed in 2.4 and their IdentityWrapper
is using object equality so our wrapper is in the way.
Looking retrospectively, the code looks all fine without the workaround
and commons pool 2.4 or later so it has been removed.
Since Spring 4.1, a CacheResolver may be configured to customize the way
the cache(s) to use for a given cache operation are retrieved. Since a
CacheResolver implementation may not use the cache names information at
all, this attribute has been made optional.
However, a fix was still applied, preventing a Cache operation without a
cache name to be defined properly. We now allow this valid use case.
Issue: SPR-13081
This commit introduces support for this kind of CORS XML namespace configuration:
<mvc:cors>
<mvc:mapping path="/api/**"
allowed-origins="http://domain1.com, http://domain2.com"
allowed-methods="GET, PUT"
allowed-headers="header1, header2, header3"
exposed-headers="header1, header2" allow-credentials="false"
max-age="123" />
<mvc:mapping path="/resources/**" allowed-origins="http://domain1.com" />
</mvc:cors>
Issue: SPR-13046
This commit introduces new 'cacheNames' attributes (analogous to the
existing attribute of the same name in @CacheConfig) as aliases for the
'value' attributes in @Cacheable, @CachePut, and @CacheEvict.
In addition, SpringCacheAnnotationParser.getAnnotations() has been
refactored to support synthesized annotations.
Issue: SPR-11393
Prior to this commit, @ComponentScan already had a value/basePackages
alias pair; however, the semantics were not properly enforced.
This commit addresses this issue by refactoring
ComponentScanAnnotationParser to ensure that it is not possible to
declare both of the aliased attributes. In addition, the 'value' and
'basePackages' attributes are now annotated with @AliasFor in order to
make the semantics clearer.
Issue: SPR-11393
This commit introduces a "synthesized annotation" alternative to
getAnnotationAttributes() in AnnotatedElementUtils, analogous to the
recently introduced findAnnotation() methods.
Issue: SPR-13082
Spring Framework 4.2 RC1 introduced support for synthesizing an
annotation from an existing annotation in order to provide additional
functionality above and beyond that provided by Java. Specifically,
such synthesized annotations provide support for @AliasFor semantics.
As luck would have it, the same principle can be used to synthesize an
annotation from any map of attributes, and in particular, from an
instance of AnnotationAttributes.
The following highlight the major changes in this commit toward
achieving this goal.
- Introduced AnnotationAttributeExtractor abstraction and refactored
SynthesizedAnnotationInvocationHandler to delegate to an
AnnotationAttributeExtractor.
- Extracted code from SynthesizedAnnotationInvocationHandler into new
AbstractAliasAwareAnnotationAttributeExtractor and
DefaultAnnotationAttributeExtractor implementation classes.
- Introduced MapAnnotationAttributeExtractor for synthesizing an
annotation that is backed by a map or AnnotationAttributes instance.
- Introduced a variant of synthesizeAnnotation() in AnnotationUtils
that accepts a map.
- Introduced findAnnotation(*) methods in AnnotatedElementUtils that
synthesize merged AnnotationAttributes back into an annotation of the
target type.
The following classes have been refactored to use the new support for
synthesizing AnnotationAttributes back into an annotation.
- ApplicationListenerMethodAdapter
- TestAnnotationUtils
- AbstractTestContextBootstrapper
- ActiveProfilesUtils
- ContextLoaderUtils
- DefaultActiveProfilesResolver
- DirtiesContextTestExecutionListener
- TestPropertySourceAttributes
- TestPropertySourceUtils
- TransactionalTestExecutionListener
- MetaAnnotationUtils
- MvcUriComponentsBuilder
- RequestMappingHandlerMapping
In addition, this commit also includes changes to ensure that arrays
returned by synthesized annotations are properly cloned first.
Issue: SPR-13067
Prior to this commit, when a nested array of annotations was
synthesized while adapting values within an AnnotationAttributes map,
the array was improperly replaced with an array of type Annotation[]
instead of an array of the concrete annotation type, which can lead to
unexpected run-time exceptions.
This commit fixes this bug by replacing annotations in the existing
array with synthesized versions of those annotations, thereby retaining
the original array's component type.
Issue: SPR-13077
This commit introduces support in AnnotationAttributes for retrieving
nested annotations that is on par with the existing type-safe support
for retrieving nested AnnotationAttributes.
Issue: SPR-13074
AnnotationAttributes has existed for several years, but none of the
"get" methods that make up its public API are documented. In many
cases, the behavior can be inferred from the name of the method, but
for some methods there are "hidden gems" and unexpected behavior
lurking behind the scenes.
This commit addresses this issue by documenting all public methods. In
addition, the hidden support for converting single elements into
single-element arrays has also been documented and tested.
Issue: SPR-13072
Reinstate a variant of the `WebContentGenerator.checkAndPrepare` method
for projects that are using it.
This variant is now marked as deprecated.
Issue: SPR-11792
Before this commit the object that #this would refer to in
nested expressions within projection/selection clauses was always
the root context object. This was incorrect as it should be the
element being projected/selected over. This commit introduces
a scope root context object which is set upon entering a new
scope (like when entering a projection or selection). Any
object. With this change this kind of expression now behaves:
where #this is the element of list1. Unqualified references
are also resolved against this scope root context object.
Issues: SPR-10417, SPR-12035, SPR-13055
This commit introduces a test that will fail if SynthesizedAnnotation is
not public as is required by the contract for getProxyClass() in
java.lang.reflect.Proxy.
Issue: SPR-13057
This commit introduces support for asynchronous return values thanks
to the new AsyncHandlerMethodReturnValueHandler interface. Out of
the box support for ListenableFuture is also provided.
Issue: SPR-12168
Commit 3d86f15 added a lot of new feature in AbstractPropertyAccessor
shared by both DirectFieldAccessor and BeanWrapperImpl. This makes this
abstract class harder to implement for others having simpler use cases.
It turns that Spring Data has such use case; this commit split these new
features in a dedicated new base class, leaving AbstractPropertyAccessor
untouched.
Issue: SPR-12805
Enable public visibility on SynthetizedAnnotation to allow annotation
outside its package to be proxied properly. This commit is pending a
unit test that actually reproduces the problem.
Issue: SPR-13057
This commit introduces first-class support for aliases for annotation
attributes. Specifically, this commit introduces a new @AliasFor
annotation that can be used to declare a pair of aliased attributes
within a single annotation or an alias from an attribute in a custom
composed annotation to an attribute in a meta-annotation.
To support @AliasFor within annotation instances, AnnotationUtils has
been overhauled to "synthesize" any annotations returned by "get" and
"find" searches. A SynthesizedAnnotation is an annotation that is
wrapped in a JDK dynamic proxy which provides run-time support for
@AliasFor semantics. SynthesizedAnnotationInvocationHandler is the
actual handler behind the proxy.
In addition, the contract for @AliasFor is fully validated, and an
AnnotationConfigurationException is thrown in case invalid
configuration is detected.
For example, @ContextConfiguration from the spring-test module is now
declared as follows:
public @interface ContextConfiguration {
@AliasFor(attribute = "locations")
String[] value() default {};
@AliasFor(attribute = "value")
String[] locations() default {};
// ...
}
The following annotations and their related support classes have been
modified to use @AliasFor.
- @ManagedResource
- @ContextConfiguration
- @ActiveProfiles
- @TestExecutionListeners
- @TestPropertySource
- @Sql
- @ControllerAdvice
- @RequestMapping
Similarly, support for AnnotationAttributes has been reworked to
support @AliasFor as well. This allows for fine-grained control over
exactly which attributes are overridden within an annotation hierarchy.
In fact, it is now possible to declare an alias for the 'value'
attribute of a meta-annotation.
For example, given the revised declaration of @ContextConfiguration
above, one can now develop a composed annotation with a custom
attribute override as follows.
@ContextConfiguration
public @interface MyTestConfig {
@AliasFor(
annotation = ContextConfiguration.class,
attribute = "locations"
)
String[] xmlFiles();
// ...
}
Consequently, the following are functionally equivalent.
- @MyTestConfig(xmlFiles = "test.xml")
- @ContextConfiguration("test.xml")
- @ContextConfiguration(locations = "test.xml").
Issue: SPR-11512, SPR-11513
Previously, the binding may have to call the getter first to retrieve the
old value of a property before actually setting it. This was guarded by
a catch block that was accidentally removed in 3d86f15
Restore that catch block and add a test to cover it.
Issue: SPR-12805
Prior to this commit, the `ResourceHttpRequestHandler` would not
properly handle HTTP requests to **directories contained in JARs**.
This would result in HTTP 500 errors, caused by `FileNotFoundException`
or `NullPointerException`.
This can be tracked to webapp ClassLoader implementations in servlet
containers:
* in Jetty9x, fetching a directory within a JAR as a `Resource` and
getting its InputStream work fine, but attempting to `close()` it
results in a NullPointerException as the underlying stream is null.
* In Tomcat6x, one cannot fetch an InputStream for the same `Resource`
as it throws a FileNotFoundException.
This change adds more try/catch clauses and catches more Exception so as
to result in HTTP 200 OK responses instead of server errors. While this
is inconsistent because the same code path would result in HTTP 404 with
existing directories on the file system, there's no other simple way to
make those checks for resources contained in JARs.
Issue: SPR-12999
`BeanWrapperImpl` and `DirectFieldAccessor` are two
`ConfigurablePropertyAccessor` implementations with different features
set.
This commit harmonizes the two implementations to use a common base class
that delegates the actual property handling to the sub-classes:
* `BeanWrapperImpl`: `PropertyDescriptor` and introspection utilities
* `DirectFieldAccessor`: reflection on `java.lang.Field`
Issues: SPR-12206 - SPR-12805
Previously, a Bean implementing `AutoCloseable` (or `Closeable`) was
always destroyed regardless of its bean definition. In particular, the
documented way of disabling the destruction callback via an empty String
did not work.
AutoCloseable beans are now treated pretty much as any other bean: we
still use the presence of the interface to optimize the check of a
destroy method and we only auto-discover the method name to invoke if
the inferred mode is enabled.
Issue: SPR-13022
Prior to this commit, WebJars users needed to use versioned links within
templates for WebJars resources, such as `/jquery/1.2.0/jquery.js`.
This can be rather cumbersome when updating libraries - all references
in templates need to be updated.
One could use version-less links in templates, but needed to add a
specific MVC Handler that uses webjars.org's webjar-locator library.
While this approach makes maintaing templates easier, this makes HTTP
caching strategies less optimal.
This commit adds a new WebJarsResourceResolver that search for resources
located in WebJar locations. This ResourceResolver is automatically
registered if the "org.webjars:webjars-locator" dependency is present.
Registering WebJars resource handling can be done like this:
```java
@Override
protected void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/webjars/**")
.addResourceLocations("classpath:META-INF/resources/webjars")
.resourceChain(true)
.addResolver(new WebJarsResourceResolver());
}
```
Issue: SPR-12323
polish
Prior to this commit, registering `HandlerInterceptor`s using the
`InterceptorRegistry` would not guarantee their order of execution. In
fact, `HandlerInterceptor`s would always be executed before
`MappedInterceptor`s.
This change makes `MappedInterceptor` implement the `HandlerInterceptor`
interface, in order to register all interceptors in a single ordered
list. The order of execution of interceptors is now guaranteed in the
`HandlerExecutionChain` built by `AbstractHandlerMapping`.
Issue: SPR-12673
This commit introduces support for OkHttp
(http://square.github.io/okhttp/) as a backing implementation for
ClientHttpRequestFactory and AsyncClientHttpRequestFactory.
Issue: SPR-12893
MvcUriComponentsBuilder::fromMethodCall creates wrong URLs with derived
controller classes. The @RequestMapping of the declaring class of the
method that is called is used instead of the @RequstMapping of the
given controller class.
https://jira.spring.io/browse/SPR-13033
After this change CorsProcessor has a single processRequest method and
it also explicitly deals with a null CorsConfiguration, which for
pre-flight requests results in a rejection while for simple requests
results in no CORS headers added.
The AbstractHandlerMapping now uses a LinkedHashMap to preserve the
order in which global patterns are provided.
In order to simplify configuration of the SpringMethodRule and to ensure
that the correct TestContextManager is always retrieved for the
currently executing test class, this commit introduces a static
TestContextManager cache in SpringClassRule.
In addition, since it is not foreseen that SpringClassRule and
SpringMethodRule should be able to be subclassed, their internal methods
are now private instead of protected.
Issue: SPR-7731
Since Spring Framework 2.5, support for integrating the Spring
TestContext Framework (TCF) into JUnit 4 based tests has been provided
via the SpringJUnit4ClassRunner, but this approach precludes the
ability for tests to be run with alternative runners like JUnit's
Parameterized or third-party runners such as the MockitoJUnitRunner.
This commit remedies this situation by introducing @ClassRule and @Rule
based alternatives to the SpringJUnit4ClassRunner. These rules are
independent of any Runner and can therefore be combined with
alternative runners.
Due to the limitations of JUnit's implementation of rules, as of JUnit
4.12 it is currently impossible to create a single rule that can be
applied both at the class level and at the method level (with access to
the test instance). Consequently, this commit introduces the following
two rules that must be used together.
- SpringClassRule: a JUnit TestRule that provides the class-level
functionality of the TCF to JUnit-based tests
- SpringMethodRule: a JUnit MethodRule that provides the
instance-level and method-level functionality of the TCF to
JUnit-based tests
In addition, this commit also introduces the following new JUnit
Statements for use with rules:
- RunPrepareTestInstanceCallbacks
- ProfileValueChecker
Issue: SPR-7731
This commit adds JavaConfig based global CORS configuration
capabilities to Spring MVC. It is now possible to specify
multiple CORS configurations, each mapped on a path pattern,
by overriding
WebMvcConfigurerAdapter#configureCrossOrigin(CrossOriginConfigurer).
It is also possible to combine global and @CrossOrigin based
CORS configuration.
Issue: SPR-12933
Prior to this commit, the documentation in AnnotationUtils was
inconsistent, and at times even misleading, with regard to finding
annotations that are "present" or "directly present" on annotated
elements.
This commit defines the terminology used within AnnotationUtils and
introduces the explicit notion of "meta-present" to denote that
annotations are present within annotation hierarchies above annotated
elements.
Issue: SPR-13030
This change introduces a strategy for expanding a URI template into a
URI and makes it a property of the RestTemplate and AsyncRestTemplate
so that they can be pre-configured with such a strategy.
The DefaultUriTemplateHandler relies on UriComponentsBuilder internally
and provides functionality equivalent to using the UriTemplate.
A DefaultUriTemplateHandler can also be configured to parse the path
of a URI template into path segments in order to allow expanding URI
variables according to path segment encoding rules.
Issue: SPR-12750
This commit updates code that previously used getAnnotationAttributes()
in AnnotatedElementUtils to use findAnnotationAttributes(), where
appropriate.
Issue: SPR-12738
This commit updates the "get semantics" search algorithm used in
`AnnotatedElementUtils` so that locally declared 'composed annotations'
are favored over inherited annotations.
Specifically, the internal `searchWithGetSemantics()` method now
searches locally declared annotations before searching inherited
annotations.
All TODOs in `AnnotatedElementUtilsTests` have been completed, and all
ignored tests have been reinstated.
Issue: SPR-11598
Prior to this commit, the ResourceUrlEncodingFilter would fail with a
StringIndexOutOfBoundsException when:
* the current request has a servlet context
* the URL to encode is relative and is shorter than the context value
This change defensively checks for those lengths and delegates to the
parent implementation if necessary.
Issue: SPR-13018
This change introduces SimpUserRegistry exposing an API to access
information about connected users, their sessions, and subscriptions
with STOMP/WebSocket messaging. Provides are methods to access users
as well as a method to find subscriptions given a Matcher strategy.
The DefaultSimpUserRegistry implementation is also a
SmartApplicationListener which listesn for ApplicationContext events
when users connect, disconnect, subscribe, and unsubscribe to
destinations.
The MultiServerUserRegistry implementation is a composite that
aggregates user information from the local SimpUserRegistry as well
as snapshots of user on remote application servers.
UserRegistryMessageHandler is used with MultiServerUserRegistry. It
broadcats user registry information through the broker and listens
for similar broadcasts from other servers. This must be enabled
explicitly when configuring the STOMP broker relay.
The existing UserSessionRegistry which was primiarly used internally
to resolve a user name to session id's has been deprecated and is no
longer used. If an application configures a custom UserSessionRegistr
still, it will be adapted accordingly to SimpUserRegistry but the
effect is rather limited (comparable to pre-existing functionality)
and will not work in multi-server scenarios.
Issue: SPR-12029
This commit improves the documentation for AnnotationUtils and
AnnotatedElementUtils by explaining that the scope of most annotation
searches is limited to finding the first such annotation, resulting in
additional such annotations being silently ignored.
Issue: SPR-13015
Spring Framework's build is using a custom MergePlugin in order to merge
a project into another one and share/override configuration and
dependencies.
Prior to this commit, two projects merged into a third one could trigger
dependency conflicts when exporting the project definition into a POM.
When trying to define the scope for a given dependency, those two
projects would compete for this with the same priority, resulting in a
Gradle exception.
One could trigger this issue by running:
./gradlew :spring-orm:install -x javadoc
Because `spring-orm-hibernate4` and `spring-orm-hibernate5` get merged
into `spring-orm` and both define optional/test dependencies to
spring-mvc, etc.
This commit makes sure that two projects, when defining dependency
scopes, don't use the same priority value; the MergePlugin now adds the
index of the current subproject to the priority value. So when two
projects compete for this, the one defined in last will define the
dependency scope.
Issue: SPR-13013
In general, the Spring Framework aims to construct error message
strings only if an actual error has occurred. This seems to be the
common pattern in the codebase and saves both CPU and memory. However,
there are some places where eager error message formatting occurs
unnecessarily.
This commit addresses this issue in the following classes:
AdviceModeImportSelector, AnnotationAttributes, and
ReadOnlySystemAttributesMap.
The change in ReadOnlySystemAttributesMap also avoids a potential
NullPointerException.
Issue: SPR-13007
This commit introduces support in the spring-test module for obtaining a
reference to the underlying target object hidden behind one or more
proxies.
Specifically this commit introduces AopTestUtils with two methods:
- getTargetObject(Object)
- getUltimateTargetObject(Object)
Issue: SPR-13005
Commit 5648fbfc31 introduced a
compile-time dependency on spring-beans-groovy in the spring-context
module which breaks the build on the CI server since the Animal Sniffer
task cannot find a JAR file for spring-beans-groovy.
This commit reverts that change so that the "sniffer" task once again
succeeds.
Prior to this commit, the `getAnnotation()` method in `TypeDescriptor`
only supported a single level of meta-annotations. In other words, the
annotation hierarchy would not be exhaustively searched.
This commit provides support for arbitrary levels of meta-annotations
in `TypeDescriptor` by delegating to `AnnotationUtils.findAnnotation()`
within `TypeDescriptor.getAnnotation()`.
Issue: SPR-12793
Prior to this commit, AntPathMatcher would not correctly combine a path
that ends with a separator with a path that starts with a separator.
For example, `/foo/` + `/bar` combined into `/foo//bar`.
Specifically, this commit:
- Removes the duplicated separator in combined paths
- Improves RequestMappingInfo's toString() representation
- Fixes Javadoc formatting in AntPathMatcher
- Polishes AntPathMatcherTests
- Polishes Javadoc in AbstractRequestCondition
Issue: SPR-12975
This commit introduces a messaging.converter.MessageConverter that
marshals to/from XML using the abstractions provided in the OXM module.
Issue: SPR-12726
Prior to this change, the `UrlTag` would simply append the remote
context and the path value in case of a context relative URL.
The following code snippet would output "//foo":
```
<spring:url value="/foo" context="/" />
```
This change now removes trailing slashes in remote context to avoid
this.
Issue: SPR-12782
Making sure that `GenericApplicationListenerAdapter` implements
`SmartApplicationListener` again as older code may try to cast an
instance to `SmartApplicationListener`.
Issue: SPR-8201
This commit picks up where SPR-11483 left off, with the goal of
eliminating all unnecessary inspection of core JDK annotations in
Spring's annotation search algorithms in AnnotatedElementUtils and
AnnotationMetadataReadingVisitor.
Issue: SPR-12989
- Methods which search for a specific annotation now properly ensure
that the sought annotation was actually found.
- Both the "get" and the "find" search algorithms no longer needlessly
traverse meta-annotation hierarchies twice.
- Both the "get" and the "find" search algorithms now properly
increment the metaDepth when recursively searching within the
meta-annotation hierarchy.
- Redesigned getMetaAnnotationTypes() so that it doesn't needlessly
search irrelevant annotations.
- Documented and tested hasMetaAnnotationTypes().
- Documented isAnnotated().
Issue: SPR-11514
Before this change AbstractHandlerMethodMapping used a map from Method
to CorsConfiguration. That works for regular @RequestMapping methods.
However frameworks like Spring Boot and Spring Integration may
programmatically register the same Method under multiple mappings,
i.e. adapter/gateway type classes.
This change ensures that CorsConfiguraiton is indexed by HandlerMethod
so that we can store CorsConfiguration for different handler instances
even when the method is the same.
In order for to make this work, HandlerMethod now provides an
additional field called resolvedFromHandlerMethod that returns the
original HandlerMethod (with the String bean name). This makes it
possible to perform reliable lookups.
Issue: SPR-11541
This commit introduces failing (but currently disabled) test cases in
HandlerMethodAnnotationDetectionTests that attempt to reproduce the
scenario described in SPR-9517.
See: ParameterizedSubclassDoesNotOverrideConcreteImplementationsFromGenericAbstractSuperclass
Furthermore, this commit also introduces passing tests cases for a
similar scenario. See: ParameterizedSubclassOverridesDefaultMappings
Issue: SPR-9517
Since SPR-10954, the SimpleBrokerMessageHandler supports `heart-beats`.
Even if the STOMP spec states that the `heart-beat` header is OPTIONAL,
and if absent considered as `heart-beat: 0,0`,
some clients rely on this to be set in CONNECTED frames.
This commit adds this header information even if no task
scheduler/heart-beat have been configured.
See: https://stomp.github.io/stomp-specification-1.2.html#Heart-beating
Issue: SPR-10954
Do not refer to deprecated ParameterizedBeanPropertyRowMapper in reference manual
Change to the BeanPropertyRowMapper from the ParameterizedBeanPropertyRowMapper
CorsConfiguration now provides methods to check and determine the
allowed origin, method, and headers according to its own configuration.
This simplifies significantly the work that needs to be done from
DefaultCorsProcessor. However an alternative CorsProcessor can still
access the raw CorsConfiguration and perform its own checks.
Issue: SPR-12885
This commit adds CORS related headers to HttpHeaders
and update DefaultCorsProcessor implementation to
use ServerHttpRequest and ServerHttpResponse instead
of HttpServletRequest and HttpServletResponse. Usage
of ServerHttpResponse allows to avoid using Servlet 3.0
specific methods in order keep CORS support Servlet 2.5
compliant.
Issue: SPR-12885
The change to provide public register/unregister methods in
AbstractHandlerMethodMapping assumed that a single method cannot be
mapped more than once. This is not the case with the MvcEndpoints and
EndpointHandlerMapping from Spring Boot which wrap one or more
non-web Endpoint types with an MvcEndpointAdapter in order to expose
them for use over the web. In effect Spring MVC sees a single handler
method mapped many times.
This change removes that assumption so rather than unregistering with
a HandlerMethod, which is not necessarily unique, the unregister method
now takes the actual mapping, which is the only thing that should actually
be unique.
Issue: SPR-11541
This commit adds additional context to the exception message generated
when two candidate methods are discovered in MvcUriComponentsBuilder's
getMethod(Class<?>, String, Object...).
Issue: SPR-12977
This commit introduces a new fromMethodNameWithBridgedMethod() test in
MvcUriComponentsBuilderTests which is currently disabled via @Ignore
until this bug is resolved.
Issue: SPR-12977
When used in combination with GzipResourceResolver, the
CachingResourceResolver does not properly cache results, since it only
takes the request path as a input for cache key generation.
Here's an example of that behavior:
1. an HTTP client requests a resource with `Accept-Encoding: gzip`, so
the GzipResourceResolver can resolve a gzipped resource.
2. the configured CachingResourceResolver caches that resource.
3. another HTTP client requests the same resource, but it does not
support gzip encoding; the previously cached gzipped resource is still
returned.
This commit uses the presence/absence of gzip encoding support as an
input in cache keys generation.
Issue: SPR-12982
Before this change AbstractHandlerMethodMapping contained multiple
maps all containing different kinds of mapping meta-data. After the
change a MappingDefinitionRegistry inner class encapsulates these
fields along with their initialization code.
Issue: SPR-11541
This commit documents the status quo for the getMetaAnnotationTypes()
method in AnnotatedElementUtils and adds appropriate regression tests to
AnnotatedElementUtilsTests.
In addition, this commit also introduces a SimpleAnnotationProcessor
base class in AnnotatedElementUtils.
Issue: SPR-11514
Prior to this commit it was possible for two @BootstrapWith annotations
to be 'present' on a test class -- for example, via competing custom
composed annotations. However, only one of the annotations will ever be
used to bootstrap the TestContext Framework. Thus, in such scenarios
one of the annotations will be silently ignored.
This commit introduces a check for such scenarios. BootstrapUtils'
resolveTestContextBootstrapper() method now throws an
IllegalStateException if more than one @BootstrapWith annotation is
'present' on a given test class.
Issue: SPR-12602
This commit consistently documents the 'element' and 'annotationType'
method arguments throughout AnnotatedElementUtils.
In addition, this commit introduces assertions against preconditions
for all 'element' and 'annotationType' method arguments.
Issue: SPR-11514
Previously MockHttpServletRequestBuilder merge method would append the
parent's (default) RequestPostProcessor implementations to the end. This
means that the default RequestPostProcessor implementations would override
values set by previous RequestPostProcessor implementations.
This commit ensures that the default RequestPostProcessor are preformed
first so that additional RequestPostProcessor implementations override
the defaults.
Issue: SPR-12945
This commit introduces support for finding annotations on abstract,
bridge, and interface methods in AnnotatedElementUtils.
- Introduced dedicated findAnnotationAttributes() methods in
AnnotatedElementUtils that provide first-class support for
processing methods, class hierarchies, interfaces, bridge methods,
etc.
- Introduced find/get search algorithm dichotomy in
AnnotatedElementUtils which is visible in the public API as well as
in the internal implementation. This was necessary in order to
maintain backwards compatibility with the existing API (even though
it was undocumented).
- Reverted all recent changes made to the "get semantics" search
algorithm in AnnotatedElementUtils in order to ensure backwards
compatibility, and reverted recent changes to
JtaTransactionAnnotationParser and SpringTransactionAnnotationParser
accordingly.
- Documented internal AnnotatedElementUtils.Processor<T> interface.
- Enabled failing tests and introduced
findAnnotationAttributesFromBridgeMethod() test in
AnnotatedElementUtilsTests.
- Refactored ApplicationListenerMethodAdapter.getCondition() and
enabled failing test in TransactionalEventListenerTests.
- AnnotationUtils.isInterfaceWithAnnotatedMethods() is now package
private.
Issue: SPR-12738, SPR-11514, SPR-11598
Before 4.2 the MvcUriComponentsBuilder exposed only static factory
methods and therefore there should be no reason for it to extend
UriComponentsBuilder (design oversight). It's also highly unlikely
for application code to treat MvcUriCB as UriCB since there is no
need and no way to obtain an instance (constructor is protected).
This change removes the base class declaration from MvcUriCB.
Issue: SPR-12617
Before this change MvcUriComponentsBuilder exposed only static factory
methods for creating links where the links are relative to the current
request or a baseUrl explicitly provided as an argument.
This change allows creating an MvcUriComponents builder instance with
a built-in baseUrl. The instance can then be used with non-static
withXxx(...) method alternatives to the static fromXxx(...) methods.
Issue: SPR-12617
Prior to this commit, AnnotationAttributes retrieved from
MetaAnnotationUtils's AnnotationDescriptor could contain attributes
from the wrong annotation if an inherited annotation shadowed a locally
declared composed annotation.
This commit addresses this issue by invoking the new
getAnnotationAttributes() method in AnnotatedElementUtils that provides
a flag to control whether superclasses should be searched -- which
coincidentally processes local annotations before searching the class
hierarchy.
Issue: SPR-12749, SPR-11598
This commit introduces support in AnnotatedElementUtils for finding
annotations declared on interfaces at the type level.
NB: this commit does not include support for finding annotations
declared on interface methods.
In order to maintain backward compatibility with @Transactional
annotation attribute processing, a new getAnnotationAttributes() method
has been added to AnnotatedElementUtils that provides a flag to control
whether interfaces should be searched.
SpringTransactionAnnotationParser and JtaTransactionAnnotationParser
have been updated accordingly to ensure that interfaces are not
unintentionally searched in the @Transactional resolution process.
This commit also introduces additional tests and updates TODOs for
SPR-12738.
Issue: SPR-12944, SPR-12738
This commit adds support for script based templating. Any templating
library running on top of a JSR-223 ScriptEngine that implements
Invocable like Nashorn or JRuby could be used.
For example, in order to render Mustache templates thanks to the Nashorn
Javascript engine provided with Java 8+, you should declare the following
configuration:
@Configuration
@EnableWebMvc
public class MustacheConfig extends WebMvcConfigurerAdapter {
@Override
public void configureViewResolvers(ViewResolverRegistry registry) {
registry.scriptTemplate();
}
@Bean
public ScriptTemplateConfigurer configurer() {
ScriptTemplateConfigurer configurer = new ScriptTemplateConfigurer();
configurer.setEngineName("nashorn");
configurer.setScripts("mustache.js");
configurer.setRenderObject("Mustache");
configurer.setRenderFunction("render");
return configurer;
}
}
The XML counterpart is:
<beans>
<mvc:annotation-driven />
<mvc:view-resolvers>
<mvc:script-template />
</mvc:view-resolvers>
<mvc:script-template-configurer engine-name="nashorn" render-object="Mustache" render-function="render">
<mvc:script location="mustache.js" />
</mvc:script-template-configurer>
</beans>
Tested with:
- Handlebars running on Nashorn
- Mustache running on Nashorn
- React running on Nashorn
- EJS running on Nashorn
- ERB running on JRuby
- String templates running on Jython
Issue: SPR-12266
Prior to this commit, the search algorithm used by the
findAnnotation(Method, Class) method in AnnotationUtils only found
direct annotations or direct meta-annotations (i.e., one level of
meta-annotations).
This commit reworks the search algorithm so that it supports arbitrary
levels of meta-annotations on methods. To make this possible, a new
findAnnotation(AnnotatedElement, Class) method has been introduced in
AnnotationUtils.
This fix also allows for the @Ignore'd tests in
TransactionalEventListenerTests to be re-enabled.
Issue: SPR-12941
Since the ContextCache is now a published SPI, it and its collaborators
have been moved to a dedicated 'org.sfw.test.context.cache' subpackage.
Issue: SPR-12683
If a custom MessageConverter is set, it is not used for replies defined
via the Message abstraction. This commit harmonizes the behaviour of the
`MessagingMessageConverter` so that the conversion of the payload can
be converted for both incoming and outgoing messages.
Issue: SPR-12912
Previously, a custom `DestinationResolver` was not made available
to the underlying `MessageListener`: if a reply needs to be sent, the
default `DestinationResolver` was used.
This commit ensures that if a custom `DestinationResolver` has been set,
it is also configured accordingly for replies.
Issue: SPR-12927
This commit adds an assertion to DefaultTestContext's
getApplicationContext() method to ensure that a context loaded by the
Spring TestContext Framework (TCF) or retrieved from the ContextCache
is still active. This extra check helps to avoid situations where
developers manually close a cached context instead of relying on the
@DirtiesContext support.
Issue: SPR-12932
The changes made in 0cb22fc8f3 would
result in contexts not being properly closed if evicted from the
ConcurrentReferenceHashMap by the Garbage Collector.
This commit reverts those changes and returns to using standard
ConcurrentHashMaps for the time being.
Issue: SPR-7687
Improve extensibility of TestContext bootstrapping & context caching
These commits include numerous refactorings and enhancements to the
bootstrapping and context caching mechanisms in the Spring TestContext
Framework.
Issue: SPR-12683
- DefaultBootstrapContext and DefaultCacheAwareContextLoaderDelegate
are now public classes in the 'support' subpackage.
- Introduced getCacheAwareContextLoaderDelegate() in
AbstractTestContextBootstrapper as an extension point for configuring
custom ContextCache support.
- Introduced reflection-based createBootstrapContext() utility method
in BootstrapUtils; TestContextManager now delegates to BootstrapUtils
in order to avoid package cycles.
- Introduced logStatistics() method in the ContextCache API and defined
statistics logging category as a constant.
- DefaultCacheAwareContextLoaderDelegate now delegates to
ContextCache.logStatistics().
Issue: SPR-12683
This commit moves the responsibility of building a TestContext from the
TestContextManager to a TestContextBootstrapper.
In addition, DefaultTestContext is now a public class residing in the
"support" subpackage.
Issue: SPR-12683
Prior to this commit, the ContextCache in the Spring TestContext
Framework (TCF) cached ApplicationContexts in a ConcurrentHashMap using
strong references. This practice can occasionally lead to
OutOfMemoryErrors when running a large number of tests in a test suite
with varying context configuration since the context cache becomes
overpopulated over time.
This commit addresses this issue by using Spring's
ConcurrentReferenceHashMap which uses SoftReferences for both the keys
(i.e., MergedContextConfiguration instances) and values (i.e.,
ApplicationContexts) stored in the map that backs the ContextCache.
Issue: SPR-7687
This change adds support for broadcasting messages with unresolved
user destinations so that other servers can try to resolve it.
That enables sending messages to users who may be connected to a
different server.
Issue: SPR-11620
Prior to this commit, ClassLevelDirtiesContextTests existed for
verifying the expected behavior of @DirtiesContext declared at the
class level in conjunction with JUnit and SpringJUnit4ClassRunner.
This commit introduces analogous tests for TestNG in the new
ClassLevelDirtiesContextTestNGTests class.
Furthermore, ContextCacheTestUtils and TrackingTestNGTestListener have
been introduced to reduce code duplication across the test suite.
Issue: SPR-12918
The attributes of @JmsListener allows to specify the reference to a key
in the Environment but @SendTo did not.
This commit fixes this inconsistency so that response destinations are
now also externally configurable.
Issue: SPR-12899
Previously, the "pubSubDomain" drove the resolution of both the
destination of the listener and the default response destination.
A new "replyPubSubDomain" attribute has been added on the base listener
and can be used to listen on a topic and reply to a queue (or vice
versa). The attribute is exposed via the "response-destination-type" XML
attribute on the listener container element. It is also available on the
JmsListenerContainerFactory for use with the @JmsListener infrastructure.
Issue: SPR-12911
This commit increases the extensibility of
AbstractTestContextBootstrapper by making the resolveContextLoader()
and resolveExplicitContextLoaderClass() methods protected instead of
private.
Furthermore, resolveContextLoader() now throws an IllegalStateException
if getDefaultContextLoaderClass() returns null.
Issue: SPR-12682
This commit improves the documentation for ScriptUtils by explicitly
mentioning that a JDBC Connection supplied to the one of the
executeSqlScript() methods will not be released automatically.
Issue: SPR-12908
The onFailure callback and future.get() occur in different threads so
this change adds a latch to ensure we have both before asserting.
Issue: SPR-12887
AbstractHttpMessageConverter now tries to call getDefaultContentType
with the actual value to be converted to see if that will result in
a more concrete mediat type than application/octet-stream.
Issue: SPR-12894
The use of RedirectAttributes was documented in four places in the
reference documentation. This commit merges some of the places and links
properly between them.
Issue: SPR-12759
Prior to this commit it was possible to set or get a static field using
ReflectionTestUtils but only if an instance of the target class was
available.
This commit introduces dedicated support for setting and getting static
fields in ReflectionTestUtils when only the target class is available.
Furthermore, this commit increases the robustness of
ReflectionTestUtilsTests regarding expected exceptions and simplifies
the Javadoc for ReflectionTestUtils.
Issue: SPR-6792
The auto startup flag can now be set on a JmsListenerContainerFactory to
control if the created container should be started automatically when the
application context starts.
Issue: SPR-12824
This commit introduces support for CORS in Spring Framework.
Cross-origin resource sharing (CORS) is a mechanism that allows
many resources (e.g. fonts, JavaScript, etc.) on a web page to
be requested from another domain outside the domain from which
the resource originated. It is defined by the CORS W3C
recommandation (http://www.w3.org/TR/cors/).
A new annotation @CrossOrigin allows to enable CORS support
on Controller type or method level. By default all origins
("*") are allowed.
@RestController
public class SampleController {
@CrossOrigin
@RequestMapping("/foo")
public String foo() {
// ...
}
}
Various @CrossOrigin attributes allow to customize the CORS configuration.
@RestController
public class SampleController {
@CrossOrigin(origin = { "http://site1.com", "http://site2.com" },
allowedHeaders = { "header1", "header2" },
exposedHeaders = { "header1", "header2" },
method = RequestMethod.DELETE,
maxAge = 123, allowCredentials = "true")
@RequestMapping(value = "/foo", method = { RequestMethod.GET, RequestMethod.POST} )
public String foo() {
// ...
}
}
A CorsConfigurationSource interface can be implemented by HTTP request
handlers that want to support CORS by providing a CorsConfiguration
that will be detected at AbstractHandlerMapping level. See for
example ResourceHttpRequestHandler that implements this interface.
Global CORS configuration should be supported through ControllerAdvice
(with type level @CrossOrigin annotated class or class implementing
CorsConfigurationSource), or with XML namespace and JavaConfig
configuration, but this is not implemented yet.
Issue: SPR-9278
This commit adds a filters property to MappingJacksonValue
and also manages a special FilterProvider class name model key in
order to be able to specify a customized FilterProvider for each
handler method execution, and thus provides a more dynamic
alternative to our existing JsonView support.
A filters property is also now available in Jackson2ObjectMapperBuilder
and Jackson2ObjectMapperFactoryBean in order to set easily a
global FilterProvider.
More details about @JsonFilter at
http://wiki.fasterxml.com/JacksonFeatureJsonFilter.
Issue: SPR-12586
Prior to this commit, the `client-library-url` XML attribute was not
effective in the MVC namespace, leaving the default value configured:
```xml
<websocket:sockjs client-library-url="/js/sockjs.js" />
```
This commit fixes the sockjs namespace handler and makes sure that this
attribute is configured on the `SockJsService` Bean to be created.
Issue: SPR-12874
This commit introduces support for "Path Segment URI Variable
expansion", see https://tools.ietf.org/html/rfc6570#section-3.2.6.
In practice, this means that URI template variables prefixed with a '/'
are treated like path segments and - as such - will encode any '/'
found. For example: {/foo} expanded with "bar/baz" with result in
"bar%2F".
Issue: SPR-12750
This change provides support for map[NEW], map[new], map[T]
and map[t]. Prior to this change the 'new' and 't' had to
be quoted because they were keywords in SpEL for a constructor
reference and type reference respectively.
Issue: SPR-11783
- The exception message now mentions lacking to-Object method as well.
- Documented explicit lacking support for toString() for conversions.
- Introduced dedicated has*() methods for greater clarity and to reduce
code duplication.
- Static factory methods (i.e., of, from, valueOf) are now supported for
conversion to a String.
- Now correctly using @Test(expected=...) where appropriate.
- Renamed DefaultConversionTests to DefaultConversionServiceTests.
- Moved all tests related to DefaultConversionService from
GenericConversionServiceTests to DefaultConversionServiceTests.
- No longer printing to System.out.
- Removed all duplicate instantiation of conversion services.
- Now using Java 8 streams to simplify implementations of custom test
converters. Also using streams in tests where appropriate.
The check for an empty request body InputStream is now in the base
class AbstractMessageConverterMethodArgumentResolver shared for
all arguments that involve reading with an HttpMessageConverter --
@RequestBody, @RequestPart, and HttpEntity.
When an empty body is detected any configured RequestBodyAdvice is
given a chance to select a default value or leave it as null.
Issue: SPR-12778, SPR-12860, SPR-12861
RequestBodyAdvice is analogous to ResponseBodyAdvice (added in 4.1)
but for intercepting for reading the request with an
HttpMessageConverter for resolving an @RequestBody or an HttpEntity
method argument.
Issue: SPR-12501
The rework of 314b069 in a7fec6a has created a lazy proxy to make sure
that the need for an exception cache resolver come as late as possible.
Unfortunately, the test that was only failing on CI because of an early
lookup has not been updated accordingly. This is now the case.
Issue: SPR-12850
This is a rework of 314b069 that may still lead to issue if a Cacheable
annotated bean is inspected on startup. Instead of resolving the default
exception CacheResolver if a cache operation is parsed, we resolve it as
late as possible (i.e. when an exception is thrown and the relevant
exception cache needs to be resolved)
Issue: SPR-12850
Previously, a cache infrastructure with only a CacheResolver would have
worked fine until the JSR-107 API is added to the classpath. When this is
the case, the JCache support kicks in and an exception cache resolver is
all of the sudden required.
The CacheResolver _is_ different as the default implementation does look
different attributes so if a custom CacheResolver is set, it is not
possible to "reuse" it as a fallback exception CacheResolver.
Now, an exception CacheResolver is only required if a JSR-107 annotation
with an "exceptionCacheName" attribute is processed (i.e. the exception
CacheResolver is lazily instantiated if necessary).
The use case of having a CachingConfigurerSupport with only a
CacheResolver was still broken though since the JCache support only looks
for a JCacheConfigurer bean (per the generic type set on
AbstractCachingConfiguration). This has been fixed as well.
Issue: SPR-12850
The getter in TransportHandlingSockJsService now returns a mutable
List. The immutable wrapper doesn't make sense since it's possible
anyway to modify the list by creating a new list and calling the
setter again. It's also consistent with the same field on
WebSocketHttpRequestHandler.
This is related to work for SPR-12845.
Generally update chapter and add documentation for 4.2 including
the return value types ResponseBodyEmitter, SseEmitter, and
StreamingResponseBody.
Issue: SPR-12672
This reverts commit a57d42829c after the
realization of a weaknesses with the proposed approach.
For example if a path segment contains both a /-prefixed and a regular
URI variable, there is no way to split that into a sequence of path
and path segments. The solution will have to be on the side of
UriComponents at the time of encoding.
Introduces an AbstractXlsView and dedicated subclasses for POI's xmlx support.
Deprecates the traditional AbstractExcelView which is based on pre POI 3.5 API.
Issue: SPR-6898
Since SPR-11792, Last-Modified and ETag headers are also written in
`HTTP 304 Not Modified` responses. This is expected as per
https://tools.ietf.org/html/rfc7232#section-4.1 .
Those tests expected "Last-Modified" to be missing in case of HTTP 304
responses, which is not the case anymore since 953608ec .
Issue: SPR-11792
The `javadoc-baseurl` asciidoctor attribute is now externalized
(i.e. not included directly in the document anymore).
This allows to properly render javadoc links in single pages, whereas
those URLs were previoulsy only supported in the single page version.
Prior to this commit, Cache-Control HTTP headers could be set using
a WebContentInterceptor and configured cache mappings.
This commit adds support for cache-related HTTP headers at the controller
method level, by returning a ResponseEntity instance:
ResponseEntity.status(HttpStatus.OK)
.cacheControl(CacheControl.maxAge(1, TimeUnit.HOURS).cachePublic())
.eTag("deadb33f8badf00d")
.body(entity);
Also, this change now automatically checks the "ETag" and
"Last-Modified" headers in ResponseEntity, in order to respond HTTP
"304 - Not Modified" if necessary.
Issue: SPR-8550
This commit improves HTTP caching defaults and flexibility in
Spring MVC.
1) Better default caching headers
The `WebContentGenerator` abstract class has been updated with
better HTTP defaults for HTTP caching, in line with current
browsers and proxies implementation (wide support of HTTP1.1, etc);
depending on the `setCacheSeconds` value:
* sends "Cache-Control: max-age=xxx" for caching responses and
do not send a "must-revalidate" value by default.
* sends "Cache-Control: no-store" or "Cache-Control: no-cache"
in order to prevent caching
Other methods used to set specific header such as
`setUseExpiresHeader` or `setAlwaysMustRevalidate` are now deprecated
in favor of `setCacheControl` for better flexibility.
Using one of the deprecated methods re-enables previous HTTP caching
behavior.
This change is applied in many Handlers, since
`WebContentGenerator` is extended by `AbstractController`,
`WebContentInterceptor`, `ResourceHttpRequestHandler` and others.
2) New CacheControl builder class
This new class brings more flexibility and allows developers
to set custom HTTP caching headers.
Several strategies are provided:
* `CacheControl.maxAge(int)` for caching responses with a
"Cache-Control: max-age=xxx" header
* `CacheControl.noStore()` prevents responses from being cached
with a "Cache-Control: no-store" header
* `CacheControl.noCache()` forces caches to revalidate the cached
response before reusing it, with a "Cache-Control: no-store" header.
From that point, it is possible to chain method calls to craft a
custom CacheControl instance:
```
CacheControl cc = CacheControl.maxAge(1, TimeUnit.HOURS)
.cachePublic().noTransform();
```
3) Configuring HTTP caching in Resource Handlers
On top of the existing ways of configuring caching mechanisms,
it is now possible to use a custom `CacheControl` to serve
resources:
```
@Configuration
public class MyWebConfig extends WebMvcConfigurerAdapter {
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
CacheControl cc = CacheControl.maxAge(1, TimeUnit.HOURS);
registry.addResourceHandler("/resources/**)
.addResourceLocations("classpath:/resources/")
.setCacheControl(cc);
}
}
```
or
```
<mvc:resources mapping="/resources/**" location="classpath:/resources/">
<mvc:cachecontrol max-age="3600" cache-public="true"/>
</mvc:resources>
```
Issue: SPR-2779, SPR-6834, SPR-7129, SPR-9543, SPR-10464
This change improves the following use cases with
`WebRequest.checkNotModified(String etag)` and
`WebRequest.checkNotModified(long lastModifiedTimeStamp)`:
1) Allow weak comparisons for ETags
Per rfc7232 section-2.3, ETags can be strong or weak;
this change allows comparing weak forms `W/"etagvalue"` but does
not make a difference between strong and weak comparisons.
2) Allow multiple ETags in client requests
HTTP clients can send multiple ETags values in a single header such as:
`If-None-Match: "firstvalue", "secondvalue"`
This change makes sure each value is compared to the one provided by
the application side.
3) Extended support for ETag values
This change adds padding `"` to the ETag value provided by
the application, if not already done:
`etagvalue` => `"etagvalue"`
It also supports wildcard values `*` that can be sent by HTTP clients.
4) Sending validation headers for 304 responses
As defined in https://tools.ietf.org/html/rfc7232#section-4.1
`304 Not Modified` reponses must generate `Etag` and `Last-Modified`
HTTP headers, as they would have for a `200 OK` response.
5) Providing a new method to validate both Etag & Last-Modified
Also, this change adds a new method
`WebRequest.checkNotModified(String etag, long lastModifiedTimeStamp)`
in order to support validation of both `If-None-Match` and
`Last-Modified` headers sent by HTTP clients, if both values are
supported by the application code.
Even though this approach is recommended by the HTTP rfc (setting both
Etag and Last-Modified headers in the response), this requires more
application logic and may not apply to all resources produced by the
application.
Issue: SPR-11324
Prior to this commit, @DirtiesContext could only be used to close a
test ApplicationContext after an entire test class or after a test
method; however, there are some use cases for which it would be
beneficial to close a test ApplicationContext before a given test class
or test method -- for example, if some rogue (i.e., yet to be
determined) test within a large test suite has corrupted the original
configuration for the ApplicationContext.
This commit provides a solution to such testing challenges by
introducing the following modes for @DirtiesContext.
- MethodMode.BEFORE_METHOD: configured via the new methodMode attribute
- ClassMode.BEFORE_CLASS and ClassMode.BEFORE_EACH_TEST_METHOD: both
configured via the existing classMode attribute
Issue: SPR-12429
Since Guava 11, CacheLoader is only invoked with a LoadingCache but the
GuavaCache wrapper is always invoking getIfPresent(), available on the
main Guava Cache interface.
Update GuavaCache#get to check for the presence of a LoadingCache and
call the appropriate method.
Issue: SPR-12842
This commit updates the Spr8849Tests test suite to include XML
configuration that guarantees that a unique database name is always
automatically generated (via the new 'generate-name' attribute that was
introduced in SPR-8849) while reusing the same bean name (i.e.,
'dataSource').
Issue: SPR-8849
Development teams often encounter errors with embedded databases if
their test suite inadvertently attempts to recreate additional
instances of the same database. This can happen quite easily if an XML
configuration file or @Configuration class is responsible for creating
an embedded database and the corresponding configuration is then reused
across multiple testing scenarios within the same test suite (i.e.,
within the same JVM process) -- for example, integration tests against
embedded databases whose ApplicationContext configuration only differs
with regard to which bean definition profiles are active.
The root cause of such errors is the fact that Spring's
EmbeddedDatabaseFactory (used internally by both the
<jdbc:embedded-database> XML namespace element and the
EmbeddedDatabaseBuilder for Java Config) will set the name of the
embedded database to "testdb" if not otherwise specified. For the case
of <jdbc:embedded-database>, the embedded database is typically
assigned a name equal to the bean's id. Thus, subsequent attempts to
create an embedded database will not result in a new database. Instead,
the same JDBC connection URL will be reused, and attempts to create a
new embedded database will actually point to an existing embedded
database created from the same configuration.
This commit addresses this common issue by introducing support for
generating unique names for embedded databases. This support can be
enabled via:
- EmbeddedDatabaseFactory.setGenerateUniqueDatabaseName()
- EmbeddedDatabaseBuilder.generateUniqueName()
- <jdbc:embedded-database generate-name="true" ... >
Issue: SPR-8849
This commit introduces support for HTTP byte ranges in the
ResourceHttpRequestHandler. This support consists of a number of
changes:
- Parsing of HTTP Range headers in HttpHeaders, using a new HttpRange
class and inner ByteRange/SuffixByteRange subclasses.
- MIME boundary generation moved from FormHttpMessageConverter to
MimeTypeUtils.
- writePartialContent() method introduced in ResourceHttpRequestHandler,
handling the byte range logic
- Additional partial content tests added to
ResourceHttpRequestHandlerTests.
Issue: SPR-10805
After this change UriComponentsBuilder#uriComponents method no longer
no longer copies from the given UriComponents but rather lets the
UriComponents instance copy itself to the UriComponentsBuilder.
This avoids the need for instanceof checks and also makes it possible
to distinguish between path and path segments, which otherwise is
internal knowledge of UriComponentsBuilder.
Issue: SPR-12742
Revised HandlerMethod.getBeanType() impl for both web and messaging.
In addition, HandlerMethods get created with the internal BeanFactory now.
Issue: SPR-12832
This commit refactors the XML configuration used by the tests in the
Spr8849Tests test suite so that a unique database name is always
generated (via the new 'database-name' attribute that was introduced in
SPR-12835) while reusing the same bean name (i.e., 'dataSource').
This is a much more robust alternative to the previous work-around
since the name of the DataSource does not randomly change across
application contexts, thus allowing proper autowiring by name and bean
referencing within XML configuration.
Issue: SPR-8849
Prior to this commit, the EmbeddedDatabaseBeanDefinitionParser set the
name of the embedded database that it configured to the value of its
'id'. This made it impossible to assign unique names to embedded
databases if the same bean 'id' (e.g, 'dataSource') was used across
multiple application contexts loaded within the same JVM, which is
often the case within an integration test suite. In contrast, the
EmbeddedDatabaseBuilder already provides support for setting the name
in Java Config. Thus there is a disconnect between XML and Java
configuration.
This commit addresses this issue by introducing a 'database-name'
attribute in <jdbc:embedded-database />. This allows developers to set
unique names for embedded databases -- for example, via a SpEL
expression or a property placeholder that is influenced by the current
active bean definition profiles.
Issue: SPR-12835
This commit modifies EmbeddedDatabaseBeanDefinitionParser so that the
<jdbc:embedded-database> XML namespace element can be declared as an
anonymous bean (i.e., without an explicit ID).
Issue: SPR-12834
This commit introduces spring-jdbc-4.2.xsd in order to support upcoming
changes to the JDBC XML namespace.
In addition, this commit polishes the XSD documentation with regard to
use cases for script execution.
FlashMap now has a single field reflecting the expiration time and
also provides accessors that can be used for serialization purposes.
Issue: SPR-12757
AbstractFlashMapManager no longer decodes the target query parameters
it needs to use to match to the request after the redirect.
Instead it stores query parameters as-is adn then relies on parsing the
encoded query string after the redirect.
Issue: SPR-12569
This change adds support for global @MessageExceptionHandler methods
with STOMP over WebSocket messages. Such methods can be added to
@ControllerAdvice annotated components, much like @ExceptionHandler
methods for Spring MVC.
Issue: SPR-12696
Covers ReflectionUtils.doWithMethods as well as affected annotation post-processors.
Includes an extension of MethodMetadata for the detection of @Bean default methods.
Issue: SPR-12822
Issue: SPR-10919
Prior to this commit, the ContentCachingRequestWrapper would immediately
consume the wrapped request's InputStream when asked for the cached
content; that caused several issues:
* the request body was read in memory even if it wasn't yet consumed by
the application, leading to inefficiencies.
* when requesting the InputStream, an empty InputStream was returned
since the original was already read.
This case only happened for form POSTs requests.
This commit makes sure that the wrapper does not alter the request
expected behavior:
* when getting the inputstream, it is wrapped in order to cache its
content
* when getting request parameters, the request body is cached and its
inputstream is consumed, as expected
Issue: SPR-12810
WebSocketStompClient can be used with any implementation of
org.springframework.web.socket.client.WebSocketClient, which includes
org.springframework.web.socket.sockjs.client.SockJsClient.
Reactor11TcpStompClient can be used with reactor-net and provides STOMP
over TCP. It's also possible to adapt other WebSocket and TCP client
libraries (see StompClientSupport for more details).
For example usage see WebSocketStompClientIntegrationTests.
Issue: SPR-11588
Various documentation improvements related to `@Configuration` and
`Bean`. Better describe how method parameter can be used to declare
dependencies of a particular bean. Also add an explicit mentions related
to "hard-wiring" of dependencies in configuration classes.
Issue: SPR-12773
If a sub-class of Future (such as ListenableFuture) is used as a return
type and an exception is thrown, the AsyncUncaughtExceptionHandler is
called. Now checking for any Future implementation instead of a faulty
strict matching.
Issue: SPR-12797
This commit ensures that @NumberFormat can be used as a
meta-annotation, as was already the case for @DateTimeFormat.
In addition, this commit polishes FormattingConversionServiceTests and
MvcNamespaceTests.
Issue: SPR-12743
Prior to this commit, the [ant:iajc] tasks logged numerous warnings
regarding incorrect classpath entries. The reason is that the classpath
was constructed with paths that do not physically exist in the file
system (e.g., for projects that do not have test classes or test
folders (yet)).
This commit picks up where ef75bd8 left off and addresses this issue by
assembling the runtime classpath passed to the iajc task with folders
and JARs that actually exist in the filesystem.
This commit reverts the changes made in 7bc44a9 so that developers who
do not use the Gradle daemon are not adversely affected by the explicit
JVM args that were introduced in that commit.
Developers who wish to run the build against JDK 9 with the Gradle
daemon can add the following to the gradle.properties file in their
'gradle user home' directory (e.g., ~/.gradle/gradle.properties):
org.gradle.daemon=true
org.gradle.jvmargs=-XX:MaxMetaspaceSize=1024m -Xmx1024m
See also: https://issues.gradle.org/browse/GRADLE-3256
Issue: SPR-12549
The upgrade to a more recent asciidoc format led to a bunch of of
broken Admonition as the text block now requires four equal signs while
previous versions tolerated only 3.
Issue: SPR-12791
Prior to this change the SpEL compiler would not compile mathematical
expressions where the operands were of differing types (e.g. int
and double). This required the expression writer to do the conversion
in the expression text. For example:
T(Integer).valueOf(someInt).doubleValue()/35d
With this commit the restriction is lifted and it is more like Java
so that you can simply do someInt/35d. The mathematical operators
affected are divide/plus/minus/multiply and modulus. This change
involved removing some guards so that the exitTypeDescriptor (the
trigger for whether compilation is allowed) is set more frequently
and enhancing bytecode generation to perform more sophisticated
conversion/coercion automatically.
Issue: SPR-12789
Core and Web chapters are important chapters in the Spring Framework
reference documentation, and splitting them in multiple files will
help to evolve the documentation while not creating too many files.
Issue: SPR-12309
The reference documentation is now organized in asciidoc bookparts.
Bookparts sections can be also put in separate files, when their
size and theme are important enough to justify that.
Documentation Layout:
```
index
|-- overview
|
|-- whats-new
|
|-- core
| |-- core-beans
| |-- core-aop
|-- testing
|
|-- data-access
|
|-- web
| |-- web-mvc
| |-- web-view
|-- integration
|
|-- appendix
|-- appx-spring-tld
|-- appx-spring-form-tld
```
Supersedes and closes#641
Issue: SPR-12309
All HttpMessageConverters should support StreamingHttpOutputMessage.
Specifically, the BufferedImageHttpMessageConverter and
FormHttpMessageConverter should do so.
Issue: SPR-12715
This commit adds the following to gradle.properties in order to execute
the Gradle daemon on JDK 9, since Gradle's DaemonParameters
automatically sets the MaxPermSize JVM argument, which is no longer
supported on JDK 9.
org.gradle.jvmargs=-XX:MaxMetaspaceSize=1024m -Xmx1024m
Issue: SPR-12549
Previously, adding `@EnableAsync` on a blank application would lead to an
info message stating that `ProxyAsyncConfiguration` is not eligible for
getting processed by all BeanPostProcessors. Concretely, this is ok as
such internal configuration is not meant to be a target of such post
processing.
Revisit the condition for non infrastructure bean only. Add the
infrastructure role to a set of internal configuration, including the
`ProxyAsyncConfiguration`.
Issue: SPR-12761
Support the creation and registration of message listener containers in
a lazy manner, that is after the container initialization has completed.
Such support brought an interesting brainstorming of the thread safety
if JmsListenerEndpointRegistrar and JmsListenerEndpointRegistry so those
have also been revisited as part of this commit.
Issue: SPR-12774
This commit simplifies the implementations of loadBeanDefinitions() in
GenericGroovyXmlContextLoader and GenericGroovyXmlWebContextLoader.
Due to the recent bug fix for GroovyBeanDefinitionReader regarding full
support for XML config files, these Groovy context loaders can now
simply use a GroovyBeanDefinitionReader instead of a
GroovyBeanDefinitionReader plus an XmlBeanDefinitionReader.
Issue: SPR-12769
Prior to this commit, the GroovyBeanDefinitionReader claimed (via its
Javadoc) that it fully supported XML configuration files in addition to
its Groovy DSL; however, this was unfortunately inaccurate since XML
validation was disabled by default which led to certain features of XML
configuration not working. For example, it was impossible to define a
<qualifier> in an XML config file without specifying the 'type'
attribute (which has a default value defined in the spring-beans XSD).
This commit fixes this issue by ensuring that bean definitions in XML
resources are loaded with a "standard" XmlBeanDefinitionReader that is
created with default settings (i.e., with XML validation enabled). With
regard to backwards compatibility, bean definitions defined using the
Groovy DSL are still loaded with an XmlBeanDefinitionReader that has
XML validation disabled by default which is necessary for proper
parsing of the Groovy DSL.
Issue: SPR-12769
Prior to this commit, it was impossible to use all features of XML
configuration (e.g., the <qualifier> tag) in web-based integration
tests (loaded using @WebAppConfiguration, @ContextConfiguration, etc.)
if the Groovy library was on the classpath. The reason is that the
GroovyBeanDefinitionReader used internally by
GenericGroovyXmlWebContextLoader disables XML validation for its
internal XmlBeanDefinitionReader, and this prevents some XML
configuration features from working properly. For example, the default
value for the 'type' attribute (defined in the spring-beans XSD) of the
<qualifier> tag gets ignored, resulting in an exception when the
application context is loaded.
This commit addresses this issue by refactoring the implementation of
loadBeanDefinitions() in GenericGroovyXmlWebContextLoader to use an
XmlBeanDefinitionReader or GroovyBeanDefinitionReader depending on the
file extension of the resource location from which bean definitions
should be loaded. This aligns the functionality of
GenericGroovyXmlWebContextLoader with the existing functionality of
GenericGroovyXmlContextLoader.
Issue: SPR-12768
Prior to this commit, the implementation of equals() in EncodedResource
was based solely on the resource and encoding. Thus, if a Charset were
specified instead of an encoding, invocations of equals() would not
work as expected.
This commit addresses this issue by including the charset in the
implementation of equals() and introducing corresponding tests in a new
EncodedResourceTests class. Furthermore, this commit makes
EncodedResource immutable and updates all Javadoc to reflect support
for the encoding and charset properties.
Issue: SPR-12767
To eliminate code duplication, ScriptStatementFailedException and
ScriptUtils now delegate to a new buildErrorMessage() utility method.
Issue: SPR-12752
This commit ensures Resources have consistent, non-empty, meaningful
implementations for getDescription(), thus ensuring that calls to
toString() (e.g., in log statements) no longer return an empty String.
This commit also polishes the Javadoc for various Resource
implementations.
Prior to this change, location checks for serving resources would append
`/` to the location path it didn't already have one.
This commit makes sure not to append a `/` if the provided location is
actually a file.
Issue: SPR-12747
Reduce logging level when no target annotation is found a on bean. For
consistency, update ScheduledAnnotationBeanPostProcessor and
JmsListenerAnnotationBeanPostProcessor that define the same log
statement.
Issue: SPR-12574
Animal Sniffer 1.11 fails against XStream 1.4.8 due to classes with 1.8 bytecode level.
Animal Sniffer 1.14 will finally include ASM 5.0.3 for proper 1.8 bytecode support.
Add StreamConverter to provide full support for converting
java.util.stream.Stream instances to and from collections or arrays.
Also attempt to convert the element type if necessary.
StreamConverter is registered by default in the DefaultConversionService
as long as Java8 is available.
Issue: SPR-12175
When a bean is retrieved via JNDI using Java config, we apply the same
inferred more for destruction callbacks as for any other bean. If an
object from the JNDI tree has a `close` or `shutdown` method, the
context calls it when it shutdowns.
Unfortunately, we have no way to know that the bean was retrieved via
JNDI and that its lifecycle is managed outside the application.
The documentation has been updated to reflect that problem explicitly.
Issue: SPR-12551
If an `@EventListener` annotated method returns a Collection or an Array,
each individual items are now published as an event instead of publishing
one event with said collection.
Issue: SPR-12733
JmsInvokerClientInterceptor defines a receiveTimeout field but does not
handle such timeout. This commit adds an additional callback that throws
an RemoteTimeoutException instead.
Sub-classes can override the onReceiveTimeout to throw a different
exception or return a fallback RemoteInvocationResult.
Issue: SPR-12731
With this commit, WebUtils.isValidOrigin() logs an error message instead
of throwing an IllegalArgumentException when Origin header value is
invalid (for example when it does not contain the scheme).
Issue: SPR-12697
Deprecated CommonsPoolTargetSource (supporting commons pool 1.5+) in
favor of CommonsPool2TargetSource with a similar contract.
Commons Pool 2.x uses object equality while Commons Pool 1.x used
identity equality. This clearly means that Commons Pool 2 behaves
differently if several instances having the same identity according to
their `Object#equals(Object)` method are managed in the same pool. To
provide a smooth upgrade, a backward-compatible pool is created by
default; use `setUseObjectEquality(boolean)` if you need the standard
Commons Pool 2.x behavior.
Issue: SPR-12532
Previously, the `@Order` annotation was managed in an inconsistent way
when placed at the implementation level. For simple beans, it was
discovered properly but wasn't for beans requiring a proxy.
OrderComparator.SourceProvider now explicitly allows to return several
order sources; the default implementation returns not only the factory
method (if any) but also the target class if it happens to be different
from the class of the bean.
Issue: SPR-12636
This commit adds support for a same origin check that compares
Origin header to Host header. It also changes the default setting
from all origins allowed to only same origin allowed.
Issues: SPR-12697, SPR-12685
- Added assertions for pre-conditions on method arguments for all
public utility methods.
- Introduced additional tests in TestPropertySourceUtilsTests to verify
the new pre-conditions.
- Introduced INLINED_PROPERTIES_PROPERTY_SOURCE_NAME constant for the
name of the MapPropertySource created from inlined properties; the
name therefore no longer contains the inlined properties, but the
original values of the inlined properties can now be logged at debug
level.
- Simplified tests in InlinedPropertiesTestPropertySourceTests.
Issue: SPR-12721
Spring Framework 4.1 introduced support for @TestPropertySource;
however, the utilities used to parse inlined properties and add test
property sources to the environment are currently private which
prevents reuse by third-party frameworks like Spring Boot.
This commit addresses this issue by making such utilities public.
- TestPropertySourceUtils is now a public class.
- Various utility methods in TestPropertySourceUtils have been made
public.
- addResourcePropertySourcesToEnvironment() has been renamed to
addPropertiesFilesToEnvironment().
- extractEnvironmentProperties() has been renamed to
convertInlinedPropertiesToMap().
- All public methods in TestPropertySourceUtils are now fully
documented.
Issue: SPR-12721
The initial implementation for adding inlined properties configured via
@TestPropertySource to the context's environment did not preserve the
order in which the properties were physically declared. This makes
@TestPropertySource a poor testing facility for mimicking the
production environment's configuration if the property source mechanism
used in production preserves ordering of property names -- which is the
case for YAML-based property sources used in Spring Boot, Spring Yarn,
etc.
This commit addresses this issue by ensuring that the ordering of
inlined properties declared via @TestPropertySource is preserved.
Specifically, the original functionality has been refactored. extracted
from AbstractContextLoader, and moved to TestPropertySourceUtils where
it may later be made public for general purpose use in other frameworks.
Issue: SPR-12710
Before this change the WebSocketTransportHandler passed
Collections.emptyMap as attributes to the HandshakeHandler because
it didn't matter what attributes the underlying WebSocketSession has
since it is wrapped by the SockJsSession and that's what exposed for
use everywhere.
This change has the WebSocketTransportHandler passing the attributes
from the SockJsSession instead since it's more accurate for the
underlying WebSocketSession to have access to the same map instance
and it allows the HandshakeHandler to change the attributes even if
it doesn't need to do that today.
Issue: SPR-12716
This commit introduces further regression tests to ensure proper parsing
of inlined properties configured via @TestPropertySource. Specifically,
these additional tests ensure that we do not introduce a bug like the
one raised in Spring Boot issue #1110 [0].
[0] https://github.com/spring-projects/spring-boot/issues/1110
Issue: SPR-12710
Previously, the exception-handler attribute was not taken care of when
task:annotation-driven is used in AspectJ mode. This commit provides the
expected behavior.
Issue: SPR-12619
Jasper Reports’ transitive dependency on spring-context (via
castor-xml which is a new dependency in 6.0.3) was being mapped by
Gradle to a dependency on the spring-context project. For reasons that
I do not fully understand this was causing -source and -javadoc jars
to be added to the project's compile classpath which is used by the
Animal Sniffer Ant task. When the task runs these jars do not exist
which causes it to fail. This commit fixes the problem by adding an
exclusion of org.springframework:spring-context to the Jasper Reports
dependencies in spring-context-support and spring-webmvc.
Previously, only indexed access for collections were supported. When
attempting to access the element of an array that had not the requested
size, the call would fail with an IndexOutOfBoundException
This commit harmonize the binding support so that the array is updated
according to the requested index if necessary.
Issue: SPR-12706
Previously, a cache decorated with TransactionAwareCacheDecorator would
clear the cache immediately, even when a transaction is running. This
commit updates the decorator to synchronize to the afterCommit phase for
the clear operation as well.
Issue: SPR-12653
Update the application event listener infrastructure to support events
that are processed according to a transactional phase.
Introduce EventListenerFactory that can be implemented to provide support
for additional event listener types. TransactionalEventListener is a new
annotation that can be used in lieu of the regular EventListener. Its
related factory implementation is registered in the context automatically
via @EnableTransactionManagement or <tx:annotation-driven/>
By default, a TransactionalEventListener is invoked when the transaction
has completed successfully (i.e. AFTER_COMMIT). Additional phases are
provided to handle BEFORE_COMMIT and AFTER_ROLLBACK events.
If no transaction is running, such listener is not invoked at all unless
the `fallbackExecution` flag has been explicitly set.
Issue: SPR-12080
Add support for annotation-based event listeners. Enabled automatically
when using Java configuration or can be enabled explicitly via the
regular <context:annotation-driven/> XML element. Detect methods of
managed beans annotated with @EventListener, either directly or through
a meta-annotation.
Annotated methods must define the event type they listen to as a single
parameter argument. Events are automatically filtered out according to
the method signature. When additional runtime filtering is required, one
can specify the `condition` attribute of the annotation that defines a
SpEL expression that should match to actually invoke the method for a
particular event. The root context exposes the actual `event`
(`#root.event`) and method arguments (`#root.args`). Individual method
arguments are also exposed via either the `a` or `p` alias (`#a0` refers
to the first method argument). Finally, methods arguments are exposed via
their names if that information can be discovered.
Events can be either an ApplicationEvent or any arbitrary payload. Such
payload is wrapped automatically in a PayloadApplicationEvent and managed
explicitly internally. As a result, users can now publish and listen
for arbitrary objects.
If an annotated method has a return value, an non null result is actually
published as a new event, something like:
@EventListener
public FooEvent handle(BarEvent event) { ... }
Events can be handled in an aynchronous manner by adding `@Async` to the
event method declaration and enabling such infrastructure. Events can
also be ordered by adding an `@Order` annotation to the event method.
Issue: SPR-11622
Update the event publishing infrastructure to support generics-based
events, that is support ApplicationListener implementations that define
a generic event, something like:
public class MyListener
implements ApplicationListener<GenericEvent<String>> { ... }
This listener should only receive events that are matching the generic
signature, for instance:
public class StringEvent extends GenericEvent<String> { ... }
Note that because of type erasure, publishing an event that defines the
generic type at the instance level will not work. In other words,
publishing "new GenericEvent<String>" will not work as expected as type
erasure will define it as GenericEvent<?>.
To support this feature, use the new GenericApplicationListener that
supersedes SmartApplicationListener to handle generics-based even types via
`supportsEventType` that takes a ResolvableType instance instead of the
simple Class of the event. ApplicationEventMulticaster has an additional
method to multicast an event based on the event and its ResolvableType.
Issue: SPR-8201
Before this change, detection of X-Forwarded-* headers was only built
into ServletUriComponentsBuilder.
This change adds a new method for creating a UriComponentsBuilder from
an existing HttpRequest. This is equivalent to the fromUri method +
X-Forwarded-* header values.
This commit introduces the following changes:
- Requests without Origin header are not rejected anymore
- Disable Iframe when allowedOrigins is not empty and not equals to *
- The Iframe is not cached anymore in order to have a reliable origin check
- allowedOrigins must not be null or empty
- allowedOrigins format is now validated (should be * or start by http(s)://)
Issue: SPR-12660
Update documentation to explicitly mention that the cache interceptor
must be fully initialized to provide the expected behavior and therefore
initialization code should not rely on this feature, i;e. typically in
PostConstruct callback.
Since the Transactional infrastructure has the exact same infrastructure,
update that section of the doc as well.
Issue: SPR-12700
Previously, one could only set the list of bean names to exclude from
auto-detection and there was no way to add additional bean names.
MBeanExporter now exposes a addExcludedBean method that can be invoked
during the initialization phase to add bean names to ignore.
Issue: SPR-12686
Prior to this change, the `ResourceUrlProvider.getForLookupPath` method
would try to match handlers using the keySet order in the
handlerMappings Map. In case of several matches, the handler used for
the return value could vary, since the registration order in the
handlerMappings can't be guaranteed in the configuration.
This commit now collects all matching handlers and sort them using a
`PatternComparator`, in order to try each handler from the most specific
mapping to the least.
Issue: SPR-12647
This commit also adds a modules(Module...) method in addition to
modules(List<Module> modules) in order to be consistent with other
parts of the API.
Issue: SPR-12634
Before this change, the maxRequestSize property was used (incorrectly)
to limit both the size of the request and response. The change:
- removes maxRequestSize and therefore no longer places limits on the
size of the request thus matching to AbstractBufferingClientHttpRequest
which is the base class for other buffering client implementations.
- adds maxResponseSize property required to create Netty's
HttpObjectAggregator for aggregating responses.
Issue: SPR-12623
Prior to this change when adding subscriptions
DefaultSubscriptionRegistry (incorrectly) made a copy of the given map
for its "access" cache rather than for its "update" cache.
Issue: SPR-12665
Provide an additional hook-point for YamlProcessor subclasses willing to
change how the Yaml instance is configured. Also expose the default
StrictMapAppenderConstructor so that they can compose a custom instance
with it.
Issue: SPR-12671
This commit adds ResponseBodyEmitter and SseEmitter (and also
ResponseEntity<ResponseBodyEmitter> and ResponseEntity<SseEmitter>) as
new return value types supported on @RequestMapping controller methods.
See Javadoc on respective types for more details.
Issue: SPR-12212
Move MethodCacheKey and related classes to the expression package so that
other parts of the framework can benefit ot it.
CacheExpressionEvaluator is a base class that can be used to cache SpEL
expressions based on its annotation source (i.e. method). Sub-classing
that base class provides a simple to use API to retrieve Expression
instances efficiently.
Issue: SPR-12622
Prior to this commit, the `ContentCachingRequestWrapper` class would
cache the response content only if the reponse would be consumed using
its InputStream. In case of a Form request, Spring MVC consumes the
response using the `getParameter*` Servlet API methods. This causes the
cached content to never be written.
This commit makes the `ContentCachingResponseWrapper` write the request
body to the cache buffer by using the `getParameter*` API, thus avoiding
those issues.
Issue: SPR-7913
Modules (well-known or user provided) registration is now performed
first in order to allow their configuration to be customized by more
specific ones like custom serializers or deserializers.
Issue: SPR-12634
Spring Framework 4.0 introduced support for using test-related
annotations as meta-annotations in the Spring TestContext Framework
(TCF) in order to create custom composed annotations within a test
suite; however, the detection of default @Configuration classes in test
classes was not updated to search for @Configuration declared as a
meta-annotation. Specifically, AnnotationConfigContextLoaderUtils
invokes Class.isAnnotated() which only searches for annotations
declared directly on the class in question.
This commit addresses this issue by refactoring the
isDefaultConfigurationClassCandidate() method in
AnnotationConfigContextLoaderUtils so that it uses
AnnotationUtils.findAnnotation() instead of Class.isAnnotated() for
detecting the presence of the @Configuration annotation, either
directly or as a meta-annotation.
Issue: SPR-12659
Various parts of the reference manual as well as the Javadoc for
AnnotationConfigContextLoaderUtils improperly refer to "static inner
classes" even though this terminology does not exist in Java. The Java
Language Specification explicitly refers to such classes as "static
nested classes." An "inner class" must be non-static by definition.
Prior to this change, the ResourceUrlProvider would listen to
ContextRefreshedEvents and autodetect resource handlers each time. This
can cause issues when multiple contexts are involved and the last one
has no resource handler, thus clearing the previously detected ones.
This commit disables resource handlers auto-detection once some have
been detected with a refreshed context.
Issue: SPR-12592
Prior to this change, location paths used for resource handling would
not allow "non-cleaned, relative paths" such as
`file://home/user/static/../static/`. When checking if the resolved
resource's path starts with the location path, a mismatch would happen
when comparing for example:
* the location `file://home/user/static/../static/`
* and the resource `file://home/user/static/resource.txt`
This commit cleans the location path before comparing it to the resource
path.
Issue: SPR-12624
This commit allows the use of "protcol relative URLs" (i.e. URLs without
scheme, starting with `//`), often used to serve resources automatically
from https or http with third party domains.
This syntax is allowed by RFC 3986.
Issue: SPR-12632
This commit fixes the default value for the contextRelative attribute of
a RedirectView, when this view is registered via a
RedirectViewController in XML. The value is set to true.
Note that the default value for this is correctly documented in
spring-mvc-4.1.xsd. Also, the documentation and implementation for its
javadoc counterpart also enforces true as a default value.
Issue: SPR-12607
A logical follow-up on commit 43d937, this change also removes (or
rather deprecates for now) writePrelude that is only of concern to
streaming SockJS session implementations.
Issue: SPR-12427
This change removes the need for the isStreaming field from the base
class AbstractHttpSockJsSession. This field was used to account for
differences between polling vs streaming SockJS sessions without having
to expose to sub-classes private fields that are otherwise protected
from concurrent access by the base class. The change manages to delegate
to sub-classes without providing direct access to protected fields.
Issue: SPR-12427
This commit overhauls several of the tests that interact with an
MBeanServer with the goal of increasing the reliability of these tests.
- MBeanClientInterceptorTests now uses JUnit "assumptions" instead of
preemptively returning from test methods, thus allowing such methods
to be properly marked as "ignored" instead of "passed".
- MBeanClientInterceptorTests now uses JUnit's support for expected
exceptions where appropriate.
- MBeanClientInterceptorTests and RemoteMBeanClientInterceptorTests now
use Spring's SocketUtils to find an available TCP port when starting
an MBeanServer instead of aborting the tests when the default JMX
port is not available.
Issue: SPR-12601
Commit 65d163e changed the textual message of an exception thrown by
ScheduledAnnotationBeanPostProcessor.afterSingletonsInstantiated(), and
this in turn caused the withAmbiguousTaskSchedulers_andSingleTask()
method in EnableSchedulingTests to start failing (albeit only during
'Performance' builds).
This commit updates the assertion to match the current implementation of
ScheduledAnnotationBeanPostProcessor.
In order to allow DefaultActiveProfilesResolver to be reused (e.g., via
extension or delegation), the check which asserts that the 'resolver'
attribute of @ActiveProfiles is not set to a customer resolver class
has been removed.
Issue: SPR-12611
JUnit 4.9 introduced a regression in BlockJUnit4ClassRunner.runChild()
such that exceptions thrown from methodBlock() cause the current test
execution to abort immediately. As a result, the failing test method is
unrooted, and subsequent test methods are never invoked. Furthermore,
RunListeners registered with JUnit are not properly notified.
In conjunction with SPR-11908, SpringJUnit4ClassRunner was updated to
use the aforementioned changes to BlockJUnit4ClassRunner.runChild().
Consequently, SpringJUnit4ClassRunner now suffers from the same
regression.
This commit addresses this issue by ensuring that any exceptions thrown
during the invocation of methodBlock() are properly wrapped in a JUnit
Fail Statement.
Issue: SPR-12613
- Copyright end date is now dynamic, based on the current year.
- Added missing spaces in front of web link to ASL 2.0 license file.
- Changed @since tag to 4.2.
Prior to this commit, HTTP responses without body (response status 204
or 304, Content-Length: 0) were handled properly by RestTemplates. But
some other cases were not properly managed, throwing exceptions for
valid HTTP responses.
This commit better handles HTTP responses, using a response wrapper that
can tell if a response:
* has no message body (HTTP status 1XX, 204, 304 or Content-Length:0)
* has an empty message body
This covers rfc7230 Section 3.3.3.
Issue: SPR-8016
Prior to this change, the ShallowEtagHeaderFilter would use a
ResizableByteArrayOutputStream to internally write data and calculate
the ETag. While that implementation is faster than the regular
ByteArrayOutputStream (since it has a better strategy for growing the
internal buffer), a lot of buffer copying/writing still happens.
This change adds a new FastByteArrayOutputStream implementation that
internally uses a LinkedList<Byte[]> to store the content. So when
writing bytes to that OutputStream implementation, new byte[] are
added to the list when the previous ones are full. This saves most
of the instantiating/copying operations.
Note that new methods were added in DigestUtils to allow usage of
Streams instead of byte[], which is more efficient in our case.
Fixes#653
Issue: SPR-12081
The test was verifying that when a DISCONNECT frame is sent to the
broker, there will be no further messages on the clientOutboundChannel.
This is generally true, however in some cases when the broker receives
a DISCONNECT it may close its connection fast enough (before we do) in
which case we send an ERROR message downstream to ensure the WebSocket
side is cleaned up. Either way the downstream should be idempotent
with regards to cleaning up sessions.
This change designates Jetty SockJS integration tests to run as part of
the "performance", but not the main "publication", CI build due to
recurring low-level failures suspected to be Jetty issues, e.g.
"java.io.IOException: Cannot append to finished buffer" or
"java.io.IOException: Out of order Continuation frame encountered".
The tests will still run at once a day with the performance build but
should not fail the main build with false negatives. Also note that
an Undertow variant of the exact same tests, which hasn't been failing,
will continue to run as part of the main build.
Update HttpComponents wrapper to merge local customizations with the
default of the current HttpClient instead of overriding everything.
This is available as from HttpComponents 4.4. that exposes the default
request config from the client via the Configurable interface. If the
client does not implement such interface, the previous behaviour is
applied
Issue: SPR-12583
Fix a regression introduced by 961574bd17 that prevents a proper lookup
of the default transaction manager by name as the absence of a qualifier
is represented by an empty string (passing the faulty null check).
Issue: SPR-12577
Prior to this commit, some requests would be wrongly mapped to "/" when:
* requests ends with "//" such as "/foo/bar//"
* the DispatcherServlet is mapped as the default ("/")
* the app container sanitizes the servletPath
In those cases, the path extraction algorithm was wrongly guessing the
path of the current request.
This commit detects if the app container sanitized the servletPath for
the current request. If so, it uses a sanitized version of the
requestUri to extract the path information.
Issue: SPR-12372
The following two refinements have been added:
1) SockJS doesn't support binary messages so don't even try
2) don't bother if payload.length == 0
Issue: SPR-12475
Previously the default settings of a custom HttpClient were always
ignored since a RequestConfig instance was always set no matter if
some customizations were applied or not.
This commit keeps an internal RequestConfig object instance that is
only initialized if the user applies a customization. If he does not, the
default settings of the HttpClient are used as it should.
Note that if the HttpComponents API exposed the default RequestConfig
of a given HttpClient, we would be able to merge our customizations with
the one specified by the client. Unfortunately, such API does not exist
and the "defaultSettingsOfHttpClientLostOnExecutorCustomization" test
illustrates that limitation.
Issue: SPR-12540
One more (and hopefully last) attempt at making sure
determineTransactionManager does not break existing use cases.
This commit prevents any lookup if no transaction attributes are set
which is more compliant with the original version and prevents a lookup
if a non existing bean name is provided explicitly (as it can be the case
with Spring Boot).
Issue: SPR-12541
The fix in cec26e9 for SPR-12541 actually introduced a regression
when the interceptor is enabled on a method that does not require any
transaction. In such a case we try to locate the default
PlatformTransactionManager instead of just returning what we have (that
is null).
This commit updates the determineTransactionManager condition again to
take that use case into account again.
Issue: SPR-12541
In order to avoid breaking changed due to the upcoming SockJS 1.0
release (see SPR-12422 for more details) and link to the right
SockJS documentation version, we now explicitly specify that we
support SockJS protocol 0.3.3 and SockJS client 0.3.x.
Before this change attributes listed with @SessionAttributes would not
be saved in the session when there was a redirect and the controller
method declared a parameter of type RedirectAttributes.
This change ensures it's the "default" model that is always the one
checked for @SessionAttributes under all circumstances since
RedirectAttributes is really only meant to provide String values to
insert into or append to the the redirect URL.
Issue: SPR-12542
Previously, if a bean has a scoped proxy and is annotated to be exposed
to the JMX domain, both the scoped proxy and the target instance were
exposed in the JMX domain, resulting in a duplicate entries. Worse, if
such bean defines an explicit name, the application wouldn't start
because of a name conflict.
This commit deals explicitely with scoped proxy and make sure to only
expose the relevant bean.
Issue: SPR-12529
Prior to this commit it was not possible to easily customize the
connection request timeout used by the HttpClient. Both
`HttpComponentsClientHttpRequestFactory` and
`HttpComponentsClientHttpRequestFactoryTests` have been updated to
support a `connectionRequestTimeout` property.
Issue: SPR-12166
Update the documentation to better reflect the fact that a @EnableCaching
configuration class must implement CachingConfigurer in order to provide
advanced customizations to the cache abstraction.
Previously, HttpComponentsHttpInvokerRequestExecutor was not compatible
with the new API of HttpComponents 4.3. Specifically, it is not possible
to update the socket and read timeouts on the HttpClient itself anymore.
We actually already updated HttpComponentsClientHttpRequestFactory for a
similar problem in SPR-11442: if we detect an older HttpClient
implementation, we update the timeout directly on the client. If that's
not the case, we keep the value in the factory itself and use it when a
new HttpRequest needs to be created.
This commit also uses the new API to create a default HttpClient and
therefore requires HttpComponents 4.3. As mentioned above, it is still
possible to use deprecated HttpClient instances against this executor.
Issue: SPR-11113
Without this change when the operands to an == are a mix of a
reference type and a primitive, the failure to box the primitive
would result in a verifyerror when the compiled code is loaded.
Issue: SPR-12557
Update the developer guide to explicitly reference the (inferred)
constant introduced in 38e90105a0.
Also emphasis the fact that the (inferred) mode is enabled by default
with Java config and how to disable it if necessary.
Issue: SPR-12534
Previously, cache transaction managers may be retained outside the
boundaries of an application context with AspectJ since an aspect is
basically a singleton for the current class loader.
This commit adds a "clearTransactionManagerCache" that is similar to the
"clearMetadataCache" introduced in CacheAspectSupport: whenever the
context is disposed, the cache is cleared to remove any reference to a
transaction manager defined by that context.
Issue: SPR-12518
SPR-11954 introduced a regression that when the "default" transaction
manager is cached, qualified transaction managers are not taken into
account anymore.
This commit rework the "determineTransactionManager" condition to
favor qualifier and "named" transaction managers. If none of these apply,
the default transaction manager is used as it should.
Also reworked the caching infrastructure so that a single cache holds
all transaction manager instances.
Issue: SPR-12541
This commit introduces test methods in CollectionFactoryTests that
demonstrate how the APIs for createCollection() and createMap() are not
type-safe, specifically regarding the use of generics, raw types, and
casting.
SPR-12483 introduced automatic type conversion support for EnumSet and
EnumMap. However, the corresponding changes in CollectionFactory
contradict the existing contract for the "create approximate" methods
by creating a copy of the supplied set or map, thereby potentially
including elements in the returned collection when the returned
collection should in fact be empty.
This commit addresses this issue by ensuring that the collections
returned by createApproximateCollection() and createApproximateMap()
are always empty.
Furthermore, this commit improves the Javadoc throughout the
CollectionFactory class.
Issue: SPR-12533
This commit introduces test methods in CollectionFactoryTests that
demonstrate how the APIs for createApproximateCollection() and
createApproximateMap() are not type-safe, specifically regarding the use
of generics, raw types, and casting.
Only compute the error message to display when the generated key is
actually null instead of using Assert.notNull as the cache operation
'toString()' method is non trivial and gets computed regardless of the
result.
Issue: SPR-12527
JUnit 4.12 created a 'public' version of the previously 'internal'
AssumptionViolatedException.
This commit upgrades Spring's Assume class to use this new public
version.
This commit introduces superfluous casts in CollectionFactory to
address a bug in Eclipse 4.4.1 that prevents the code from compiling
within Eclipse. Specifically, without these casts Eclipse displays the
following error for use of the EnumSet.copyOf() and EnumSet.noneOf()
methods:
Type mismatch: cannot convert from EnumSet<Enum<Enum<E>>> to
Collection<E>
Previously, the default reply destination could not be discovered if the
@JmsListener annotation was placed on a bean that is eligible for
proxying as the proxy method is used internally and does not reveal
an annotation placed on the implementation.
This commit makes sure to resolve the most specific method when
searching that annotation.
Issue: SPR-12513
This commit introduces the SpringHandlerInstantiator
class, a Jackson HandlerInstantiator that allows to autowire
Jackson handlers (JsonSerializer, JsonDeserializer, KeyDeserializer,
TypeResolverBuilder and TypeIdResolver) if needed.
SpringHandlerInstantiator is automatically used with
@EnableWebMvc and <mvc:annotation-driven />.
Issue: SPR-10768
Prior to this change, RestTemplate returned an empty response body if:
* HTTP return status 204 or 304
* Content-length header equals 0
This change adds a new condition for this, better supporting RFC7230
section 3.4, for connections that are closed without response body:
* No Content-length header
* No Transfer-encoding: chunked header value
* a Connection: close header value
See SPR-7911 for previous efforts in that space.
Issue: SPR-8016
With this commit, Jackson builder is now used in spring-websocket
to create the ObjectMapper instance.
It is not possible to use the builder for spring-messaging
and spring-jms since these modules don't have a dependency on
spring-web, thus they now just customize the same features:
- MapperFeature#DEFAULT_VIEW_INCLUSION is disabled
- DeserializationFeature#FAIL_ON_UNKNOWN_PROPERTIES is disabled
Issue: SPR-12293
Add a protected getFlattenedMap method to the YamlProcessor that
subclasses can use to flatten a source Map so that it has the same
entries as the Properties, but retains order.
Issue: SPR-12499
FormHttpMessageConverter incorrectly determines that the media type
"multipart/form-data; charset=utf-8" is not multipart. This commit
allows the media type to contain a charset parameter.
Previously, any @Configuration class was enhanced to namely implement
DisposableBean in order to remove static callbacks that were registered
for that class. This leads to problem if an ApplicationContext is created
and destroyed within the lifecycle on another ApplicationContext in the
same class loader.
It turns out that the destruction callback is no longer necessary as the
interceptors are now stateless: the VM is free to reclaim any of those if
necessary.
Issue: SPR-12445
Prior to this change, the ResourceUrlEncodingFilter would work well when
the application is mapped to "/". But when mapped to a non-empty servlet
context, this filter would not properly encode URLs and apply
ResourceResolver URL resolution for resources.
This commit makes sure that the lookup path is properly resolved in the
request URI, taking into account the servlet context.
Issue: SPR-12459
The removed test testConfigFileParsingErrorWhenNamedBeans() could cause
a groovyc compilation error, for example when using latest IntelliJ IDEA.
Issue: SPR-12435
Using the "quotes" substitution group by default leads to side effect
when the "*" character is used. This is especially true for AOP pointcut
or for MVC mappings.
Plain verbatim might work most of the time unless you intend to highlight
a piece of code or a comment.
Issue: SPR-12456
Upgrade undertow dependency to 1.1.0.Final.
Add support for undertow 1.1.0.Final in the
UndertowRequestUpgradeStrategy, after a breaking change in the
`io.undertow.websockets.jsr.ConfiguredServerEndpoint` constructor.
Issue: SPR-12302
SPR-12354 applied new checks to make sure that served static resources
are under authorized locations.
Prior to this change, serving static resources from Servlet 3 locations
such as "/webjars/" would not work since those locations can be within
one of the JARs on path. In that case, the checkLocation method would
return false and disallow serving that static resource.
This change fixes this issue by making sure to call the
`ServletContextResource.getPath()` method for servlet context resources.
Note that there's a known workaround for this issue, which is using a
classpath scheme as location, such as:
"classpath:/META-INF/resources/webjars/" instead of "/webjars".
Issue: SPR-12432
This commit fixes the parsing of message destinations such as
"/user/anna/queue/foo", reverting a regression introduced by SPR-11506,
which worked well with @SendToUser use cases but caused issues for
messages sent to other users.
Issue: SPR-12444
Prior to this commit, JOptCommandLinePropertySource prevented the
possibility of non-String option arguments. This effectively prevents
the use of JOpt's #ofType support (which allows specifying custom
argument types).
Now, non-String arguments are detected and converted to strings as
necessary. JOpt's #ofType now works as expected. A test has been added
to cover this case.
Without this change the plus operator would fail to
include a CHECKCAST in generated bytecode when it
was compiled in cases where one of the operands
has a runtime type of String but a statically
declared type that was not String (i.e. Object).
Issue: SPR-12426
- remove leading '/' and control chars
- improve url and relative path checks
- account for URL encoding
- add isResourceUnderLocation final verification
Issue: SPR-12354
Prior to this commit, finding out how many application contexts had
been loaded within a test suite required the use of reflection and a
bit of hacking.
This commit addresses this issue by logging ContextCache statistics
whenever an application context is loaded by the Spring TestContext
Framework (TCF).
The log output can be enabled by setting the
"org.springframework.test.context.cache" logging category to DEBUG.
Issue: SPR-12409
Prior to this change, duplicate SubProtocolHandlers could be registered
when configuring STOMP with several registrations:
public void registerStompEndpoints
(final StompEndpointRegistry registry) {
this.endpointRegistry.addEndpoint("/stompOverWebSocket");
this.endpointRegistry.addEndpoint("/stompOverSockJS").withSockJS();
}
This commit registers sub-protocols in a Set instead of a list (see
SubProtocolWebSocketHandler), thus fixing the issue.
Issue: SPR-12403
As indicated by our recent Spring Integration test failure, autowiring attempts after context closing did not fail before. After the introduction of the separately managed manualSingletonNames set, the algorithm could run into a situation where a singleton name is still in the manualSingletonNames set but not in the singletonObjects map anymore. As a remedy, destroySingletons needs to explicitly clear the manualSingletonNames set in order to remove references to non-disposable singleton beans as well (which are otherwise left in the set since individual destroySingleton calls only come in for disposable beans with destroy methods).
Issue: SPR-12404
ScheduledAnnotationBeanPostProcessor uses getBean(Class) for TaskScheduler/ScheduledExecutorService retrieval, allowing for a scheduler bean to be flagged as primary, and for a TaskScheduler bean to override a ScheduledExecutorService bean.
ContextLifecycleScheduledTaskRegistrar hooks into SmartInitializingSingleton's afterSingletonsInstantiated callback instead of ContextRefreshedEvent, as a natural consequence of SmartInitializingSingleton's introduction in Spring Framework 4.1 GA.
Prior to this commmit, any configuration class holding a CacheManager
bean would be eagerly instantiated. This is because the
CacheConfiguration infrastructure requests all beans of type
CacheManager.
This commit defers the resolution of the CacheManager as late
as possible.
Issue: SPR-12336
This commit adds an explicit support for String array for value
resolution. <util:properties> switches the 'locations' property to a
String array in 662d8aa and this broke expression evaluation.
Issue: SPR-12391
Before this change isWritable() could return true
for a badly formed expression. That is because the
decision about whether something is writable was made
based on the node type rather than whether the node
represented something that could actually be resolved
to be a real thing. This change ensures a resolution
check is done and isWritable() should only return
true if a subsequent setValue() will succeed.
Issue: SPR-10610
This commit introduces a new OriginHandshakeInterceptor. It filters
Origin header value against a list of allowed origins.
AbstractSockJsService as been modified to:
- Reject CORS requests with forbidden origins
- Disable transport types that does not support CORS when an origin
check is required
- Use the Origin request header value instead of "*" for
Access-Control-Allow-Origin response header value
(mandatory when Access-Control-Allow-Credentials=true)
- Return CORS header only if the request contains an Origin header
It is possible to configure easily this behavior thanks to JavaConfig API
WebSocketHandlerRegistration#addAllowedOrigins(String...) and
StompWebSocketEndpointRegistration#addAllowedOrigins(String...).
It is also possible to configure it using the websocket XML namespace.
Please notice that this commit does not change the default behavior:
cross origin requests are still enabled by default.
Issues: SPR-12226
These changes provide more robust handling of function
reference compilation in SpEL expressions. Prior to
this change the isCompilable check was not performing
enough visibility checks on the proposed target
function, causing bytecode to be generated that
would lead to an IllegalAccessError.
The changes also bring the argument handling for
function invocation completely inline with that used
for method invocation allowing some code to be deleted.
Many new tests are also included for function
reference compilation.
Issue: SPR-12359
Before this change the simple broker simply removed subscriptions
upon receiving a DISCONNECT message assuming it was a result of
a client STOMP WebSocket session ending.
However, if the server-side application sends a DISCONNECT to
the broker in order to terminate a session, the STOMP WebSocket
session could remain unware without any further action. This
change ensures the simple broker sends a DISCONNECT_ACK message
downstream whenever it receives a DISCONNECT.
Issue: SPR-12288
With SPR-9293, it is now possible to HTML escape text while taking into
account the current response encoding. When using UTF-* encodings, only
XML markup significant characters are escaped, since UTF-* natively
support those characters.
This commit adds a new servlet context parameter to enable this fix by
default in a Spring MVC application:
<context-param>
<param-name>responseEncodedHtmlEscape</param-name>
<param-value>true</param-value>
</context-param>
Issue: SPR-12350, SPR-12132
This commits complements 222d2b1 for another required dependency.
javax.persistence.Entity was previously required, regardless of which
aspects were actually used by the project. It is now optional and will
not break the build if it is not present. Note that the side effect is that
AnnotationDrivenStaticEntityMockingControl is disabled as well if the
JPA API is not available.
Issue: SPR-6819
Prior to this commit, a project using compile time weaving upgrading to
4.1 was forced to add spring-context-support and the jcache API in order
to build. This problem is not new really: spring-aspects holds all
aspects provided by the framework and they all are evaluated when
compiling. 4.1 just happens to define a new aspect that requires extra
dependencies.
This commit uses a new annotation of AspectJ 1.8.3. When @RequiredTypes
is added on an aspect, it is evaluated only if the classes defined on the
annotation are actually present. If they are not, the aspect is disabled
and does not break the build.
Issue: SPR-12163
This change adds a ChannelInterceptor that flips the immutable flag on
messages being sent. This allows components sending messages to leave
the message mutable for interceptors to further apply modifications
before the message is sent (and exposed to concurrency).
The interceptor is automatically added with the STOMP/WebSocket Java
and XML config and the StompSubProtocolHandler leaves parsed incoming
messages mutable so they can be further modified before being sent.
Issue: SPR-12321
During the HTTP Content Negotiation phase, the ContentNegotiationManager
uses configured ContentNegotiationStrategy(ies) to define the list of
content types accepted by the client.
When HTTP clients don't send Accept headers, nor use a configured
file extension in the request, nor a request param, developers can
define a default content type using the
ContentNegotiationConfigurer.defaultContentType() method.
This change adds a new overloaded defaultContentType method that takes a
ContentNegotiationStrategy as an argument. This strategy will take the
current request as an argument and return a default content type.
Issue: SPR-12286
Building on the initial work for SPR-12326, this commit
addresses three problems:
Firstly the ReflectiveMethodResolver is modified to consider
a direct parameter match more important than a varargs match.
Also in that same type when there are a number of close
matches, the first one is taken rather than the last one.
Secondly more testcases and better support have been added
for the case of passing a single parameter to a varargs
accepting method.
Finally it is possible to set the root context object
indirectly and not pass it on getValue() calls to the
expression objects but not all variants of getValue()
were handling that. This is now fixed.
Issue: SPR-12326
This commit adds new htmlEscape methods that take the character encoding
as a parameter. According to specs and recommendations, the list of
chars to be html escaped depends on the encoding used in the response.
If the current char encoding supports chars natively, we shouldn't
escape those; of course, reserved chars (<,>,',",&) should always be
escaped.
See: http://www.w3.org/TR/html4/sgml/entities.html#h-24.3
See: spring-projects/spring-framework#385 by @candrews
Issue: SPR-9293
The argument processing for compiling constructor references
was very basic and this fix removes that and ensures the
comprehensive logic written for method argument processing
(under SPR-12328) is now used for both method and constructor
argument handling. This fixes the reported issue and ensures
varargs constructor references can be compiled.
This also includes a couple of small fixes for the secondary
testcase reported in SPR-12326. The first is to ensure the
right root context object is used when it is passed
to getValue() indirectly through the evaluation context.
The final fix is to ensure correct boxing of primitives is
done when a method is called upon a primitive.
Issue: SPR-12326
This fix addresses a 4.1.1 regression where a raw ResponseEntity return
value (used to return potentially a different kind of body) caused an
exception.
The regression came from the fact we now try to render a null body in
order to give ResponseBodyAdvice a chance to substitute a different
value. That in turn means we have to try to determine the body type
from the method signature.
This change improves the logic for extracting the generic parameter
type to accommodate a raw ResponseEntity class. Also we avoid raising
HttpMediaTypeNotAcceptableException if the value to be rendered is
null.
Issue: SPR-12287
Commit https://github.com/spring-projects/spring-framework/commit/2b97d6
introduced a change where the path within the DispatcherServlet is
determined with each call to ResourceUrlProvider.getForRequestUrl.
To avoid repeating that every time a URL is encoded through the
response, we now cache the result of the lookupPath determination in
ResourceUrlEncodingFilter.
Issue: SPR-12332
The use of the HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE
in ResourceUrlProvider (as a way of saving lookup path determination)
leads to incorrect results. For example when the request is forwarded
the current requestUri may no longer be compariable to the value of the
PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE. Also where the request is mapped
using a pattern, the value of PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE is
not the same as the lookup path.
This change removes the use of the attribute from ResourceUrlProvider
and instead always determines the lookup path when getForRequestUrl
is called.
Issue: SPR-12332
This change introduces support for compilation of expressions
involving inline lists, string concatenation and method
invocations where the method being invoked is declared
with a varargs parameter. It also fixes a problem with
compiling existing method invocations where the target
method is on a non public type.
Issue: SPR-12328
Before this change, the type of asynchronously produced return values
(e.g. Callable, DeferredResult, ListenableFuture) could not be
properly determined with an actual resulting value of null. Or even
with an actual value returned, the generic type could not be properly
determined. This change fixes both of those issues.
Issue: SPR-12287
Prior to this commit, the cache operation metadata cache was not
updated for a method not using the JCache annotations. This means
that every execution of said method was going through the process
of identifying if it was using the cache or not.
This commit adds a default placeholder identifying the absence of
metadata; this allows to flag such method as not having any metadata
at all.
Issue: SPR-12337
The getForRequestUrl method of ResourceUrlProvider uses the
HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE attribute to
determine the relevant portion of the resource URL path.
However there are cases when that attribute may not have a leading
(e.g. when the current URL was matched to a prefix-based pattern
and hence extracted via PathMatcher#extractPathWithinPattern), which
interferes with the matching of resource URL paths to patterns.
This change ensures a leading slash is present
Issue: SPR-12281
Snake YAML allows for duplicate keys in map nodes. See
https://code.google.com/p/snakeyaml/issues/detail?id=199
This commit uses a dedicated Constructor extension that explicitly
checks for such duplicate keys.
Issue: SPR-12318
The resourceHandlerMapping in the MVC Java config is not configured
with any interceptors, and in particular those added through the
InterceptorRegistry, which are otherwise added to all other handler
mapping beans created by the config. This means that the
ResourceUrlProviderExposingInterceptor (added in 4.0) is also not
used for resource requests.
This change ensures the ResourceUrlProviderExposingInterceptor is
configured on the resourceHandlerMapping.
Issue: SPR-12279
The WebSocketMessageBroker config now allows wrapping the
SubProtocolWebSocketHandler to enable advanced use cases that may
require access to the underlying WebSocketSession.
Issue: SPR-12314
This change adds a new XhrTransport for the SockJs client
implementation. This transport is based on `UndertowClient`,
Undertow's HTTP client.
Note that this transport can be customized with an OptionMap that is
used by the Xnio worker backing the I/O communications (see
http://xnio.jboss.org).
Implementation tested with undertow 1.0.36, 1.1.0.RC3, 1.2.0.Beta1.
Issue: SPR-12008
This change adds a "Vary: Origin" HTTP response header for /info and
/iframe SockJS endpoints.
This is preventing proxies and browsers from caching a response and
reusing it for an invalid Origin.
Reference: https://groups.google.com/forum/#!topic/sockjs/svsLWRorSis
Issue: SPR-12310
This commit adds support for direct Jackson mix-in annotations registration in
Jackson2ObjectMapperFactoryBean and Jackson2ObjectMapperBuilder.
Issue: SPR-12144
Prior to this commit, the getter methods in MockServletContext threw an
UnsupportedOperationException when trying to retrieve Servlet and
Filter registrations.
This commit improves the behavior of these methods by returning null
when a single registration is requested and an empty map when all
registrations are requested. This is now in line with the Javadoc for
ServletContext. Note, however, that the corresponding setter methods
still throw UnsupportedOperationExceptions which is suitable behavior
for a mock.
Issue: SPR-12290
The ternary expression node was failing to generate the
necessary unboxing bytecode when the condition part
of the expression returned a boxed Boolean rather than
a primitive boolean.
Also fixed here is an IllegalAccessError that was
seen in the same expression due to generating a
CHECKCAST bytecode for a private type.
Issue: SPR-12271
Prior to this commit, the ResolvableType static cache was holding a lot
of duplicates for simple types. We are using too much metadata to compute
the key when the class has no generic information. so setFoo(String foo)
and setBar(String bar) would result in two entries in the cache because
the TypeProvider is different. On a very simple application 65% of the
entries in the cache were duplicate.
When the type is a Class with no generic information, the ResolvableType
instance is a simple wrapper around it so we might just as well not cache
it at all as the cost of finding it back from the cache is higher than
creating that simple wrapper.
This commit adds an explicit check; if the type is a simple Class we just
return a "resolved" ResolvableType instance for it. On a few test cases,
this reduces the size of the cache by 85%
Issue: SPR-12275
Prior to this commit, `AntPathMatcher.extractPathWithinPattern` would
not process correctly `**` patterns and would only match *one* path
segment in the given path.
This commit changes `extractPathWithinPattern` to allow multiple path
segments to be matched against a single `**` pattern segment.
Issue: SPR-10515
Jackson2ObjectMapperBuilder now allows to create ObjectMapper and XmlMapper
instances easily thanks to its fluent API.
This builder is used in Jackson message converters and views to instantiate default
ObjectMapper and XmlMapper.
This commit also add a createXmlMapper property to
Jackson2ObjectMapperFactoryBean in order to allow to create easily a XmlMapper
instance.
Issue: SPR-12243
When not ViewResolver's have been registered, detect if the context
contains any other ViewResolver beans. If not, add InternalResourceVR
to match default DispatcherServlet behavior.
Issue: SPR-12267
Commit 6a04831 introduced a regression that lead to burst recovery
attempts when the broker is up but the listener is failing for some
reason (the most obvious one being that the destination does not
exist).
Since the sleep period between recovery attempts strategy is more
complex, we can't just sleep for a period of time. But we can create
an execution and apply it once which should work just fine for most
use cases.
Issue: SPR-12183
The new contract allows registration of interceptors with any
MessageChannel implementation hierarchy -- for example the one in the
Spring Framework or the one in Spring Integration.
When a DISCONNECT is sent to the broker, we proactively close the TCP
connection unless the DISCONNECT has a receipt header. Depending on
the timing, the broker may also close the connection on its side.
That appears to cause an exception in reactor on the CI server, e.g.:
https://build.spring.io/browse/SPR-PUB-JOB1-1715/test/case/135247530
This change traps the exceptions and prevents it from propagating.
This change uses a ChannelInterceptor (inserted at index 0) to detect
when a DISCONNECT message is precluded from being sent on the
clientInboundChannel. This can happen if another interceptor allows
a runtime exception out from preSend or returns false.
It is crucial for such messages to be processed, so when detected
they're processed still.
Issue: SPR-12218
This commit ensures that single quotes nested in double quotes in
code examples in the reference manual are properly escaped using ''.
Issue: SPR-12246
WebSocket clients going away is an expected and common occurance.
Logging at ERROR level on failure to close a connection or on failures
to write data to a WebSocket sessions has a high potential for false
positives with very little to do. This change lowers the log level for
a number of log messages that fit this category.
This should be helped by the effort already spent for 4.1 to ensure
logging at DEBUG level doesn't produce excessive amounts of logging.
Issue: SPR-12155
Refine the logic introduced in commit 71c6eb2b so that additional
imported @Configuration classes are not considered as candidates if
they have already been parsed.
Issue: SPR-12233
Prior to this commit, the `ProtobufHttpMessageConverter` would call
`outputMessage.getBody()` at the beginning of the `writeInternal`
method, thus writing HTTP headers. Since this method is trying to write
"x-protobuf" headers after that, protobuf support wasn't working
properly for the default "x-protobuf" media type.
Thanks Toshiaki Maki for the repro project!
Also fixed:
* improve `MockHttpOutputMessage` behavior to reproduce the read-only
state of HTTP headers once they've been written.
Issue: SPR-12229
Update PathMatchingResourcePatternResolver to include additional
protected methods that can be used by subclasses to optimize which
JARs are searched.
Issue: SPR-12231
Update SystemEnvironmentPropertySource to attempt optimized Map lookups
first, and only fall-back to the defensive SecurityManager safe-mode
if these fail.
Issue: SPR-12224
This change defers determination of whether to invoke a message
converter in case of a null @ResponseBody value (or ResponseEntity with
a null body) until after the invocation of the ResponseBodyAdvice
chain. This allows a ResponseBodyAdvice to handle null values
potentially turning them into non-null value.s
Issue: SPR-12152
This change extends the "websocket" scope to ApplicationContext events
published from StompSubProtocolHandler. This however will only work
with ApplicationEventMulticaster that multicasts events in the same
thread.
Issue: SPR-12172
Refine property source ordering so that sources already contained in the
environment remain before those added by @PropertySource annotations.
Issue: SPR-12198
Update JndiLocatorDelegate.isDefaultJndiEnvironmentAvailable() to
call `getEnvironment()` on the `InitialContext` in order to actually
trigger a NamingException if JNDI is not available.
Issue: SPR-12223
Update ConditionEvaluator to collect then sort Conditions before
evaluation. By annotating Conditions with @Ordered expensive operations
can be pushed to the back of the queue.
Issue: SPR-12219
Per the Javadoc for the SocketUtils() constructor, SocketUtils can be
instantiated as a Spring Bean in XML configuration files; however,
SocketUtils is currently abstract which prevents such usage.
This commit removes the 'abstract' declaration thereby allowing
SocketUtils to be instantiated as a Spring bean.
Issue: SPR-12169
Prior to this change, getForRequestUrl implementation would only work
for applications with a non-empty servlet path. So web applications
mapped to "/" would trigger a IllegalStateException while checking the
current request against the request path within the current mapping.
This change relaxes this and only check that the path within mapping is
within the request URL.
Issue: SPR-12158
This change moves the resource-cache configuration to the
<resource-chain/> tag, since enabling/disabling resource cache should
be driven by a property or a SpEL expression.
So now that configuration can be set with XML attributes:
<mvc:resource-chain resource-cache="true"
cache-manager="resourceCache" cache-name="test-resource-cache">
In order to mirror the JavaConfig behavior, the "resource-cache"
attribute is required.
Issue: SPR-12129
Before this change ResourceUrlProvider used getUrlMap to detect
ResourceHttpRequestHandler instances, however the map may contain bean
names as is the case when using <mvc:resources>. Instead it now uses
getHandlerMap.
This change adds a ResourceUrlProvider bean to the
ResourceBeanDefinitionParser to match the same in the Java config.
For consistency the name of the bean in the Java config is renamed.
Also a ResourceUrlProviderExposingInterceptor is declares as a global
MappedInterceptor.
Prior to this change, ResourceTransformers that transformed resources by
updating the links to other resources, worked only if links were
relative to the resource being transformed.
For example, when the CssLinkResourceTransformer rewrote links within
a "main.css" resource, only links such as "../css/other.css" were
rewritten.
Using relative links is a recommended approach, because it's totally
independent from the application servlet path, context path, mappings...
This change allows absolute links to be rewritten by those Transformers,
provided those links are accurate and point to existing resources.
Issue: SPR-12137
Update ImportRegistry to track all import registrations that occur
against an importing class (rather than just keeping the last). In
addition, prune imported classes from the registry when a configuration
class is removed during the REGISTER_BEAN ConfigurationPhase.
This update prevents incorrect metadata from being injected into an
ImportAware class which is imported twice by different configurations
classes (when one of the configuration classes will be ultimately skipped
due to a @Condition).
Issue: SPR-12128
This change adds the artifacts names in the Spring Framework Modules
documentation. Linking both concepts make it easier to decide which
Spring module should be importer in an application's build.
Issue: SPR-11534
This commit allows to use place holder definitions for JmsListener
attributes, effectively allowing to externalize those settings from
the code.
Issue: SPR-12134
This commit restructures the content of the "TestExecutionListener
registration and ordering" section of the Testing chapter in the
reference manual into cross-referenced subsections with more
appropriate titles.
In addition, this commit introduces a new "Merging
TestExecutionListeners" subsection which documents the new MergeMode
feature in @TestExecutionListeners, including an example demonstrating
the MERGE_WITH_DEFAULTS mode.
Issue: SPR-12083
This commit introduces a new "TestExecutionListener registration and
ordering" section in the Testing chapter of the reference manual.
Issue: SPR-12082
This commit introduces a new "Programmatic transaction management"
section in the Testing chapter of the reference manual with an example
highlighting the new support provided via TestTransaction.
In addition, this commit begins the work to be addressed more
thoroughly in SPR-11399 by overhauling the entire "Transaction
management" section with in-depth discussions on the following topics.
- Test-managed transactions
- Enabling and disabling transactions
- Transaction rollback and commit behavior
- Executing code outside of a transaction
- Configuring a transaction manager
Issue: SPR-11941, SPR-11399
This commit introduces a new "Context configuration with test property
sources" section in the Testing chapter of the reference manual.
In addition, the "Context caching" section has been updated regarding
support for test property source locations and properties in
MergedContextConfiguration.
Issue: SPR-12076
This commit documents support for using Groovy scripts to load
ApplicationContexts using the Spring TestContext Framework (TCF) in the
reference manual.
Issue: SPR-12027
- Introduced a new "Executing SQL scripts" section in the Testing
chapter with a subsection covering programmatic script execution via
ResourceDatabasePopulator, ScriptUtils, etc. and a subsection
dedicated to the new declarative support via @Sql.
- Documented @Sql, @SqlConfig, and @SqlGroup in the "Annotations" and
"Meta-annotation" sections.
- Fixed broken cross-reference links to "false positives" with ORM tip.
- Documented methods in JdbcTestUtils.
- Improved layout and information in sections covering
AbstractTransactionalJUnit4SpringContextTests and
AbstractTransactionalTestNGSpringContextTests.
Issue: SPR-11849
Prior to this commit, the discussion of JUnit vs. Spring with regard to
timeout support in tests erroneously claimed that Spring's support for
JUnit's @Test(timeout=...) did not include set up and tear down or
repetitions. This information, however, was based on a previous version
of SpringJUnit4ClassRunner and is no longer valid.
This commit revises the affected section of the testing chapter in the
reference manual accordingly.
This commit changes the way a <mvc:resource-cache> can be configured
with a user defined Cache instance.
Now a reference to a CacheManager Bean and a Cache name must be
provided. This is a more flexible configuration for typical XML setups.
<mvc:resource-cache
cache-manager="resourceCache"
cache-name="test-resource-cache"/>
Issue: SPR-12129
With the new ResourceResolver abstraction and resource resolver chain
in 4.1, the assumption that resources are found by checking for the URL
path under the configured locations is no longer accurate.
A custom ResourceResolver could find resources in ways that don't
depend on a list of locations.
Issuse: SPR-12133
This change introduces a new <mvc:resource-chain/> tag that mirrors
the ResourceChainRegistration java config counterpart.
Resolvers and Transformers can be registered with bean/ref tags, and
specific tags have been created for <mvc:version-resovlver> and
<mvc:resource-cache> in order to make common configurations easier.
Note that a specific "auto-configuration" attribute on the
resource-chain allows to completely disable default registration of
Resolvers and Transformers (sane defaults considered by the Framework).
<mvc:resources mapping="/resources/**" location="/, classpath:/META-INF/">
<mvc:resource-chain>
<mvc:resource-cache cache="resourceCache"/>
<mvc:resolvers>
<mvc:version-resolver>
<mvc:fixed-version-strategy version="abc" patterns="/**/*.js"/>
<mvc:content-version-strategy patterns="/**"/>
</mvc:version-resolver>
</mvc:resolvers>
<mvc:transformers>
<bean class="org.springframework.web.servlet.resource.AppCacheManifestTransformer"/>
</mvc:transformers>
</mvc:resource-chain>
</mvc:resources>
This also fixes a typo in the class name of
AppCacheManifestResourceTransfo*r*mer.
Issue: SPR-12129
Prior to this commit, AssertThrows in the spring-test module only
supported Exception; however, there are legitimate test cases where the
subject under test (SUT) may potentially throw a subclass of Throwable.
This commit refactors AssertThrows so that it supports exceptions of
type Throwable instead of the limiting support for Exception.
Furthermore, AssertThrows has been refactored to use generics (e.g.,
Class<? extends Throwable> instead of merely Class).
Issue: SPR-6362
This commit makes it possible to specify port with an URI template variable.
For example :
RestTemplate restTemplate = new RestTemplate();
restTemplate.getForObject("http://localhost:{port}/resource", String.class, 8080);
Issue: SPR-12123
This change separates out resource chain related methods previously in
ResourceHandlerRegistration into a new class ResourceChainRegistration
with the goal of improving readability.
Along with that, the registration of caching resolver and transformer
is now explicitly controled with a boolean flag (on the method used
to obtain the ResourceChainRegistration) and an overloaded method
also allows providing a Cache instance.
Issue: SPR-12124
This change moves the VersionStrategy builder-style methods from
ResourceHandlerRegistration to VersionResourceResolver.
This makes the methods more universally usable and also makes use of
ResourceHandlerRegistration more readable, i.e. simply a sequence of
addResource and addTransformer calls.
Prior to this commit the implementation of isSecure() in
MockHttpServletRequest simply returned the value of the 'secure'
boolean flag. Thus setting the scheme to 'https' had no effect on the
value returned by isSecure() even though most non-mock implementations
(e.g., Tomcat, Jetty, etc.) base the return value on the actual scheme
in the request.
This commit makes the behavior of MockHttpServletRequest.isSecure()
more intuitive by honoring both the 'secure' boolean flag and the
current value of the scheme.
Issue: SPR-12098
The ResourceHandlerRegistration now checks if the last resolver is an
instance of PathResourceResolver and if so it skips adding it.
This change also creates and adds the VersionResourceResolver (as well
as CssLinkTransformer) the first time any VersionStrategy is
registered. This ensures that custom resolvers (including an extension
of PathResourceResolver) may be added both before and after the
VersionResourceResolver.
Lastly this change renames addVersion and addVersionHash to be
consistent with addVersionStrategy.
Issue: SPR-12124
Prior to this commit, setting the parameters used to build the caches
was fragile in static mode as the caches were created right when the
setCacheNames setter was called.
This commit provides a better handling of such arguments and also
provide a way to restore the dynamic mode if necessary.
Issue: SPR-12120
This commit updates the documentation to mention that the #result
object is available in the SpEL context for computing the key to use
for a @CachePut operation.
Issue: SPR-12125
Prior to this commit, when there was a lot of entries in the
ResolvableType.cache HashMap, getting a simple value could
take a lot of time due to a lot of calls to ResolvableType.equals().
ResolvableType.equals() used this.type, getSource(),
this.variableResolver.getSource() and this.componentType, but
ResolvableType.hashCode() used only this.type.
With this commit, ResolvableType.hashCode() now uses the same
fields than ResolvableType.equals().
Performance on the spring-resolvabletype-benchmark project:
- 8000 us before this commit
- 120 us with this commit
Issue: SPR-12122
Prior to this commit, it was unclear that it was possible to register
custom MIME types when using MockServletContext.
This commit updates the Javadoc for MockServletContext.getMimeType()
with an example of how to achieve this using the MimetypesFileTypeMap
from the Java Activation Framework.
Issue: SPR-12126
This commit updates the Gradle build to ensure that *all* source
artifacts are including in published 'sources' jars.
To achieve this, we are now assembling 'sources' jars from
'sourceSets.main.allSource' and not explicitly including or excluding
anything by default.
Issue: SPR-12085
This change enables the ability to configure
ViewNameMethodReturnValueHandler & ModelAndViewMethodReturnValueHandler
with patterns to use to test for a custom redirect view name.
Issue: SPR-12054
This commit replace the two empty "chapters" dedicated to profiles
and property source to an 'Environment abstraction' chapter that
covers both.
Issue: SPR-12107
Rework the @PropertySource parsing logic recently changed in commit
7c608886 to deal with the same source appearing on a @Configuration
class and an @Import class.
Processing now occurs in a single sweep, with any previously added
sources being converted to a CompositePropertySource.
Issue: SPR-12115
Other PropertySources and in particular @ComponentScan can benefit from previously declared property sources on the same configuration class.
Issue: SPR-12110
Issue: SPR-12111
Prior to this commit, the getServerName() and getServerPort() methods
in MockHttpServletRequest simply returned the 'mocked' serverName and
serverPort but ignored the 'Host' header entirely. Per the Servlet
specification, however, these methods must parse the server name or
port from the 'Host' header if it is present and otherwise fall back to
the resolved server name or port.
This commit fixes this by ensuring that getServerName() and
getServerPort() properly parse the server's name or port from the
'Host' header if it is present in the request. If the 'Host' header is
not present, MockHttpServletRequest falls back to returning the
'mocked' serverName and serverPort.
Issue: SPR-12088
Prior to this commit, spring-build-src and spring-framework-bom
internal artifacts were published as part of the distribution bundle.
This commit excludes those project so that those unnecessary artifacts
are no longer shipped.
Issue: SPR-12087
Prior to this commit, only @Async annotated methods with proxy style
had an explicit support for ListenableFuture. This commit brings that
support to AspectJ as well.
Issue: SPR-12092
Prior to this commit, only @Async annotated methods with proxy style
had their custom uncaught exception handler applied. This commit
harmonizes the configuration so that AspectJ applies that behaviour as
well.
Issue: SPR-12090
In our Gradle build script, we are now assembling 'sources' jars from
'sourceSets.main.allSource' in order to include Java, Groovy, and
AspectJ source code as well all other appropriate classpath resources.
Issue: SPR-12086
This commit updates the Gradle build to ensure that the following are
including in published 'sources' jars.
- Java source code (previously supported)
- AspectJ source code (previously supported)
- META-INF/spring.factories
- META-INF/services/*
- Java Properties files
- XML files
- MIME types files (mime.types)
Issue: SPR-12085
Prior to this commit, if a custom TestExecutionListener was registered
via @TestExecutionListeners the defaults would not be registered. Thus,
if a user wanted to declare a custom listener and use the default
listeners, the user was forced to manually declare all default
listeners in addition to any custom listeners. This unfortunately
required that the user know exactly which listeners were registered by
default. Moreover, the set of default listeners can change from release
to release, and with the support for automatic discovery of default
listeners introduced in SPR-11466 it is no longer even possible to know
what the set of default TestExecutionListeners is before runtime.
This commit addresses this issue by introducing a mechanism for merging
custom declared listeners with the defaults for the current
environment. Specifically, @TestExecutionListeners supports a new
MergeMode that is used to control whether or not explicitly declared
listeners are merged with the default listeners when
@TestExecutionListeners is declared on a class that does not inherit
listeners from a superclass.
Issue: SPR-8854
Prior to this commit, there was no declarative mechanism for a custom
TestExecutionListener to be registered as a default
TestExecutionListener.
This commit introduces support for discovering default
TestExecutionListener implementations via the SpringFactoriesLoader
mechanism. Specifically, the spring-test module declares all core
default TestExecutionListeners under the
org.springframework.test.context.TestExecutionListener key in its
META-INF/spring.factories properties file, and third-party frameworks
and developers can contribute to the list of default
TestExecutionListeners in the same manner.
- AbstractTestContextBootstrapper uses the SpringFactoriesLoader to
look up the class names of all registered default
TestExecutionListeners and sorts the instantiated listeners using
AnnotationAwareOrderComparator.
- DefaultTestContextBootstrapper and WebTestContextBootstrapper now
rely on the SpringFactoriesLoader mechanism for finding default
TestExecutionListeners instead of hard coding fully qualified class
names.
- To ensure that default TestExecutionListeners are registered in the
correct order, each can implement Ordered or declare @Order.
- AbstractTestExecutionListener and all default TestExecutionListeners
provided by Spring now implement Ordered with appropriate values.
- Introduced "copy constructors" in MergedContextConfiguration and
WebMergedContextConfiguration
- SpringFactoriesLoader now uses AnnotationAwareOrderComparator
instead of OrderComparator.
Issue: SPR-11466
Prior to this commit, if both locations and classes were declared via
@ContextConfiguration at differing levels in a test class hierarchy,
the exception message stated that neither of the default context
loaders was able to load an ApplicationContext from the merged context
configuration, but the message didn't explain why.
This commit adds an explicit check for such scenarios and provides a
more informative exception message similar to the following:
"Neither X nor Y supports loading an ApplicationContext from
[MergedContextConfiguration ...]: declare either 'locations' or
'classes' but not both."
Issue: SPR-12060
Spring Framework 3.1 introduced an Environment abstraction with support
for hierarchical PropertySources that can be configured
programmatically as well as declaratively via the @PropertySource
annotation. However, prior to this commit, there was no way to
declaratively configure PropertySources in integration tests in the
Spring TestContext Framework (TCF).
This commit introduces declarative support for PropertySources in the
TCF via a new class-level @TestPropertySource annotation. This
annotation provides two options for declaring test property sources:
- The 'locations' attribute allows developers to declare external
resource locations for test properties files.
- The 'properties' attribute allows developers to declare inlined
properties in the form of key-value pairs.
Test properties files are added to the Environment before all other
property sources and can therefore override system and application
property sources. Similarly, inlined properties are added to the
Environment before all other property sources and can therefore
override system property sources, application property sources, and
test properties files.
Specifically, this commit introduces the following major changes:
- Introduced @TestPropertySource annotation along with internal
TestPropertySourceAttributes, MergedTestPropertySources, and
TestPropertySourceUtils for working with test property sources
within the TCF.
- All TestContextBootstrappers have been modified to support the
merged property resource locations and inlined properties from
@TestPropertySource.
- MergedContextConfiguration (and consequently the context caching
key) is now additionally based on the merged property resource
locations and inlined properties from @TestPropertySource. The same
applies to WebMergedContextConfiguration.
- AbstractContextLoader's prepareContext() method now adds
PropertySources for all resource locations and inlined properties
from the supplied MergedContextConfiguration to the Environment of
the supplied ApplicationContext. All subclasses of
AbstractGenericContextLoader and AbstractGenericWebContextLoader
therefore automatically provide support for @TestPropertySource.
Issue: SPR-12051
This commit adds support for XML serialization/deserialization based on
the jackson-dataformat-xml extension. When using @EnableWebMvc or
<mvc:annotation-driven/>, Jackson will be used by default instead of JAXB2
if jackson-dataformat-xml classes are found in the classpath.
This commit introduces MappingJackson2XmlHttpMessageConverter and
MappingJackson2XmlView classes, and common parts between JSON
and XML processing have been moved to AbstractJackson2HttpMessageConverter
and AbstractJackson2View classes.
MappingJackson2XmlView supports serialization of a single object. If the model
contains multiple entries, MappingJackson2XmlView.setModelKey() should be
used to specify the entry to serialize.
Pretty print works in XML, but tests are not included since a Woodstox dependency
is needed, and it is better to continue testing spring-web and spring-webmvc
against JAXB2.
Issue: SPR-11785
This release contains the following new features:
- The new @JsonAdapter annotation to specify a Json TypeAdapter for a
class field
- JsonPath support: JsonParser.getPath() method returns the JsonPath
expression
- New public methods in JsonArray (similar to the java.util.List):
contains(JsonElement), remove(JsonElement), remove(int index),
set(int index, JsonElement element)
- Many other smaller bug fixes
See: https://groups.google.com/forum/#!topic/google-gson/MOqf5RGtIzk
This commit configures the SonarRunner plugin so that SonarQube can
be used against the project. A few customizations were applied to
namely exclude the asm and cglib repackaged classes.
Issue: SPR-10766
This commit also turns MessagingException into a NestedRuntimeException subclass which delivers a root message that has the cause message appended to it. That's a common expectation with the use of Spring exceptions since all of our exception hierarchies have historically been designed that way.
Issue: SPR-12064
Issue: SPR-12038
Analogous to HibernateTransactionManager, there is a "prepareConnection" flag on HibernateJpaDialect which allows for overriding the actual mode of operation. This is easily accessible from HibernateJpaVendorAdapter now which declares HibernateJpaDialect from its getJpaDialect() method.
Issue: SPR-8959
Issue: SPR-11942
Replace references to the old RFC 2616 (HTTP 1.1) with references
to the new RFCs 7230 to 7235.
This commit also deprecates:
- HttpStatus.USE_PROXY
- HttpStatus.REQUEST_ENTITY_TOO_LARGE in favor of HttpStatus.PAYLOAD_TOO_LARGE
- HttpStatus.REQUEST_URI_TOO_LONG in favor of HttpStatus.URI_TOO_LONG
Issue: SPR-12067
This commit introduces the ability to specify an inline map in
an expression. The syntax is similar to inline lists and of
the form: "{key:value,key2:value}". The keys can optionally
be quoted. The documentation is also updated with information
on the syntax.
Issue: SPR-9472
Prior to this commit, given an enum which implements some interface,
GenericConversionService would select the String -> Enum converter even
if a converter for String -> SomeInterface was registered. This also
affected converters that were registered for String ->
SomeBaseInterface, when SomeInterface extended SomeBaseInterface.
This change modifies the behavior of the private method
getClassHierarchy() by placing Enum.class as late as possible, pretty
much the same way as Object.class is handled.
Issue: SPR-12050
Prior to this commit, the schema distribution archive contains
duplicate entries for the more recent XSD as it is reference both with
its version and as the "default" XSD (i.e. without a version).
This commit configures the task to apply a duplicatesStrategy so that
only the first entry remains.
Issue: SPR-12011
Surprisingly until now the MockMvcRequestBuilders did not have methods
for HTTP HEAD. This change adds such methods to the API making it
consistent with other HTTP method types.
Issue: SPR-12055
This change adds new methods in the ResourceHandlerRegistration API
for registering ResourceResolvers and ResourceTransformers, allowing
to better handle server-side resources in web applications.i
Here is an example of configuration for an HTML5 web application
that uses JavaScript and HTML5 appcache manifests:
registry.addResourceHandler("/**")
.addResourceLocations("classpath:static/")
.addTransformer(new AppCacheManifestTransfomer())
.addVersion("v1", "/**/*.js")
.addVersionHash("/**");
Issue: SPR-11982
This commit moves JmsHandlerMethodFactory and its default
implementation to the messaging abstraction. Working on a similar
support for AMQP revealed that this factory has nothing that is JMS
specific and is exactly identical in the case of AMQP.
Issue: SPR-12053
Before this change the SockJsWebSocketHandler precluded determination
of the sub-protocols by wrapping the actual target handler.
After this change SockJsWebSocketHandler implements SubProtocolCapable
and returns the list of sub-protocols from the wrapped handler.
There is special handling for SpEL expressions involving a map
and an unquoted string literal key (e.g. mymap[key1]). SpEL does
not require key1 to be quoted. This special handling which is done
in Indexer getValueRef() was not being also done in the Indexer
generateCode() method that compiles the expression. Also fixed
a problem where the key was not being compiled in a new
sub scope. Without the new scope the key expression was failing
to reload the relevant context object when it needed it.
Issue: SPR-12045
This commit allows the SpEL compiler to cope with generic methods
being used in expressions involving numeric operands. Due to the
use of unbound type variables the methods may look like they
return Object but in fact they are returning objects of a numeric
type that are suitable for compilation. The changes here ensure
the runtime types are looked at if the discovered declared types
are not providing enough information. This impacts all the
operands involving numerics (mathematical and relational).
Issue: SPR-12040
This commit introduces MessagingExceptionTranslator, a messaging
exception translation infrastructure similar to what
PersistenceExceptionTranslator provides.
JmsMessagingTemplate does not throw raw JmsException anymore but
translates those to an instance of Spring's MessagingException
hierarchy.
Issue: SPR-12038
This commit updates the Javadoc for getLocale() and getLocales() in
MockHttpServletRequest to point out that the mock implementation does
not comply with the the Servlet specification with regard to the
Accept-Language header.
Issue: SPR-12043
This commit updates the class-level Javadoc for MockHttpServletRequest
with information regarding the default locale for the mocked server.
Issue: SPR-11701
If a resource location in the MergedContextConfiguration has a ".xml"
extension, the GenericGroovyXmlContextLoader now delegates to a
dedicated XmlBeanDefinitionReader for loading bean definitions from that
resource, thus preserving XML validation for all XML resource locations.
For all other extensions (presumably only ".groovy"), the
GenericGroovyXmlContextLoader delegates to a GroovyBeanDefinitionReader.
Issue: SPR-11233
This commit updates JmsMessagingTemplate to support the
MessageRequestReplyOperation interface that provides synchronous
request/reply operations.
As JmsMessagingTemplate delegates everything under the scenes to
JmsTemplate, the latter has been updated as well to offer such lower
level operation.
Issue: SPR-12037
This change creates an AbstractTyrusRequestUpgradeStrategy shared
between the WebLogic and GlassFish sub-classes.
The version of Tyrus is lowered to 1.3.5 to match the version used
in WebLogic (12.1.3) and that in turn requires a little extra effort
in the base AbstractTyrusRequestUpgradeStrategy to make up for
changes that have taken place from Tyrus 1.3.5 to 1.7.
Issue: SPR-11293
Spring Framework 4.0 introduced first-class support for a Groovy-based
DSL for defining the beans for an ApplicationContext. However, prior to
this commit, the Spring TestContext Framework (TCF) did not provide any
out-of-the-box support for using Groovy scripts as path-based resource
locations when loading an application context for tests.
This commit addresses this issue by introducing first-class support for
using Groovy scripts to load the ApplicationContext for integration
tests managed by the TCF. Specifically, the following changes have been
made in the TCF to support Groovy scripts.
- Introduced getResourceSuffixes() in AbstractContextLoader in order
to support multiple resource suffixes in the default detection
process. This feature is used by the new Groovy/Xml context loaders.
- Introduced GenericGroovyXmlContextLoader and
GenericGroovyXmlWebContextLoader which support both Groovy scripts
and XML config files for loading bean definitions. Furthermore,
these loaders support "-context.xml" and "Context.groovy" as
resource suffixes when detecting defaults. Note that a default XML
config file will be detected before a default Groovy script.
- DelegatingSmartContextLoader and WebDelegatingSmartContextLoader now
use reflection to choose between using GenericGroovyXmlContextLoader
and GenericGroovyXmlWebContextLoader vs. GenericXmlContextLoader and
GenericXmlWebContextLoader as their XML loaders, depending on
whether Groovy is present in the classpath.
- Groovy scripts can be configured via the 'locations' or 'value'
attributes of @ContextConfiguration and can be mixed seamlessly with
XML config files.
Issue: SPR-11233
This change provides WebSocket support for the upcoming Glassfish 4.0.1
release while at the same dropping support for Glassfish 4.0 due to
incompatible changes.
Issue: SPR-11094
Before this change the DefaultHandshakeHandler by default passed the
list of requested WebSocket extensions as-is relying on the WebSocket
engine to remove those not supported.
This change ensures that WebSocket extensions not supported by the
runtime are proactively removed instead.
This change is preparation for SPR-11094.
This commit fixes a potential NPE when determining the priority of a
bean instance in case multiple candidates exist and no bean was marked
as @Primary
Issue: SPR-12024
This change adds a new HttpMessageConverter supporting
Google protocol buffers (aka Protobuf).
This message converter supports the following media types:
* application/json
* application/xml
* text/plain
* text/html (output only)
* and by default application/x-protobuf
Note, in order to generate Proto Message classes, the protoc binary
must be available on your system.
Issue: SPR-5807/SPR-6259
Before this change if Velocity Spring form macro was bound to a path
which contains square brackets, those brackets would also appear in id
of generated tag, making the id invalid.
As of this fix all Velocity Spring form macros generate tag with id
that does not contain square brackets.
Issue: SPR-5172
This is a follow-up on the commit introducing MockMvcConfigurer:
https://github.com/spring-projects/spring-framework/commit/c2b0fac852dd9f865699fb374ad78543767fec05
This commit refines the MockMvcConfigurer contract to use (the new)
ConfigurableMockMvcBuilder hence not requiring downcasting to
AbstractMockMvcBuilder.
The same also no longer passes the "default" RequestBuilder which would
also require a downcast, but rather allows a RequestPostProcessor to be
returned so that a 3rd party framework or application can modify any
property of every performed MockHttpServletRequest.
To make this possible the new SmartRequestBuilder interface separates
request building from request post processing while the new
ConfigurableSmartRequestBuilder allows adding a RequestPostProcessor
to a MockMvcBuilder.
Issue: SPR-11497
This change adds support for configuring redirect view controllers and
also status controllers to the MVC Java config and the MVC namespace.
Issue: SPR-11543
This change makes it possible to configure RedirectView such that the
query string of the current request is added to the target URL.
This change is preparation for SPR-11543.
This change two new capabilities to ParameterizableViewController:
- configure a View instance (in addition to view name)
- configure response status code
The status code may be useful to send a 404 while also writing to the
body using a view.
The status code may also be used to override the redirect status code
of RedirectView. Even today it's possible to configure a "redirect:"
prefixed view name but the status code could not be selected. When a
3xx status is set, the code is passed on to the RedirectView while the
view name is automatically prefixed with "redirect:" (if not already).
For full control over RedirectView it is now also possible to
parameterize the controller with a View instance.
As one more possible resulting variation, given status 204 and no view
the request is considered handled (controller returns null).
This change is preparation for SPR-11543.
Since the MVC Java config always registers a ViewResolver (composite)
bean, at a very minimum we must add an InternalResourceViewResolver
consistent with default DispatcherServlet configuration and by
extension with the MVC namespace which falls back on DispatcherServlet
implicity if no <view-resolvers> element is present.
Issue: SPR-7093
Prior to this commit, the support for SQL script execution via @Sql
provided an algorithm for looking up a required
PlatformTransactionManager to use to drive transactions. However, a
transaction manager is not actually required for all testing scenarios.
This commit improves the transaction management support for @Sql so
that SQL scripts can be executed without a transaction if a transaction
manger is not present in the ApplicationContext. The updated algorithm
now supports the following use cases.
- If a transaction manager and data source are both present (i.e.,
explicitly specified via the transactionManager and dataSource
attributes of @SqlConfig or implicitly discovered in the
ApplicationContext based on conventions), both will be used.
- If a transaction manager is not explicitly specified and not
implicitly discovered based on conventions, SQL scripts will be
executed without a transaction but requiring the presence of a data
source. If a data source is not present, an exception will be thrown.
- If a data source is not explicitly specified and not implicitly
discovered based on conventions, an attempt will be made to retrieve
it by using reflection to invoke a public method named
getDataSource() on the transaction manager. If this attempt fails,
an exception will be thrown.
- If a data source can be retrieved from the resolved transaction
manager using reflection, an exception will be thrown if the
resolved data source is not the data source associated with the
resolved transaction manager. This helps to avoid possibly
unintended configuration errors.
- If @SqlConfig.transactionMode is set to ISOLATED, an exception will
be thrown if a transaction manager is not present.
Issue: SPR-11911
This commit adds an extra test implementation that runs the cache
abstraction tests using a JSR-107 cache manager. This further covers
JCacheCacheManager.
The actual JSR-107 implementation is ehcache-jcache that requires at
least ehcache 2.8.3. Since the ehcache-core artifact is no longer a
public artifact, this commit switches to the full ehcache library,
that is net.sf.ehcache:ehcache
Prior to this commit, @Sql provided attributes for configuring the
syntax of the referenced SQL scripts as well as exception handling and
transaction behavior; however, such configuration could not be reused
across @Sql declarations thus requiring developers to copy-and-paste
common configuration and resulting in unnecessary code duplication.
This commit addresses this issue by introducing a new @SqlConfig
annotation that can be used to declare common, global configuration for
SQL scripts that can be reused within a test class hierarchy.
- Introduced top-level @SqlConfig annotation and extracted
common configuration attributes from @Sql.
- @SqlConfig can be used at the class level for common, global config
or via the new 'config' attribute of @Sql for local config.
- Introduced MergedSqlConfig as a holder for the merged values from
local and global @SqlConfig instances. MergedSqlConfig also contains
the logic for overriding global configuration with local
configuration.
- Refactored all attributes of @SqlConfig to be either of type String
or custom enums in order to support overriding. Empty Strings or
DEFAULT enum values imply the use of a default or inherited value.
Issue: SPR-11896
Make it possible to use a ListenableFuture with Java 8
lambda expressions, using a syntax like
listenableFuture.addCallback(() -> ..., () -> ...);
Issue: SPR-11820
Also contains explicit ClassLoader management, passed through StandardBeanExpressionResolver and SpelParserConfiguration to SpelCompiler lookup.
Issue: SPR-10943
This change adds a WebSocketTestServer setup method that initializes
the server and obtains a new port.
In turn AbstractWebSocketIntegrationTests invokes the new method from
its setup method thus ensuring a new port is used on every test.
Also contains refined exception handling, treating regular class loading and ASM-based loading consistently in terms of exception wrapping, and always mentioning the current configuration class in all exception messages.
Issue: SPR-11997
After some further discussion:
The MVC config simplifies ViewResolver configuration especially where
content negotiation view resolution is involved.
The configuration of the underlying view technology however is kept
completely separate. In the case of the MVC namespace, dedicated
top-level freemarker, velocity, and tiles namespace elements are
provided. In the case of the MVC Java config, applications simply
declare FreeMarkerConfigurer, VelocityConfigurer, or TilesConfigurer
beans respectively.
Issue: SPR-7093
In order to be able to use separators like "." (used by default
by most broker relays) instead of "/" for destination patterns
handling, the PathMatcher used in spring-messaging can now
be customized easily thanks to XML websocket namespace
or JavaConfig.
AntPathMatcher has been updated in order to use the configured path
separator instead of an hardcoded "/" for path concatenation.
Extension handling is now disabled when the "." separator is configured.
Issue: SPR-11660
This commit adds the missing 4.1 XSDs for the following components:
* spring-aop
* spring-context
* spring-jee
* spring-lang
* spring-tx
* spring-util
These are strictly identical to the definition of the 4.0 XSDs.
Issue: SPR-11990
Prior to this commit, customizing the concurrency to use fo a given JMS
listener involved to define it in a specific listener-container. As
this is quite restrictive, users may stop using the XML namespace
support altogether to fallback on regular abstract bean definition for
the container.
This commit adds a concurrency attribute to the jms and jca listener
element as well as on the @JmsListener annotation. If the value is set,
it takes precedence; otherwise the value provided by the factory is
used.
Issue: SPR-11988
Following the separation of FreeMarker/Velocity/TilesConfigurer-related
configuration via separate interface, simplify and streamline the
view registration helper classes which no longer have much difference
(most are UrlBasedViewResolver's).
Updates to Javadoc and tests.
Issue: SPR-7093
This change improves the support for auto-registration of FreeMarker,
Velocity, and Tiles configuration.
The configuration is now conditional not only based on the classpath
but also based on whether a FreeMarkerConfigurer for example is already
present in the configuration.
This change also introduces FreeMarker~, Velocity~, and
TilesWebMvcConfigurer interfaces for customizing each view technology.
The WebMvcConfigurer can still be used to configure all view resolvers
centrally (including FreeMarker, Velocity, and Tiles) without some
default conifguration, i.e. without the need to use the new
~WebMvcConfigurer interfaces until customizations are required.
Issue: SPR-7093
This commit improves and completes the initial MVC namespace
view resolution implementation. ContentNegotiatingViewResolver
registration is now also supported.
Java Config view resolution support has been added.
FreeMarker, Velocity and Tiles view configurers are registered
depending on the classpath thanks to an ImportSelector.
For both, a default configuration is provided and documented.
Issue: SPR-7093
Move spring-webmvc-tiles3 content to spring-webmvc, and
create a spring-webmvc-tiles2 module with Tiles 2 support.
Its allows View Resolution to configure Tiles 3 instead of Tiles 2.
Issue: SPR-7093
This change adds a method within the ModelResultMatcher that will allow
a user to assert whether the returned Model has an attribute with a
field that has a specific error associated with it.
Issue: SPR-11971
When using ServletUriComponentsBuilder.fromRequest, this change
makes sure that:
* the default port is used when the "X-Forwarded-Host" header is set
and no port is defined in that header value
* to use the scheme defined in the "X-Forwarded-Proto" header if set
Issue: SPR-11872
Before this change WebSocketConnectionManager delegated SmartLifecycle
methods to the client instance it contained. After this change
WebSocketClient implementations are expected to implement Lifecycle
(rather than SmartLifecycle).
The need for this is even more evident with SockJsClient, which is a
WebSocketClient implementation and contains a WebSocketTransport that
in turn contains the actual WebSocketClient. In this case
WebSocketConnectionManager as the top level container is the obvious
place to configure autostartup while Lifecycle events can be
propagated all the way down to the root WebSocketClient.
With these changes an optional compiler is added for SpEL
expressions. The compiler is off by default but can be enabled
via the SpEL parser configuration object or system property
(when SpEL is embedded and parser configuration is not possible).
Not all expressions are currently handled but the common
cases are and it is an extensible compilation framework.
Issue: SPR-10943
This change renames AppCacheResourceTransformer to
AppCacheManifestTransfomer, in order to avoid confusion between this
transformer and the CacheResourceTransformer (which caches
transformations done by the chain to save CPU/memory at runtime).
Issue: SPR-11964
This change adds a new ResourceTransformer that helps handling resources
within HTML5 AppCache manifests for HTML5 offline application.
This transformer:
* modifies links to match the public URL paths
* appends a comment in the manifest, containing a Hash (e.g. "# Hash:
9de0f09ed7caf84e885f1f0f11c7e326")
See http://www.whatwg.org/specs/web-apps/current-work/multipage/offline.html#offline
for more details on HTML5 offline apps and appcache manifests.
Here is a WebConfig example:
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
AppCacheResourceTransformer appCacheTransformer =
new AppCacheResourceTransformer();
registry.addResourceHandler("/**")
.addResourceLocations("classpath:static/")
.setResourceResolvers(...)
.setResourceTransformers(..., appCacheTransformer);
}
Issue: SPR-11964
Users can not mix and match between "inner bean" argument resolver and "external bean" argument resolver. This commit only focuses only on argument-resolver, while the support could be extended to return value handlers as well.
Issue: SPR-11927
This commit fixes cases where part of the URI was mistaken for the
userinfo when:
* the URI did not contain any path
* the query string contained the "@"
Issue: SPR-11964
This change removes most logging at INFO level and also ensures the
amount of information logged at DEBUG level is useful, brief, and
not duplicated.
Also added is custom logging for STOMP frames to ensure very readable
and consise output.
Issue: SPR-11934
This change adds collection of stats in key infrastructure components
of the WebSocket message broker config setup and exposes the gathered
information for logging and viewing (e.g. via JMX).
WebSocketMessageBrokerStats is a single class that assembles all
gathered information and by default logs it once every 15 minutes.
Application can also easily expose to JMX through an MBeanExporter.
A new section in the reference documentation provides a summary of
the available information.
Issue: SPR-11739
Commit 5fe8f52 introduced a support for @Priority as an alternative to
@Primary but it broke the semantic of the priority value. This commit
fixes this inconsistency.
As for @Order, the lowest value means the highest priority so if
several beans are candidates for injection, the one having the lowest
value will be used.
Issue: SPR-10548
This commit removes the immediate package dependency cycle between the context and jmx packages. A specific callback arrangement will follow in time for 4.1 RC1; at this point, it's temporarily back to registration kicked off by afterPropertiesSet again.
Issue: SPR-8045
Prior to this change, AbstractHttpReceivingTransportHandler had a direct
dependency on a Jacckson Exception (checking that exception in a catch
clause). This can cause issues for applications that don't have that
dependency.
This commit removes that direct dependency, still logging the
appropriate log messages using a parent exception (IOException) and
reflection.
Issue: SPR-11963
Commit eea230f introduced a regression by adding a support for the
"result" variable in SpEL expression for @CachePut. As such expressions
cannot be evaluated upfront anymore, any method that contains both
@Cacheable and @CachePut annotations are always executed even when
their conditions are mutually exclusive.
This is an example of such mutual exclusion
@Cacheable(condition = "#p1", key = "#p0")
@CachePut(condition = "!#p1", key = "#p0")
public Object getFooById(Object id, boolean flag) { ... }
This commit updates CacheEvaluationContext to define a set of
unavailable variables. When such variable is accessed for a given
expression, an exception is thrown. This is used to restore the
evaluation of the @CachePut condition upfront by registering "result"
as an unavailable variable.
If all @CachePut operations have been excluded by this upfront check,
the @Cacheable operation is processed as it was before. Such upfront
check restore the behavior prior to eea230f.
Issue: SPR-11955
Prior to this commit, cache operations mentioning a qualifier led to
a lookup for the same PlatformTransactionManager over and over again.
The same applied when a transactionManager bean name was specified on
the interceptor.
This commit adds a cache to store the reference of such transaction
managers. As a convenience, the default PlatformTransactionManager is
also initialized if it has not been through configuration.
Issue: SPR-11954
This commit introduces unit tests that attempt to reproduce the problem
described in Spring Boot issue 885; however, the tests pass and
therefore do not confirm the reported problem.
See: https://github.com/spring-projects/spring-boot/issues/885
This commit supports two additional methods of the MessageProducer
interface as from JMS 2.0
An integration test infrastructure is necessary to be able to test
those scenario: this is taken care of in a separated initiative.
Issue: SPR-11950
Historically, Spring's JUnit 3.8 TestCase class hierarchy supported
programmatic transaction management of "test-managed transactions" via
the protected endTransaction() and startNewTransaction() methods in
AbstractTransactionalSpringContextTests.
The Spring TestContext Framework (TCF) was introduced in Spring 2.5 to
supersede the legacy JUnit 3.8 support classes; however, prior to this
commit the TCF has not provided support for programmatically starting
or stopping the test-managed transaction.
This commit introduces a TestTransaction class in the TCF that provides
static utility methods for programmatically interacting with
test-managed transactions. Specifically, the following features are
supported by TestTransaction and its collaborators.
- End the current test-managed transaction.
- Start a new test-managed transaction, using the default rollback
semantics configured via @TransactionConfiguration and @Rollback.
- Flag the current test-managed transaction to be committed.
- Flag the current test-managed transaction to be rolled back.
Implementation Details:
- TransactionContext is now a top-level, package private class.
- The existing test transaction management logic has been extracted
from TransactionalTestExecutionListener into TransactionContext.
- The current TransactionContext is stored in a
NamedInheritableThreadLocal that is managed by
TransactionContextHolder.
- TestTransaction defines the end-user API, interacting with the
TransactionContextHolder behind the scenes.
- TransactionalTestExecutionListener now delegates to
TransactionContext completely for starting and ending transactions.
Issue: SPR-5079
Although unlikely in practice (but not impossible), the SockJS
integration tests write a message while the request is initializing.
This change adds synchronization around request intiailization
for the SockJS HTTP sesion.
Issue: SPR-11916
This change adds support for configuring ResourceResolvers and
ResourceTransformers with ResourceHttpRequestHandlers.
This is an example configuration:
<mvc:resources mapping="/resources/**" location="/">
<mvc:resolvers>
<bean class="org.springframework.web.servlet.resource.PathResourceResolver"/>
<ref bean="myResourceResolver"/>
</mvc:resolvers>
<mvc:transformers>
<bean class="org.springframework.web.servlet.resource.CssLinkResourceTransformer" />
</mvc:transformers>
</mvc:resources>
<bean id="myResourceResolver" class="org.example.resource.MyResourceResolver"/>
Issue: SPR-10951
HibernateEntityManagerFactoryIntegrationTests in the spring-orm module
has been disabled for quite some time due to a dependency on the
AnnotationBeanConfigurerAspect from the spring-aspects module. Since
spring-aspects depends on spring-orm, a cyclical dependency would
result if this code were re-enabled "as is".
This commit removes the dependency on AnnotationBeanConfigurerAspect in
HibernateEntityManagerFactoryIntegrationTests by deleting all test code
and configuration related to @Configurable. In addition, this commit
also deletes all SessionFactory-specific test code in
HibernateEntityManagerFactoryIntegrationTests, allowing the test class
to focus on Hibernate as a JPA provider.
Issue: SPR-11922
This change exposes exceptions handled in the DispatcherServlet with a
HandlerExceptionResolver as a request attribute. This is done only when
the resolver returns an empty ModelAndView indicating the exception was
resolved but not view is required (e.g. status code was set). In such
cases the exception may be useful to any handlers in an ERRPR dispatch
by the servlet container.
Issue: SPR-11686
This commit introduces the RequestEntity, a class similar to
ResponseEntity, but meant for HTTP requests rather than responses. The
RequestEntity can be used both in RestTemplate as well as @MVC
scenarios.
The class also comes with a builder, similar to the one found in
ResponseEntity, which allows for building of a RequestEntity through a
fluent API.
Issue: SPR-11752
Avoid using destination pattern based search when removing sessions or
subscriptions from DefaultSubscriptionRegistry and use only session and
subscription ids.
Issue: SPR-11930
This commit adds a test that reproduces the behaviour described in
SPR-11915 and validates that the fix introduced in f8b6114440 works
as expected.
Issue: SPR-11915
GroovyBeanDefinitionReader and Groovy ApplicationContexts redirect ".xml" files to XmlBeanDefinitionReader now, similar to what they've been doing for importBeans directives already. Analogously, @ImportResource for configuration classes redirects ".groovy" to GroovyBeanDefinitionReader now.
Issue: SPR-11924
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
Prior to this commit, the Spring TestContext Framework (TCF) was
compatible with JUnit 4.5 or higher.
This commit effectively raises the minimum version of JUnit that is
officially supported by the TCF to JUnit 4.9, thereby aligning with
similar upgrades made in the Spring Framework 4.0 release (i.e.,
upgrading minimum requirements on third-party libraries to versions
released mid 2010 or later).
Issue: SPR-11908
Prior to this commit, one of the available strategies for resolving
resources was the PrefixResourceResolver. Reconsidering the core goal of
this resolver and the FingerprintResourceResolver, we found that the
true core feature is versioning static resources application-wide.
This commit refactors both Resolvers by:
* having only on VersionResourceResolver
* that resolver takes a mapping of paths -> VersionStrategy
* provided VersionStrategy implementations are ContentBasedVS
(previously FingerprintRR), FixedVS (previously PrefixRR)
One can add a VersionResourceResolver like this:
Map<String, VersionStrategy> versionStrategies = new HashMap<>();
versionStrategies.put("/**/*.js", new PrefixVersionStrategy("prefix"));
versionStrategies.put("/**", new ContentBasedVersionStrategy());
VersionResourceResolver versionResolver = new VersionResourceResolver();
versionResolver.setVersionStrategyMap(versionStrategies);
List<ResourceResolver> resolvers = new ArrayList<ResourceResolver>();
resolvers.add(versionResolver);
resolvers.add(new PathResourceResolver());
Issue: SPR-11871
This is analogous to what the JVM does for cases where the annotation type itself isn't present on the classpath. We're effectively extending that policy to values referenced within an annotation declaration.
Issue: SPR-11874
Prior to this commit, SQL script annotations and related classes in the
TestContext framework (TCF) were named DatabaseInitializer*. However,
these annotations are not used only for initialization and are
therefore misleading when used for cleaning up the database.
This commit refines the names of annotations and related classes for
configuring SQL scripts to be executed for integration tests in the TCF
as follows:
- @DatabaseInitializer -> @Sql
- @DatabaseInitializers -> @SqlGroup
- DatabaseInitializerTestExecutionListener -> SqlScriptsTestExecutionListener
A special thanks goes out to the following attendees of the Zurich
Hackergarten meeting last night for their collective brainstorming:
@aalmiray, @atsticks, @ollin, @simkuenzi, @tangresh, @vyazelenko.
Issue: SPR-7655
This change modifies the SettableListenableFuture implementation to use
internally a ListenableFutureTask created with a "settable" Callable.
Issue: SPR-11614
A SettableListenableFuture implementation of Spring's ListenableFuture
The class is inspired by Google Guava’s
com.google.common.util.concurrent.SettableFuture, but this
implementation uses ReentrantReadWriteLock and CountDownLatch
internally to handle thread synchronization.
Issue: SPR-11614
After this change, java.util.Optional is supported with @RequestParam,
@RequestHeader, and @MatrixVariable arguments in Java 8. When Optional
is used the required flag is effectively ignored.
Issue: SPR-11829
Prior to this commit, StringUtils#trimAllWhitespace(String str) was
unecessary slower. Using sb.deleteCharAt(index) leads to a complete
copy of the char[]
Prior to this commit, the CssLinkResourceTransformer would transform
"external resources", i.e. resources not served by the web application.
This commit only allows transformation for resources which path don't
contain scheme such as "file://" or "http://". Only relative and
absolute paths for resources served by the webapp are valid.
Issue: SPR-11860
Prior to this commit, AntPathMatcher had been refactored for SPR-6741.
During that process, a key feature has been removed:
When comparing two patterns, pattern elements (*, {}, etc) are counted
to score those patterns. When a pattern ends with ".*", the ending
wildcard should not be counted against pattern elements for this
pattern.
This commit reintroduces that behavior.
Issue: SPR-6741
Prior to this commit, "**" and "*" pattern elements had
the same priority when comparing two patterns.
So when comparing several patterns, the computed order was:
1- /hotels/{hotel}/bookings/{booking}
2- /hotels/**
3- /hotels/{hotel}/bookings/{booking}/customer/{customer}
This commit updates the comparator so that patterns ending
with "**" (a.k.a "catch-all" patterns) are less specific than
the others; in the previous example, the 2nd pattern would
then end up last.
This commit also optimizes the comparator implementation.
Issue: SPR-6741
Since SPR-11486 and SPR-10163, Path Matching options can be configured
to customize path matching options for RequestMappingHandlerMapping.
Prior to this commit, the defined pathMatcher and pathHelper instances
were only used in RequestMappingHandlerMapping.
This commit now registers pathMatcher and pathHelper beans under
well-known names and share them with several HandlerMappings beans,
such as ViewControllerMappings and ResourcesMappings.
Issue: SPR-11753
This commit provides a proper documentation for the @ComponentScan
annotation as a java config alternative to <context:component-scan/>
Issue: SPR-11846
This commit adds a new function to the Spring tag library for preparing
links to @Controller methods. For more details see the Javadoc of
MvcUriComponentsBuilder.fromMappingName.
Issue: SPR-5779
This commit adds support for Groovy Markup templates.
Spring's support requires Groovy 2.3.1+.
To use it, simply create a GroovyMarkupConfigurer and a
GroovyMarkupViewResolver beans in the web application context.
Issue: SPR-11789
Reorganized class structure to match our code style (setter for
properties at the top of the class, public method before private
implementation).
Removed DisposableBean as it the lifecycle is already taking care
of removing MBeans on stop.
Cleaned test suite
Issue: SPR-8045
Prior to this commit, MBeans were registered in a post construct
call of MBeanExporter. This commit moves that logic after the
initialization phase using the SmartLifecycle callback.
Issue: SPR-8045
Enable JSONP support by wrapping the JSON output into
a callback when a JSONP query parameter specifying the
function name to use as callback is detected.
Default query parameter names recognized as JSONP ones
are "jsonp" and "callback". This list can be customized if
needed.
This commit also fixes JSONView support by removing
the view name specified in the model from the output.
Issue: SPR-8346
Before this change @ModelAttribute methods were not invoked in any
particular order other than ensuring global @ControllerAdvice methods
are called first and local @Controller methods second.
This change introduces a simple algorithm that selects the next
@ModelAttribute method to invoke by making a pass over all methods and
looking for one that has no dependencies (i.e. @ModelAttribute
input arguments) or has all dependencies resolved (i.e. available in
the model). The process is repeated until no more @ModelAttribute
methods remain.
If the next @ModelAttribute method cannot be determined because all
remaining methods have unresolved dependencies, the first available
method is picked anyway just as before, i.e. with required
dependencies created through the default constructor.
Examples in ModelFactoryOrderingTests.
Issue: SPR-6299
Includes support for arbitrary deep nesting levels in DependencyDescriptor's getDependencyType() and MethodParameter's getNestedParameterType().
Issue: SPR-11833
Prior to this commit, it was possible to execute SQL scripts
programmatically via ResourceDatabasePopulator, JdbcTestUtils, and
ScriptUtils. Furthermore, it was also possible to execute SQL scripts
declaratively via the <jdbc> XML namespace. However, it was not
possible to execute SQL scripts declaratively on a per test class or
per test method basis.
This commit makes it possible to declaratively configure SQL scripts
for execution in integration tests via annotations that can be declared
at the class or method level. Details follow.
- Introduced a repeatable @DatabaseInitializer annotation that can be
used to configure SQL scripts at the class or method level with
method-level overrides. @DatabaseInitializers serves as a container
for @DatabaseInitializer.
- Introduced a new DatabaseInitializerTestExecutionListener that is
responsible for parsing @DatabaseInitializer and
@DatabaseInitializers and executing SQL scripts.
- DatabaseInitializerTestExecutionListener is registered by default in
abstract base test classes as well as in TestContextBootstrapper
implementations.
- @DatabaseInitializer and @DatabaseInitializers may be used as
meta-annotations; however, attribute overrides are not currently
supported for repeatable annotations used as meta-annotations. This
is a known limitation of Spring's AnnotationUtils.
- The semantics for locating SQL script resources is consistent with
@ContextConfiguration's semantics for locating XML configuration
files. In addition, a default SQL script can be detected based
either on the name of the annotated class or on the name of the
annotated test method.
- @DatabaseInitializer allows for specifying which DataSource and
PlatformTransactionManager to use from the test's
ApplicationContext, including default conventions consistent with
TransactionalTestExecutionListener and @TransactionConfiguration.
- @DatabaseInitializer supports all of the script configuration options
currently supported by ResourceDatabasePopulator.
- @DatabaseInitializer and DatabaseInitializerTestExecutionListener
support execution phases for scripts that dictate when SQL scripts
are executed (i.e., before or after a test method).
- SQL scripts can be executed within the current test's transaction if
present, outside of the current test's transaction if present, or
always in a new transaction, depending on the value of the boolean
requireNewTransaction flag in @DatabaseInitializer.
- DatabaseInitializerTestExecutionListener delegates to
ResourceDatabasePopulator#execute to actually execute the scripts.
Issue: SPR-7655
This commit introduces OrderProvider and OrderProviderComparator, two
interfaces designed to externalize how a collection of element is sorted
according to their order value.
FactoryAwareOrderProvider is an OrderProvider implementation that knows
about the objects to order and the corresponding BeanFactory instance.
This allows to retrieve additional metadata about the actual instances
to sort, such as its factory method.
A @Bean method can now holds an additional @Order to define the order
value that this bean should have when injected as part of a collection
or array.
Issue: SPR-11310
This commit adds a invokeOperation protected method in case one
needs a hook point in the way the underlying cache method is invoked,
and how exceptions that might be thrown by that invocation are handled.
Issue: SPR-11540
Prior to this commit, the ordering of classpath entries in the
generated Eclipse .classpath files did not align with the intended
dependency management configured in the Gradle build. Specifically,
project dependencies often came before dependencies on third-party
libraries required for the given project, causing the project not to
compile in Eclipse.
This commit fixes this issue by introducing new functionality in the
ide.gradle script that moves all project dependencies to the end of the
generated classpath.
Issue: SPR-11836
This commit upgrades Hibernate-based integration tests in the
spring-test module to use Hibernate 4 instead of 3 and Hibernate
Validator 5 instead of 4. This streamlines and simplifies our
dependency management at the same time.
Issue: SPR-11834
- Set the eclipse.jdt source and target compatibility to 1.8 in
ide.gradle.
- Updated the instructions in import-into-eclipse.sh to reflect minimum
requirements for building Spring Framework 4.1 against Java 8 with
Eclipse and STS
Issue: SPR-11831
Prior to this commit, no exception was raised if a message could not
be converted to the requested payload because no suitable converter
were found.
This commit adds an explicit check if the converted payload is null.
Issue: SPR-11817
Eclipse 4.4 early release versions have issues with generics.
This commit slightly tweaks the use of generics in
JmsMessagingTemplateTests so that the class compiles in the latest
builds of Eclipse 4.4
This change adds a ResourceTransformer that can be invoked in a chain
after resource resolution. The CssLinkResourceTransformer modifies a
CSS file being served in order to update its @import and url() links
(e.g. to images or other CSS files) to match the resource resolution
strategy (e.g. adding MD5 content-based hashes).
Issue: SPR-11800
This commit revisits JmsMessagingTemplate and adds support for
receiving operations as well. JmsMessageSendingOperations has been
renamed to JmsMessageOperations.
The messaging abstraction did not split receiving and request-reply
operations. AbstractMessageReceivingTemplate has been created to hold
only the receiving operations.
Issue: SPR-11772
This commit adds support to read and write JSON using the Google Gson
library. GsonHttpMessageConverter offers default Gson configuration, but
can be customized by using GsonFactoryBean. GsonFactoryBean includes
several convenience properties for configuring the internal GsonBuilder
and the resulting Gson object.
By default Gson converts byte arrays to JSON arrays instead of a Base64
encoded string. GsonBase64ByteArrayJsonTypeAdapter provides support to
read and write Base64 encoded byte arrays, and can be enabled in
GsonFactoryBean.
RestTemplate will enable GsonHttpMessageConverter only if Jackson 2 is
not found on the class path, because by default GsonHttpMessageConverter
supports the same media types as Jackson.
Issue: SPR-9488
Prior to this commit, CacheResolver could not be configured through
the XML namespace (i.e. cache:annotation-driven). This is now the
case.
Issue: SPR-11490
This commit adds the necessary infrastructure to handle exceptions
thrown by a cache provider in both Spring's and JCache's caching
abstractions.
Both interceptors can be configured with a CacheErrorHandler that
defines several callbacks on typical cache operations. In particular,
handleCacheGetError can be implemented in such a way that an
exception thrown by the provider is handled as a cache miss by the
caching abstraction.
The handler can be configured with both CachingConfigurer and the
XML namespace (error-handler property)
Issue: SPR-9275
The newly added support for ResponseBodyInterceptor is a good fit for
the (also recently added) support for the Jackson @JsonView annotation.
This change refactors the original implementation of @JsonView support
for @ResponseBody and ResponseEntity controller methods this time
implemented as an ResponseBodyInterceptor.
Issue: SPR-7156
This change introduces a new ResponseBodyInterceptor interface that can
be used to modify the response after @ResponseBody or ResponseEntity
methods but before the body is actually written to the response with the
selected HttpMessageConverter.
The RequestMappingHandlerAdapter and ExceptionHandlerExceptionResolver
each have a property to configure such interceptors. In addition both
RequestMappingHandlerAdapter and ExceptionHandlerExceptionResolver
detect if any @ControllerAdvice bean implements ResponseBodyInterceptor
and use it accordingly.
Issue: SPR-10859
This commit adds a JMS implementation of MessageSendingOperations,
allowing to send JMS messages using Spring's standard Messaging
abstraction.
MessagingMessageConverter is a standard JMS's MessageConverter that
can convert Spring's Message to JMS message and vice versa. Existing
infrastructure has been updated to use this implementation.
Issue: SPR-11772
This commit also includes lazy resolution support for StandardServletMultipartResolver, along the lines of existing lazy mode in CommonsMultipartResolver.
Issue: SPR-11074
Issue: SPR-11730
This feature required support for response exposure on Servlet/PortletRequestAttributes, instead of just in the Servlet/PortletWebRequest subclasses.
Issue: SPR-11795
Spring MVC now supports Jackon's serialization views for rendering
different subsets of the same POJO from different controller
methods (e.g. detailed page vs summary view).
Issue: SPR-7156
This commit adds a SQLErrorCodes instance for SAP DB, based on a
contribution from Andrew Clemons
Mostly based on SAP Hana SPS 07 with a few additional codes that are
only present is previous versions:
* -813 - Cannot connect to host somehost:30115 [Connection refused]
* -709 - Unknown host somehost:30115 [somehost], -709.]
* -708 - Cannot connect to jdbc:sap://somehost:30115 [Receive of connect failed.]
* -11210 - Invalid column index XYZ.
Issue: SPR-11770
This commit avoids throwing JMSException from the listener execution
as this is not allowed per spec. Our SessionAwareMessageListener
gives a callback that can throw JMSException and we have "abused" it
so far.
Typical message processing goes in those 3 steps:
* Unmarshall the javax.jms.Message to the requested type
* Invoke the actual user method (including processing of method
arguments)
* Send a reply message, if any
Those three steps have been harmonized so that they don't throw a
JMSException anymore. For the later case, introduced
ReplyFailureException as a general exception indicating the
reply message could not have been sent.
Issue: SPR-11778
Prior to this commit, RestTemplate's documentation advised to a
DecompressingHttpClient decorator along with Apache's HttpClient in
order to support gzipped responses.
Since this is now deprecated as of Apache HttpClient 4.3+, this commits
update the documentation with HttpClientBuilder.
This commit adds an explicit error message when the BackOff instance
has returned BackOffExecution#STOP which basically means that no
further attempts are allowed.
This error message is a convenience way to notify that the container is
about to be shut down.
Issue: SPR-11746
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
This commit separates the BackOff configuration from an actual
execution. BackOffExecution now contains all the state of a
particular execution and BackOff is only meant to start (i.e.
create) a new execution.
The method "reset" has been removed as its no longer necessary:
when an execution does not need to be used for a given operation
anymore it can be simply discarded.
Issue: SPR-11746
This commit adds a "back-off" attribute to the jms:listener-container
element so that a BackOff instance can be provided for users of the
XML namespace.
Issue: SPR-11746
Prior to this commit, DefaultMessageListenerContainer was recovering
on failure using a fixed time interval, potentially in an infinite way.
This commit adds an extra "backoff" property to the container that
permits to fine tune the recovery interval using a BackOff instance.
FixedBackOff provides a fixed interval between two attempts and a
maximum number of retries. ExponentialBackOff increases an initial
interval until a maximum interval has been reached. A BackOff instance
can return a special "STOP" time value that indicates that no further
attemps should be made. DefaultMessageListenerContainer uses this
value to stop the container.
protected method "sleepInbetweenRecoveryAttempts" has been renamed
to "applyBackOff" and now returns a boolean that indicate if the
back off has been applied and a new attempt should now be made.
Issue: SPR-11746
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
This commit migrates the YAML support available in Spring Boot to
the core framework. YAML documents can be loaded either as a
properties object or as a map.
Issue: SPR-9897
Removal of cached destination is now moved outside the for loop
that removes subscriptions to avoid ConcurrentModificationException.
Also since updateCache is a LinkedHashMap with accessOrder=true,
a simple access with updateCache.get() modify the map.
By iterating over updateCache.entrySet(), we avoid this update.
Issue: SPR-11755
Before this change UrlTag expanded URI vars and encoded them using
UriUtils.encodePath.
This change makes it possible to expand using
UriUtils.encodePathSegment, which means a "/" is encoded as "%2F".
To expand with path segment semantics, prefix the URI var name "/":
<spring:url value="/url/path/{/var}">
<spring:param name="var" value="my/Id" />
</spring:url>
Issue: SPR-11401
This change adds a strategy for assigning a default name to an
@RequestMapping controller method. The @RequestMapping annotation
itself now has a name attribute allowing the explicit assignment
of a mapping name.
This is mainly intended for use in EL expressions in views. The
RequestContext class now provides a getMvcUrl method that internally
delegates to MvcUriComponents to look up the handler method.
See the Javadoc of MvcUriComponents.fromMappingName.
Issue: SPR-5779
This change refines the logic of "mapping" content negotiation
strategies with regards to how to handle cases where no mapping is
found.
The request parameter strategy now treats request parameter values that
do not match any mapped media type as 406 errors.
The path extension strategy provides a new flag called
"ignoreUnknownExtensions" (true by default) that when set to false also
results in a 406. The same flag is also exposed through the
ContentNegotiationManagerFactoryBean and the MVC Java config.
Issue: SPR-10170
Added the ability to send a message only to one user session. Given a
user has two tabs open and the client sends a message to the server
from tab 1, it is now possible to send a reply message to only 1 tab
instead of the default mode of targetting all known user sessions.
Issue: SPR-11506
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
This commits fixes a confusing phrasing of Cacheable javadoc that
mentioned explicitly that the method signature is used to compute the
key for the cache.
Issue: SPR-11736
DestinationCache is now used for both plain and pattern
destinations. It stores internally the subscriptions map for each
cached destination. Subscriptions are initially created when there
is no cache for the requested destination, and are updated when
subscriptions change.
Issue: SPR-11657
This change simplifies the implementation of the "test" EventPublisher
and MessageHandler used in the STOMP broker relay integration tests.
The updated implementations use a time-limted poll on a BlockingQueue.
This commit removes the queue attribute of the JmsListener annotation
as this information should be provided by the container factory and not
by each individual listener endpoints.
There was a side effect that an annotation value cannot be null, which
was forcing the container to be a queue-based container by default.
Issue: SPR-9882
The configured prefix should not begin with a "/", since
PublicResourceUrlProvider is already taking path mapping into account
when resolving resources and URLs.
This commit replaces the "responseDestination" attribute on the
JmsListener annotation by a support of the standard SendTo annotation.
Issue: SPR-11707
Prior to this commit, the default JmsListenerContainerFactory to use
must be explicitly set. Since having a single container factory is a
fairly common use case, we look up the default one automatically
using the bean name "jmsListenerContainerFactory".
It is still possible to provide an explicit default but since it refers
more to "the" container factory to use, the parameter has been
renamed to "containerFactory" which is shorter and more explicit.
The lookup strategy is lazy: if all endpoints are providing an
explicit container factory and no container factory with the
"jmsListenerContainerFactory" bean name exists, no exception
will be thrown.
Issue : SPR-11706
This change modifies the names of the Reactor support classes in order
to align with the same changes in the 4.0.x line which now supports
both Reactor 1.1 and 1.0.
Issue: SPR-11636
- ResourceResolver and ResourceResolverChain now have a consistent API
with regard to method names and terminology.
- ResourceResolver and ResourceResolverChain now accept
List<? extends Resource> instead of List<Resource> for simplified
programmatic use.
- Improved Javadoc across the package.
- Formatted code to align with standards.
- Removed all references to ResourceUrlPathTranslator.
Issue: SPR-10933
Clean up compiler warnings in the tests of spring-context-support.
This commit:
* adds type parameters to all the types except `Cache` (mostly `List`
and `Map`)
* removes unused imports
Clean up compiler warnings in the tests of spring-jms. This commit
adds type parameters to all the types (mostly `List` and `Map`).
I am not too sure about the `Map` type parameters in
`MessageContentsDelegate` and `ResponsiveMessageDelegate` however the
respective methods seem unused.
Clean up compiler warnings in the tests of spring-tx. This commit
adds type parameters to all the types (mostly `List` and `Map`). In
addition it uses Java 5 autoboxing to get rid of several `new Integer`
(except in cases where it's needed).
After this commit the only warnings in spring-tx left are in
`TransactionAttributeSourceTests`` that code would never compile with
generics.
Clean up compiler warnings in the tests of spring-web. This commit
adds type parameters to all the types (mostly `List` and `Map`).
After this commit the only warnings in spring-web left are in
* `MockExpressionEvaluator` this can't be fixed until JSP-EL is fixed
* `Jackson2ObjectMapperFactoryBeanTests#testSetModules` that code
would never compile with generics.
Clean up compiler warnings in the tests of spring-expression. This
commit adds type parameters to some of the types (mostly `List` and
`Map`). Some of them can't be cleaned up, some tests are even
specifically for raw types.
Clean up compiler warnings in the tests of spring-webmvc-portlet. This
commit adds type parameters to all the types (mostly `List` and `Map`).
After this commit the only warnings in spring-web left are the
subclasses of `MyCommandProvidingFormController`.
Clean up compiler warnings in the tests of spring-jdbc. This commit
adds type parameters to all the types (mostly `List` and `Map`). In
addition it uses Java 5 autoboxing to get rid of all of the following
* new Integer
* new Long
* new Float
* new Double
* new Boolean
* new String
This should be unnoticeably faster since interning can be uses for
Integer and such.
After this commit the only warnings in spring-jdbc left are:
* raw type warning in `MapDataSourceLookupTests`, that code would never
compile with generics
* deprecation warning for `#queryForInt` and `#queryForLong`
Prior to this commit, invoking the getMergedAnnotationAttributes()
method in AnnotationReadingVisitorUtils resulted in mutation of the
internal state of the ASM-based annotation metadata supplied to the
method.
This commit fixes this issue by making a copy of the original
AnnotationAttributes for the target annotation before merging attribute
values from the meta-annotation hierarchy.
This commit also introduces a slight performance improvement by
avoiding duplicate processing of the attributes of the target
annotation.
Issue: SPR-11710
This commit adds the support of JMS annotated endpoint. Can be
activated both by @EnableJms or <jms:annotation-driven/> and
detects methods of managed beans annotated with @JmsListener,
either directly or through a meta-annotation.
Containers are created and managed under the cover by a registry
at application startup time. Container creation is delegated to a
JmsListenerContainerFactory that is identified by the containerFactory
attribute of the JmsListener annotation. Containers can be
retrieved from the registry using a custom id that can be specified
directly on the annotation.
A "factory-id" attribute is available on the container element of
the XML namespace. When it is present, the configuration defined at
the namespace level is used to build a JmsListenerContainerFactory
that is exposed with the value of the "factory-id" attribute. This can
be used as a smooth migration path for users having listener containers
defined at the namespace level. It is also possible to migrate all
listeners to annotated endpoints and yet keep the
<jms:listener-container> or <jms:jca-listener-container> element to
share the container configuration.
The configuration can be fine-tuned by implementing the
JmsListenerConfigurer interface which gives access to the registrar
used to register endpoints. This includes a programmatic registration
of endpoints in complement to the declarative approach. A default
JmsListenerContainerFactory can also be specified to be used if no
containerFactory has been set on the annotation.
Annotated methods can have flexible method arguments that are similar
to what @MessageMapping provides. In particular, jms listener endpoint
methods can fully use the messaging abstraction, including convenient
header accessors. It is also possible to inject the raw
javax.jms.Message and the Session for more advanced use cases. The
payload can be injected as long as the conversion service is able to
convert it from the original type of the JMS payload. By
default, a DefaultJmsHandlerMethodFactory is used but it can be
configured further to support additional method arguments or to
customize conversion and validation support.
The return type of an annotated method can also be an instance of
Spring's Message abstraction. Instead of just converting the payload,
such response type allows to communicate standard and custom headers.
The JmsHeaderMapper infrastructure from Spring integration has also
been migrated to the Spring framework. SimpleJmsHeaderMapper is based
on SI's DefaultJmsHeaderMapper. The simple implementation maps all
JMS headers so that the generated Message abstraction has all the
information stored in the protocol specific message.
Issue: SPR-9882
An initial commit with expanded support for static resource handling:
- Add ResourceResolver strategy for resolving a request to a Resource
along with a few implementations.
- Add PublicResourceUrlProvider to get URLs for client-side use.
- Add ResourceUrlEncodingFilter and
PublicResourceUrlProviderExposingInterceptor along with initial
MVC Java config support.
Issue: SPR-10933
Prior to this commit, only the java.lang.reflect.Method was used to
identify an annotated method. As a result, if different annotations
were placed on different methods (method overriding, interface
implementation) only the first one (cached) was used.
LazyParamAwareEvaluationContext was affected by the exact
same problem and has been also fixed.
Issue: SPR-11692
Introduce MessageHeaderInitializer strategy for initializing a
MessageHeaderAccessor.
Add IdTimestampMessageHeaderInitializer implementation that provides
control over ID and timestamp header generation.
Disable ID and timestamp by default in SimpMessageHeaderAccessor and
therefore its sub-class StompHeaderAccessor.
Issue: SPR-11468
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.
AbstractMessageConverter and messaging template implementations now
detect and use mutable headers if passed in.
The SimpMessagingTemplate is optimized to supporting using a single
MessageHeaders instance while preparing a message.
This commit also updates code using the SimpMessagingTemplate to take
advantage of its new capabilities.
Issue: SPR-11468
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
Prior to this commit it was impossible to add additional scripts to a
ResourceDatabasePopulator after setScripts() had been invoked.
This commit fixes this by ensuring that the internal scripts list
continues to be modifiable when setScripts() is invoked.
Issue: SPR-11691
Prior to this commit ResourceDatabasePopulator did not assert any
preconditions for constructor and method arguments. Consequently,
errors would not be encountered until the populator was executed.
This commit addresses this issue by ensuring that preconditions for
constructor and method arguments are asserted immediately, throwing
IllegalArgumentExceptions where appropriate.
Issue: SPR-11690
Changed the value of ScriptUtils.EOF_STATEMENT_SEPARATOR from
"<<< END OF SCRIPT >>>" to "^^^ END OF SCRIPT ^^^" so that the angle
brackets do not have to be escaped in XML configuration files.
Issue: SPR-11687
Prior to Spring Framework 4.0.3, it was possible to supply a bogus
statement separator (i.e., a separator string that does not exist in
the configured SQL scripts) to ResourceDatabasePopulator with the side
effect that the entire contents of a script file would be interpreted
as a single SQL statement.
This undocumented feature was never intentional; however, some
developers came to rely on it. Unfortunately, changes made in
conjunction with SPR-9531 and SPR-11560 caused such scenarios to no
longer work.
This commit introduces first-class support for executing scripts which
contain a single statement that spans multiple lines but is not
followed by an explicit statement separator.
Specifically, ScriptUtils.EOF_STATEMENT_SEPARATOR may now be specified
as a 'virtual' statement separator to denote that a script contains a
single statement and no actual separator.
Issue: SPR-11687
Work done in conjunction with SPR-5243 and SPR-4588 introduced physical
package cycles in the spring-test module. The work performed in
conjunction with SPR-9924 uses reflection to resolve these physical
package cycles; however, prior to this commit the logical package
cycles still remain.
Furthermore, over time it has become apparent that the Spring
TestContext Framework (TCF) could better serve application developers
and especially third-party framework developers by providing a more
flexible mechanism for "bootstrapping" the TCF. For example, prior to
this commit, default TestExecutionListeners could only be registered by
subclassing TestContextManager (and SpringJUnit4ClassRunner if using
JUnit). Similarly, the default ContextLoader could only be set by
subclassing SpringJUnit4ClassRunner for JUnit and by copying and
modifying AbstractTestNGSpringContextTests for TestNG.
This commit addresses the aforementioned issues by introducing a
bootstrap strategy in the TestContext framework that is responsible for
determining default TestExecutionListeners and the default
ContextLoader in an extensible fashion. The new TestContextBootstrapper
SPI also provides a mechanism for supporting various types of
MergedContextConfiguration depending on the feature set of the context
loaders supported by the strategy.
The following provides an overview of the most significant changes in
this commit.
- Introduced TestContextBootstrapper strategy SPI, BootstrapContext,
and @BootstrapWith.
- Introduced AbstractTestContextBootstrapper,
DefaultTestContextBootstrapper, and WebTestContextBootstrapper
implementations of the TestContextBootstrapper SPI and extracted
related reflection code from ContextLoaderUtils & TestContextManager.
- Introduced BootstrapUtils for retrieving the TestContextBootstrapper
from @BootstrapWith, falling back to a default if @BootstrapWith is
not present.
- @WebAppConfiguration is now annotated with
@BootstrapWith(WebTestContextBootstrapper.class).
- CacheAwareContextLoaderDelegate is now an interface with a new
DefaultCacheAwareContextLoaderDelegate implementation class.
- Introduced closeContext(MergedContextConfiguration, HierarchyMode) in
CacheAwareContextLoaderDelegate.
- DefaultTestContext now uses CacheAwareContextLoaderDelegate instead
of interacting directly with the ContextCache.
- DefaultTestContext now delegates to a TestContextBootstrapper for
building the MergedContextConfiguration.
- TestContextManager now delegates to TestContextBootstrapper for
retrieving TestExecutionListeners.
- Deleted TestContextManager(Class, String) constructor and
SpringJUnit4ClassRunner.getDefaultContextLoaderClassName(Class)
method since default ContextLoader support is now implemented by
TestContextBootstrappers.
- Extracted ActiveProfilesUtils from ContextLoaderUtils.
- Extracted ApplicationContextInitializerUtils from ContextLoaderUtils.
- MetaAnnotationUtils is now a public utility class in the test.util
package.
- Removed restriction in @ActiveProfiles that a custom resolver cannot
be used with the 'value' or 'profiles' attributes.
- Introduced DefaultActiveProfilesResolver.
Issue: SPR-9955
This commit is a general update of the Cache Abstraction chapter.
Existing sections have been updated with recent improvements made in
that area, in particular:
* Guava and JSR-107 caches support
* New @CacheConfig annotation allowing to share some key customizations
at class-level
* CacheResolver interface used to resolve the cache(s) to use at
runtime
* Update section on @CachePut
This commit also describes the support of standard JCache annotations,
i.e. JSR-107.
Issues: SPR-11490, SPR-11316, SPR-10629, SPR-9616, SPR-8696
This commit fixes the handling of cached exceptions in the JSR-107
advisor. Such exceptions are now properly propagated instead of being
wrapped in a RuntimeException.
Issue: SPR-9616
Prior to this commit, AnnotatedJCacheableService contained an annotated
method demonstrating a failure scenario. This could break depending on
the order of the methods array as AopUtils creates the proxy if the
pointcut matches by checking each method.
On the CI server, the first method was this invalid use case so
checking if the proxy has to be created lead to an unexpected
exception. This scenario has been moved to its own private class now.
Prior to this commit, the CacheResolver was not used by Spring's
caching abstraction. This commit provides the necessary configuration
options to tune how a cache is resolved for a given operation.
CacheResolver can be customized globally, at the operation level or at
the class level. This breaks the CachingConfigurer class and a support
implementation is provided that implements all methods so that the
default is taken if it's not overridden. The JSR-107 support has been
updated as well, with a similar support class.
In particular, the static and runtime information of a cache
operation were mixed which prevents any forms of caching. As the
CacheResolver and the KeyGenerator can be customized, every operation
call lead to a lookup in the context for the bean.
This commit adds CacheOperationMetadata, a static holder of all
the non-runtime metadata about a cache operation. This is used
as an input source for the existing CacheOperationContext.
Caching the operation metadata in an AspectJ aspect can have side
effects as the aspect is static instance for the current ClassLoader.
The metadata cache needs to be cleared when the context shutdowns.
This is essentially a test issue only as in practice each application
runs in its class loader. Tests are now closing the context properly
to honor the DisposableBean callback.
Issue: SPR-11490
This commit adds support for the JSR-107 cache annotations alongside
the Spring's cache annotations, that is @CacheResult, @CachePut,
@CacheRemove and @CacheRemoveAll as well as related annotations
@CacheDefaults, @CacheKey and @CacheValue.
Spring's caching configuration infrastructure detects the presence of
the JSR-107 API and Spring's JCache implementation. Both
@EnableCaching and the cache namespace are able to configure the
required JCache infrastructure when necessary. Both proxy mode
and AspectJ mode are supported.
As JSR-107 permits the customization of the CacheResolver to use for
both regular and exception caches, JCacheConfigurer has been
introduced as an extension of CachingConfigurer and permits to define
those.
If an exception is cached and should be rethrown, it is cloned and
the call stack is rewritten so that it matches the calling thread each
time. If the exception cannot be cloned, the original exception is
returned.
Internally, the interceptors uses Spring's caching abstraction by default
with an adapter layer when a JSR-107 component needs to be called.
This is the case for CacheResolver and CacheKeyGenerator.
The implementation uses Spring's CacheManager abstraction behind the
scene. The standard annotations can therefore be used against any
CacheManager implementation.
Issue: SPR-9616
This commit introduces an explicit integration test to verify that a
PropertySource can be set via a custom ApplicationContextInitializer in
the Spring TestContext Framework.
Issue: SPR-11666
Prior to this commit, there were numerous places in the reference
manual, where we would see output similar to the following:
BeanDefinition`s with the `ApplicationContext
This commit addresses this issue by using unconstrained quotes
(e.g., ++XYZ++s) instead of backticks (e.g., `XYZ`s) when the formatted
text is immediately followed by an "s".
This commit also corrects a few typos and corrects natural English
pluralization of Java code elements in the reference manual where
appropriate -- for example, "@Controllers" becomes "@Controller classes,
etc.
Issue: SPR-11650
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
This commit adds a putIfAbsent method to the Cache interface. This
method offers an atomic put if the key is not already associated in
the cache.
Issue: SPR-11400
This commit updates a number of dependencies upon Java EE specs to
use the preferred artifacts. Part of this change has been to move
to new API artifacts for both JSTL and JavaMail. In both cases these
new API jars are genuine API jars, i.e. they no longer contain an
implementation. Where needed, implementation dependencies have been
added.
Prior to this commit, an exception thrown by an @Async void method
was not further processed as there is no way to transmit that
exception to the caller.
The AsyncUncaughtExceptionHandler is a new strategy interface that
can be implemented to handle unexpected exception thrown during the
invocation of such asynchronous method.
The handler can be specified using either the XML namespace or by
implementing the AsyncConfigurer interface with the EnableAsync
annotation.
Issue: SPR-8995
Prior to this commit, the Spring TestContext Framework did not support
the declaration of both 'locations' and 'classes' within
@ContextConfiguration at the same time.
This commit addresses this in the following manner:
- ContextConfigurationAttributes no longer throws an
IllegalArgumentException if both 'locations' and 'classes' are
supplied to its constructor.
- Concrete SmartContextLoader implementations now validate the
supplied MergedContextConfiguration before attempting to load the
ApplicationContext. See validateMergedContextConfiguration().
- Introduced tests for hybrid context loaders like the one used in
Spring Boot. See HybridContextLoaderTests.
- Updated the Testing chapter of the reference manual so that it no
longer states that locations and classes cannot be used
simultaneously, mentioning Spring Boot as well.
- The Javadoc for @ContextConfiguration has been updated accordingly.
- Added hasLocations(), hasClasses(), and hasResources() convenience
methods to MergedContextConfiguration.
Issue: SPR-11634
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
Prior to this commit, a cache that is added on-the-fly is not properly
decorated by the provided CacheManager implementation that supports
it (EhCache and JCache).
This commits adds an extra getMissingCache method to
the AbstractCacheManager that can be extended to provide a cache that
may exist in the native cache manager but is not yet known by the
spring abstraction.
Issue: SPR-11518
This commit rationalizes the use of @Order so that the standard
@Priority annotation can be used instead. The handling of both
annotations are now defined in OrderUtils.
This also updates the link to the JavaEE API so that we refer to
JavaEE7 instead of JavaEE6.
Issue: SPR-11639
This commit adds support for @Priority to filter multiple candidates
for autowiring. When multiple candidates are available for a given
bean, the bean annotated with @Primary is used. If none exists, the
one with the higher value for the @Priority annotation is used. If
two beans have the same priority a NoUniqueBeanDefinitionException
is thrown, just as if two beans are annotated with @Primary.
The underlying code for #getBean and #resolveDependency has been
merged as this feature is available for both dependency injection
and bean lookup by type.
Issue: SPR-10548
Added tests checking the behaviour of autowiring by type when the @Primary
annotation is present on the class. Fixed also some inconsistencies in the
code.
Prior to this commit, common cache operation settings had to be
repeated for every operation: cache name(s), custom cache manager
and custom key manager.
This commit introduces the @CacheConfig annotation to bet set at
class-level (either directly or as a meta-annotation). As the cache
name(s) can be rationalized there, the "value" of the various
annotations are no longer mandatory.
CacheAnnotationParser has an API breakage to be able to retrieve
information at class-level.
Issue: SPR-11316
It is now possible to specify the CacheManager to use per operation.
The related cache annotation now has an extra attribute that defines
the name of the CacheManager bean to use. The cache manager that
was previously used is therefore a 'default' cache manager (i.e. the
one to use if no custom cache manager has been set on the operation).
Issue: SPR-8696
This commit adds an extra parameter to the base @Cache method
annotations: keyGenerator. This parameter holds the name of the
KeyGenerator bean to use to compute the key for that specific
caching endpoint.
This gives therefore a third way to customize the key. These are:
1. Default KeyGenerator (global for all endpoints)
2. The 'key' attribute of the annotation, giving the SpEL expression to use
3. The 'keyGenerator' attribute of the annotation
The annotation attributes are therefore exclusive. Trying to specify
them both will result in an IllegalStateException.
The KeyGenerator to use for a given operation is cached on startup
so that multiple calls to it does not resolve the instance to use over and
over again.
Issue: SPR-10629
This commit ensures that QuartzSupportTests and its related
configuration are compatible with Quartz 2.1.7.
- Test jobs are now durable where required.
- Deleted legacy tests that attempted to use a Runnable instead of a
Job as a jobClass for a JobDetail.
- Replaced quartz-hsql.sql with current version for Quartz 2.1.7.
Issue: SPR-11630
To simplify common use cases, this commit introduces a new
execute(DataSource) method in ResourceDatabasePopulator that complements
the existing populate(Connection) method.
Issue: SPR-11629
Prior to this commit, if multiple test methods were executed in a
subclass of AbstractTestNGSpringContextTests annotated with
@WebAppConfiguration, then injected Servlet API mocks would only
reference the mocks created for the first test method. Subsequent test
methods could therefore never reference the current mocks, and there
was a discrepancy between the state of the injected mocks and the mock
set in the RequestContextHolder.
This commit addresses this issue by ensuring that dependencies
(including updated mocks) are injected into the test instance before
the next test method if the ServletTestExecutionListener resets the
request attributes in RequestContextHolder.
Issue: SPR-11626
Previously, the use of Assume.group(CUSTOM_COMPILATION) in
AbstractJasperReportsTests excluded all JR tests when executing in the
IDE (e.g., Eclipse). This commit executes the assumption only where
necessary.
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.
// Until eclipse fully supports Java 8 use 1.7 source level
eclipse.jdt{
sourceCompatibility=1.7
targetCompatibility=1.7
sourceCompatibility=1.8
targetCompatibility=1.8
}
// Replace classpath entries with project dependencies (GRADLE-1116)
// http://issues.gradle.org/browse/GRADLE-1116
eclipse.classpath.file.whenMerged{classpath->
defregexp=/.*?\/([^\/]+)\/build\/[^\/]+\/(?:main|test)/// only match those that end in main or test (avoids removing necessary entries like build/classes/jaxb)
Some files were not shown because too many files have changed in this diff
Show More
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.