Supporting ScriptEngine#eval(String, Bindings) when no render function
is specified allows to support use cases where script templates are
simply evaluating a script expression with an even more simplified
configuration.
This improvement also makes it possible to use script engines that
do not implement Invocable.
Issue: SPR-15115
This commit also removes nullability from two common spots: ResolvableType.getType() and TargetSource.getTarget(), both of which are never effectively null with any regular implementation. For such scenarios, a non-null empty type/target is the cleaner contract.
Issue: SPR-15540
Beyond just formally declaring the current behavior, this revision actually enforces non-null behavior in selected signatures now, not tolerating null values anymore when not explicitly documented. It also changes some utility methods with historic null-in/null-out tolerance towards enforced non-null return values, making them a proper citizen in non-null assignments.
Some issues are left as to-do: in particular a thorough revision of spring-test, and a few tests with unclear failures (ignored as "TODO: NULLABLE") to be sorted out in a follow-up commit.
Issue: SPR-15540
With the new `ParsingPathMatcher` implementation, new patterns are now
allowed, such as `"/foo/{*bar}". The `"{*bar}"` segment will capture
everything until the end of the given path. Adding other elements after
that segment is illegal and will throw exceptions.
One can configure on a `PathMatchConfigurer` various options like
`useTrailingSlashMatch` and `useSuffixPatternMatch`; those options, when
enabled, will try to append suffixes like `".*"` and `"/"` to existing
path patterns. In case of a "capture the rest" pattern segment, those
options won't be honored.
This is why this commit ensures that an exception is thrown at the start
of the application if an illegal configuration is applied to the
`PathMatchConfigurer`.
Issue: SPR-15303, SPR-15558
This commit introduces 2 new @Nullable and @NonNullApi
annotations that leverage JSR 305 (dormant but available via
Findbugs jsr305 dependency and already used by libraries
like OkHttp) meta-annotations to specify explicitly
null-safety of Spring Framework parameters and return values.
In order to avoid adding too much annotations, the
default is set at package level with @NonNullApi and
@Nullable annotations are added when needed at parameter or
return value level. These annotations are intended to be used
on Spring Framework itself but also by other Spring projects.
@Nullable annotations have been introduced based on Javadoc
and search of patterns like "return null;". It is expected that
nullability of Spring Framework API will be polished with
complementary commits.
In practice, this will make the whole Spring Framework API
null-safe for Kotlin projects (when KT-10942 will be fixed)
since Kotlin will be able to leverage these annotations to
know if a parameter or a return value is nullable or not. But
this is also useful for Java developers as well since IntelliJ
IDEA, for example, also understands these annotations to
generate warnings when unsafe nullable usages are detected.
Issue: SPR-15540
Prior to this commit, resolving resources from webjars using the
`WebJarAssetLocator.getFullPath` could lead to multiple candidates,
since this method is trying to find *any* resource matching that path
under the given webjar location.
This commit replaces that call with
`WebJarAssetLocator.getFullPathExact`, which avoids those multiple
matches and only resolves resources if the given path is exact.
Issue: SPR-15526
(cherry picked from commit e2aa117ff9)
Prior to this commit, the AbstractFlashMapManager has used the
originating URI but the query string of the forwarded request. That
resulted to FlashMap not being matched even when both originating
URI and query string matched the FlashMap attributes. The originating
query string is now used to match the forwarded request.
Issue: SPR-15505
HttpMessageConverter's are client and server and arguably shouldn't
contain a server-side concept such a response status.
The status field is recent, it was added to differentiate 400 vs 500
errors with Jackson 2.9+ but there is no need for it since the same
distinction is reflected in raising an HttpMessageNotReadableException
vs a general HttpMessageConversionException.
Issue: SPR-15516
Spring MVC now treats Flux<String> + "application/json" as (serialized)
text to be written directly to the response as is. This is consistent
with the rendering of String + "application/json".
Issue: SPR-15456
InvalidDefinitionException has been introduced in Jackson 2.9 to be
able to differentiate invalid data sent from the client (should still
generate a 4xx HTTP status code) from server side errors like beans with
no default constructor (should generate a 5xx HTTP status code).
Issue: SPR-14925
This commit adds support for reactive library types to be returned
directly from controller methods adapting them either to a
ResponseBodyEmitter (streaming) or DeferredResult (non-streaming).
The reactive libraries supported are the ones that can adapted to a
Reactive Streams Publisher through the ReactiveAdapterRegistry.
Issue: SPR-15365
Revise Javadoc on AsyncHandlerMethodReturnValueHandler to clarify its
main purpose is to prioritze custom async return value handlers ahead
of built-in ones. Also replace the interface from built-in handlers
which are prioritized already.
Remove DeferredResultAdapter and ResponseBodyEmitterAdapter --
introduced in 4.3 for custom async return value handling, since for
5.0 we will add built-in support for reactive types and the value of
these contracts becomes very marginal.
Issue: SPR-15365
This commit changes `ResourceTransformerSupport` to look for the
`ResourceUrlProvider` in the current request if none is configured on
the resource transformer itself.
Issue: SPR-15369
Prior to this commit, the `VersionResourceResolver` implementations of
`resolveUrlPathInternal` would delegate to the resolver chain but would
never use the give result if the current request didn't match a
configured version strategy pattern.
This is a problem if the resolver supposed to resolve the resource path
is configured after a `VersionResourceResolver` in the resolver chain;
this means that other resolver never gets to participate in the result
of the chain.
Issue: SPR-15372
Includes a new overloaded ModelAndView constructor with an HttpStatus argument, as well as a HandlerMethodArgumentResolverSupport refactoring (revised checkParameterType signature, actually implementing the HandlerMethodArgumentResolver interface).
Issue: SPR-15199
This commit introduces a `useRegisteredExtensionsOnly` property that
indicates whether classes that use the `MediaTypeFactory` for supplying
default media types can do so.
- In classes that were introduced in Spring 5.0, the
`useRegisteredExtensionsOnly` property takes the place of the
`useJaf` property that was removed in 0aaa652
- In classes that existed before Spring 5.0, the
`useRegisteredExtensionsOnly` property is added in addition to the
deprecated `useJaf`, the latter delegating to the former, but with
flipped behavior.
Issue: SPR-14908
This commit changes the `MockServletContext.getMimeType` method to use
`MediaTypeFactory` instead of JAF. It also adds a `addMimeType(String,
MediaType)` method to customize the mime types returned from said
method.
Issue: SPR-14908
This commit updates the main code base to conform to the dropped JAF
dependency in MediaTypeFactory. Specifically, it
- Removes JAF detection (JAF_PRESENT constants)
- Deprecated useJaf properties, with no direct replacement.
- Updated docs to remove JAF references, in favor of MediaTypeFactory.
Issue: SPR-14908
This commit introduces a PathPatternParser which parses request pattern
strings into PathPattern objects which can then be used to fast
match incoming string paths. The parser and matching supports the syntax
as described in SPR-14544. The code is optimized around the common usages
of request patterns and is designed to create very little transient
garbage when matching.
Issue: SPR-14544
Codacy warns us that there are several references to Boolean
constructors in the tests. Direct usage of the Boolean constructor is
discouraged and even deprecated in Java 9 [1]. Boolean constructor use
can easily be replaced with the constant instances.
This commit contains the following changes:
- replace references to Boolean constructors with boolean constants in
JSP tag tests
- update the copyright year where necessary
- BooleanComparatorTests is intentionally left unchanged as it should
also work with the non-constant instances correctly
[1] http://download.java.net/java/jdk9/docs/api/java/lang/Boolean.html#Boolean-boolean-
Issue: SPR-15076
Kotlin JSR 223 support currently requires kotlin-script-util
dependency (jcabi-aether, maven-core and aether-api can be
excluded since they are only used for live import of
dependencies and bring a lot of JARs in the classpath) and a
/META-INF/services/javax.script.ScriptEngineFactory
file specifying the ScriptEngineFactory to use, in that case
org.jetbrains.kotlin.script.jsr223.KotlinJsr223JvmLocalScriptEngineFactory.
Issue: SPR-15059
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
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
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 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
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, `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
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
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
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
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
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, 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
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 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
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
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
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 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
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
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
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
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
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
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
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 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
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
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
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
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
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
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
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
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
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
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.
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
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
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, 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 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
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
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
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 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
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 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
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 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
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
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
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
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.
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.
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
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
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
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
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
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
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
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
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
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
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
- 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
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
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
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
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 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 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
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
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
Reinstate a variant of the `WebContentGenerator.checkAndPrepare` method
for projects that are using it.
This variant is now marked as deprecated.
Issue: SPR-11792
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
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
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.
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 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
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
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
- 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
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
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
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
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
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
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
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
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 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
Revised HandlerMethod.getBeanType() impl for both web and messaging.
In addition, HandlerMethods get created with the internal BeanFactory now.
Issue: SPR-12832
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 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 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
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.
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 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
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