Prior to this commit, gh-30953 fixed a case where multipart file parts
were not emitted properly when the body itself is empty.
There are other cases like this, depending on the order and slicing of
data buffers received by the parser. Here, a buffer containing the
entire boundary would not cause an empty file part to be emitted and
instead switch to the next header.
This commit ensures that empty file parts are always emitted as they
should.
Fixes gh-37264
Prior to this commit, Hibernate 8 types extending
`MutationOrSelectionQuery` would fail proxying at runtime in native
images because reflection hints were not registered at build time.
While the `MutationOrSelectionQueryImpl` case can be solved with an
additional proxy hint, `NativeMutationOrSelectionQueryImpl` is
impossible to solve that way due to multi interface mismatch.
This was found in gh-36878 and handled with a fallback proxy.
In this case, native image will throw a
`MissingReflectionRegistrationError` - but obviously we cannot depend on
this type in JVM applications. `MissingReflectionRegistrationError`
extends `LinkageError`, which we will use along
IllegalArgumentException` to detect that the proxying operation failed
and that we should use the fallback.
This commit also register a proxy hint for the said fallback.
Fixes gh-37251
Prior to this commit, calling `DefaultAsyncServerResponse.writeAsync()`
would unconditionally create a new `AsyncWebRequest` and install it
on the `WebAsyncManager`, even when one is already present for the
current request.
The functional web framework can do such a thing when returning a
`ServerResponse.async(future)` from a `HandlerFunction`; the
`HandlerFunctionAdapter` does install an async web request already.
This means that the async timeout configured at the application level
would be ignored and instead falling back to the Servlet container
default.
This commit makes the `DefaultAsyncServerResponse` skip async web
request creation it there is an existing one.
Fixes gh-37257
This commit makes use of the Java specification version in the Jar
metadata to make build easier to reproduce on a different environment.
Closes gh-37250
This commit adds the missing reflection hints for Hibernate 8 support:
`PersistenceUnitInfoDescriptor` and `StatelessSession`.
Fixes gh-37247
Fixes gh-37249
Most of the documentation updates were already done in gh-36803, this
completes the section with some information on the property path syntax
supported by allowFields/disallowFields.
Closes gh-36789
Prior to this commit, the reconnection attempt count provided to the
reconnect strategy would not give the updated, incremented value but
instead the previous one.
This commit fixes this and ensures the value is incremented before it's
given to the strategy.
Fixes gh-37223
Prior to this commit, the `DefaultClientResponseBuilder` would assume
that an original client HTTP response, when mutated, would not be reused
nor read anymore. While this is the advised use case, there was some
inconsistency with the builder API here when mutating: some data like
the response status would copied, but the HTTP headers and cookies would
refer directly to the previous entries, making all changes visible to
the previous response instance.
This commit ensures that deep copies are performed when mutating a
client response with the builder API.
Fixes gh-37086
Prior to this commit,
`MockHttpServletRequest.isRequestedSessionIdValid()` would return `true`
by default and could only be changed manually with a setter. This does
not align with the Servlet spec because of 1) its default value and 2)
it does not react to `changeSessionId()` calls.
This commit fixes that behavior while still allowing "manual" booleans
being set here.
Fixes gh-36631
Prior to this commit, many classes would support writing Server Sent
Events in some way to the response output stream. This has lead to some
code duplication.
This commit refactors the duplicated code in a shared `SseUtils` class.
Closes gh-37065
Prior to this commit, building a "Content-Disposition" header to a
String and then parsing it back would not always result in the original
header.
This commit ensures that ContentDisposition guarantees this and honors
the "equals" contract.
Fixes gh-37064
Prior to this commit, the MVC and WebFlux view fragments rendering would
only partially escape rendered view fragments before sending then as SSE
events. This could in some cases break the SSE stream with invalid data.
This commit ensures that the rendered views are properly escaped before
they are sent as SSE events.
Fixes gh-37061
This commit ensures that workflow dispatches to docs build only happen
on OSS branches.
This also upgrades the verification project to the latest version.
See gh-37097
Prior to this commit, `ClassFileAnnotationDelegate#parseArrayValue`
would only consider `int[]`, `double[]` and `long[]` array
annotation attributes; other primitive array types like `byte[]`
would use a generic path that would use boxed types.
This commit ensures that a comprehensive pass is made for all
primitive typed arrays. Because the `AnnotationValue` hierarchy
is sealed, we can now maje sure that the implementation is
exhaustive.
Closes gh-37083
Prior to this commit, gh-36328 avoided using RFC 2047 encoding for the
"filename" parameter and use ISO-8859-1 only. This change unfortunately
caused issues because some implementations might try and detect the
encoding automatically.
This commit restricts the filename parameter to ASCII encoding only by:
* transliterating characters to the closes ASCII character
("é"->"e", "ä"->"ae"...)
* falling back to "_" for other chacacters with non latin alphabet or
emojis
Closes gh-37062
Prior to this commit, module javadoc packages like
"spring-core-7.0.8-javadoc.jar" would contain 4MB of web fonts in the
`resource-files/fonts/` folder. This increases significantly (often
doubles) the size of the javadoc JAR for little value.
With this commit, Web fonts are packaged with the aggregated Javadocs
for the entire Spring Framework project, but are skipped for inidividual
modules.
Closes gh-36889
This commit adds further fixes in the same area, since there were
similar bugs in the WriteCompletionHandler:
* databuffers were not always emitted when fully read in the onNext hook
* on completion, the iterator was closed too early, before it was fully
read
* on completion, writing the next bytebuffers from the iterator would
always reuse the first one and not update the attachment
Closes gh-36714
This fixes a potential regression introduced by the previous commit.
Because the current value was not updated after the temporal was rolled
forward, there were new cases where entire days would be skipped.
Closes gh-36865
Prior to this commit, comments sent with Server Sent Events could break
the wire format when sent over the network when comments contained line
breaks.
While comments are mainly used for sending keepalive messages, they can
also be used for sending debug data. This commit ensures that line
breaks are properly handled in comments.
Fixes gh-36866
Prior to this commit, MIME types with parameter values that contain a
quoted pair would sometimes fail and parse an incomplete parameter
value.
This commit ensures that the quoted section of the parameter value is
correctly handled.
Fixes gh-36730
Prior to this commit, the `resolveUrlPath` implementation for the
`LiteWebJarsResourceResolver` would always delegate to the resource
chain once the versioned webjar folder has been resolved.
While this aligns with the `ResourceResolver` contract and the fact that
the resource chain does not resolve directories, here the WebJar locator
does support such use cases and we shouldn't get in the way here.
This commit falls back to the resolved versioned WebJar path if no
resource could be resolved and the path ends with "/".
Fixes gh-36726
Prior to this commit, the `PartGenerator` would allow requesting
additional part tokens while in the `CreateFileState`. This is invalid
as any new token emitted would be rejected and would fail the entire
process.
This would only happen if the tmp file creation is slow enough for a new
token to be parsed and emitted.
This commit ensures that no new part token is requested while creating
the temporary file.
This change also fixes lifecycle issues and ensures that buffer
resources are cleaned in case of errors.
Fixes gh-36694
Prior to this commit, there could be cache collisions in the
`CachingResourceResolver` because the cache key generation was
incomplete. This commit expands the cache key generation to avoid such
cases.
Fixes gh-36713
Prior to this commit, content based version strategies would remove all
instances of the version string in the request path when trying to
resolve the original resource with the chain.
This can cause issues in rare cases where there is a collision between
the content version and some other version string in the request path.
Because this strategy is based on the contents of the file itself, we
should only remove the last instance of the version string and then
attempt to resolve the original file.
Fixes gh-36698
Prior to this commit, `ResourceHandlerUtils` would perform resource
location checks to ensure that the configured location is valid. This
commit also ensures that we log a WARN message if the application
chooses a well-known unsafe location like "classpath:" or the root
Servlet context for serving static resources.
Closes gh-36692
Prior to this commit, fields that are not allowed for binding were
always skipped and would not be bound. But the field and default marker
support (with the "_" and "!" prefixes) would be still considered and
could trigger collection instantiation/autogrow.
While this does not cause unwanted binding, this allocates memory for no
reason. This commit revisits the binding algorithm to only consider
default and field marker support if the regular field is allowed.
Fixes gh-36625
Prior to this commit, the ClassFile variant for annotation and method
metadata would report incorrect metadata for:
* the method return type names in case of primitives and array types
* `toString` values for methods
* `equals` and `hashcode` information for methods
This commit expands the test suite and ensures that the ASM and
ClassFile variants are aligned.
Fixes gh-36577
Signed-off-by: Brian Clozel <brian.clozel@broadcom.com>
Prior to this commit, all `with**Converter` methods in
`HttpMessageConverters` builders would only apply if the
`registerDefaults()` option is on. While the original intent is to allow
overrides for auto-detected defaults, this creates an unnecessary
discrepancy with `addCustomConverter` which is always effective.
Allowing sich registrations when defaults are off should not introduce
invalid states and only reflects the intent of the developer. This
commit now allows such cases.
Fixes gh-36579
Now that `RestClient` offers a better alternative, this commit revisits
our integration tests to use `RestClient` instead of `RestTemplate`.
Closes gh-36573
Prior to this commit, `MockRestServiceServer` would provide
`createServer` shortcuts for `RestTemplate` and `RestGatewaySupport`.
Now that `RestClient` offers a modern client variant, we should provide
the same for `RestClient`.
Closes gh-36572
Prior to this commit, the `SockJsClient` would use the
`RestTemplateXhrTransport`. `RestClient` is a modern replacement for
RestTemplate and should be used instead.
This commit introduces the `RestClientXhrTransport` variant as an
immediate replacement.
Closes gh-36566
Prior to this commit, `SseServerResponse.send()` would flush the
output stream returned by `getBody()`. Since gh-36385,
`ServletServerHttpResponse` wraps this stream with a non-flushing
decorator to avoid performance issues with `HttpMessageConverter`
implementations that flush excessively. As a result, SSE events were
no longer flushed to the client.
This commit changes `send()` to call `outputMessage.flush()` instead
of `body.flush()`, which properly delegates to the servlet response
`flushBuffer()` and is not affected by the non-flushing wrapper.
Fixes gh-36537
This commit links the Spring Framework Observability section in the
reference documentation to the Micrometer docs describing how
Observations are handled as metrics.
Closes gh-34994
Prior to this commit, the `DefaultRestClient` implementation would
look at the type of the returned value to decide whether the HTTP
response stream needs to be closed before returning.
As of gh-36380, this checks for `InputStream` and `InputStreamResource`
return types, effectively not considering `ResponseEntity<InputStream>`
and variants.
This commit ensures that `ResponseEntity` types are unwrapped before
checking for streaming types.
Fixes gh-36492
Prior to this commit, different resource resolvers would resolve
accepted codings from the HTTP request sent by the client. This would be
done with different implementations, which could lead to resolution
errors and desynchronizations.
This commit now introduced a new shared method in
`EncodedResourceResolver` (Servlet and Reactive) to perform a consisten
resolution.
Fixes gh-36507
Prior to this commit, the `StandardWebSocketUpgradeStrategy` would get
the HTTP headers from the handshake request and store them in the
WebSocket session for the entire duration of the session.
As of gh-36334, Spring MVC manages HTTP directly with a native API
instead of copying them. This improves performance but also uncovered
this bug: we cannot keep a reference to HTTP headers once the HTTP
exchange is finished, because such resources can be recycled and reused.
This commit ensures that the handshake headers are copied into the
session info to keep them around for the entire duration of the session.
Without that, Tomcat will raise an `IllegalStateException` at runtime.
This was already done for WebFlux in SPR-17250, but the latest header
management changes in Framework uncovered this issue for the Standard
WebSocket container case.
Fixes gh-36486
Prior to this commit, the `WebTestClient` could only accept non-nullable
types in its `expectBodyList<T>` Kotlin extension function.
This commit relaxes this requirements to allow for more assertions.
Fixes gh-36476
This commit ensures that `ParameterizedTypeReference<T>` can accept
nullable types. This is especially useful for Kotlin extension functions
and assertion contracts.
Fixes gh-36477
Prior to this commit, the `ClassFile` based implementation of
`AnnotationMetadata` would rely on the `NestHost` class element to get
the enclosing class name for a nested class.
This approach works for bytecode emitted by Java11+, which aligns with
our Java17+ runtime policy. But there are cases where bytecode was not
emitted by a Java11+ compiler, such as Kotlin. In this case, the
`NestHost` class element is absent and we should instead use the
`InnerClasses` information to get it.
This commit makes use of `InnerClasses` to get the enclosing class name,
but still uses `NestHost` as a fallback for anonymous classes.
Fixes gh-36451
Prior to this commit, the `setMessageConverters` method would have
private visibility. But `initBodyConvertFunction`, which is `protected`,
relies on the message converters being set in the first place.
While this works with `RestTemplate` because this is done automatically,
the `RestClient` does offer a builder method to configure a
`ResponseErrorHandler` and this makes it impossible to configure
converters in this case.
This commit aligns the method visibility by making it protected.
Closes gh-36434
Prior to this commit, our implementation of Server Sent Events (SSE),
`SseEmitter` (MVC) and `ServerSentEvent` (WebFlux), would not guard
against invalid characters if the application mistakenly inserts such
characters in the `id` or `event` types.
Both implementations would also behave differently when it comes
to escaping comment multi-line events.
This commit ensures that both implementations handle multi-line comment
events and reject invalid characters in id/event types.
This commit also optimizes `String` concatenation and memory usage
when writing data.
Fixes gh-36440
Prior to this commit, flush calls on the output stream returned by
`ServletServerHttpResponse#getBody` would be delegated to the Servlet
response output stream.
This can cause performance issues when `HttpMessageConverter` and other
web components write and flush multiple times to the response body.
Here, the Servlet container is in a better position to flush to the
network at the optimal time and buffer the response body until then.
This is particularly true for `HttpMessageConverters` when they flush
many times the output stream, sometimes due to the underlying codec
library. Instead of revisiting the entire message converter contract, we
are here ignoring flush calls to that output stream.
This change does not affect the client side, nor the
`ServletServerHttpResponse#flush` calls.
This commit also introduces a new Spring property
`"spring.http.response.flush.enabled"` that reverts this behavior change
if necessary.
Closes gh-36385
Prior to this commit, a few implementations of the `HttpMessageConverter`
contract were inheriting from abstract classes. Those classes were
performing extra `OutputStream#flush` on the response body even though
this is the responsibility of the super class. Such abstract classes
do flush already, after delegating to the `writeInternal` method.
This commit ensures that we remove such extra calls as they tend to
waste resources for no added benefit.
Closes gh-36383
This commit updates the target type detection in
`ResourceHttpMessageConverter` to only support target types that are
relevant: `InputStreamResource` for streaming, and types assignable from
`ByteArrayResource` for non-streaming cases.
Closes gh-36368
The `AbstractMessageConverterMethodProcessor` is in charge of handling
controller method return values and to write those as HTTP response
messages. The content negotiation process is an important part.
The `MimeTypeUtils#sortBySpecificity` is in charge of sorting inbound
"Accept" media types by their specificity and reject them if the list
is too large, in order to protect the application from ddos attacks.
Prior to this commit, the content negotiation process would first get
the sorted "Accept" media types, the producible media types as
advertized by message converters - and collect the intersection of both
in a new list (also sorted by specificity). If the "Accept" list is
large enough (but under the limit), the list of compatible media types
could exceed that limit because duplicates could be introduced in that
list: several converters can produce the same content type.
This commit ensures that compatible media types are collected in a set
to avoid duplicates. Without that, exceeding the limit at this point
will throw an `InvalidMimeTypeException` that's not handled by the
processor and result in a server error.
Fixes gh-36300
This commit fixes the `configureMessageConverters` and
`configureMessageConvertersList` behavior.
`configureMessageConverters` was not executing consumers in their order
of registration (but in the reverse order).
`configureMessageConvertersList` was not executing multiple consumers
and was instead executing the first consumer multiple times.
This commit fixes both issues.
Fixes gh-36332
Prior to this commit, the reactive `MultipartParser` and `PartGenerator`
types were leaking memory at runtime in specific cases:
* many HTTP clients must send multipart requests to be parsed and close
the connection while uploading
* the `PartGenerator` must be configured to write file parts to
temporary files on disk
* concurrency, upload speed must be important to trigger cases where the
file system is not fast enough to consume incoming buffers
The `MultipartParser` parses and emits `BodyToken` to its sink
(here, the `PartGenerator`). By definition, Reactor's `FluxSink` when
created with `Flux.create(FluxSink)` will use a "buffer" strategy and
will queue emitted elements if they cannot be consumed.
Here, the cancellation signal does dispose internal states in the
`MultiPartParser` and `PartGenerator` but does not clear the internal
queue in `FluxSink`.
This commit ensures that an operation is registered to release buffers
on the discard event.
Fixes gh-36262
Prior to this commit, the `MediaType` and `MimeType` "copy" constructors
would not leverage the fact that the existing instance has been
validated already (types, subtype and parameters have been checked
already for errors) and the entire validation would be performed again.
This would also allocate map instances in the process.
This commit ensures that the already validated information is reused
directly and that we avoid unnessecary operations and allocations for
such constructors.
Closes gh-36318
The builder for `HttpMessageConverters` allows for auto-detection of
message converters on the classpath and their default registration when
`registerDefaults()` is called. Once called, there is no way to undo
this.
This commit adds a new `disableDefaults()` method to disable the default
registration and take full control over the list of message converters.
Closes gh-36303
Prior to this commit, the `HttpEntityMethodProcessor` would create a new
`ServletServerHttpRequest` input message to parse the native Servlet
request, but would not reuse it for reading the request body using the
message converters.
In gh-32471, we applied a change that updates HTTP headers accordingly
when request parameters are read. But not reusing the input message
means that we are losing this update when instantiating the resulting
`HttpEntity`.
This commit ensures that `HttpEntityMethodProcessor` uses the input
message it just created when decoding the request body.
Fixes gh-36298
Prior to this commit, the "application/*+json" wildcard MIME type was
added to the list of supported MIME types in the JSON messaging
converter. This change wasn't fully reflected in the
`AbstractMessageConverter`, because only strict matching of type and
subtybe were considered.
This commit updates the `AbstractMessageConverter` to not only check the
type and subtype, but also check whether the supported MIME type
includes the one given as a parameter.
Fixes gh-36285
Prior to this commit, the `Netty4HeadersAdapter` `MultiValueMapi#remove`
implementation would return an empty list if no value was present. This
is not consistent with other implementations.
This change ensures that `null` is returned for those cases.
Fixes gh-36226
This commit updates the HttpComponents HttpClient to refer to the parsed
`HttpEntity` for the content-related HTTP response headers such as
encoding and body length.
Closes gh-36100
This commit updates the `HttpHeaders` javadoc to better reflect that
`asSingleValueMap()`, `asMultiValueMap()`, and `toSingleValueMap()` all
return case-sentitive map implementations.
Closes gh-36070
In gh-35947, the `Converter` contract was refined to allow for nullable
return values. This created a mismatch with the `ConverterFactory`
contract.
This commit fixes this mismatch by allowing nullable return values in
`Converter` instances created by `ConverterFactory`.
Fixes gh-36063
Prior to this commit, the `StringHttpMessageConverter` would perform a
flush after writing the body, via `StreamUtils#copy`. This operation is
not needed as a flush is already performed by the abstract class.
Flush calls by HTTP message converters is being reconsidered altogether
in gh-35427, but we should first remove this extra operation.
Closes gh-36065
Prior to this commit, we found in gh-35953 that using the `WebTestClient`
the following way leaks data buffers:
```
var body = client.get().uri("download")
.exchange()
.expectStatus().isOk()
.returnResult()
.getResponseBodyContent();
```
Here, the test performs expectations on the response status and headers,
but not on the response body. The WiretapConnector already supports this
case by subscribing to the Flux response body in those cases and
accumulating the entire content as a single byte[].
Here, the `DataBuffer` instances are not decoded by any `Decoder` and
are not released. This results in a memory leak.
This commit ensures that the automatic subscription in
`WiretapConnector` also releases the buffers automatically as the DSL
does not allow at that point to go back to performing body expectations.
Fixes gh-36050
Prior to this commit, the `RfcUriParser` would ignore URI fragments if
their length is < 2. This commit fixes the length check to allow for
single char fragments when parsing URIs.
Fixes gh-36029
Prior to this commit, the `JdkClientHttpRequest` would add all values
from `HttpHeaders` to the native request builder. This could cause
`NullPointerException` being thrown at runtime because the `HttpClient`
does not support that.
This commit replicates a fix that was applied to the
`SimpleClientHttpRequest`, turning null values into empty "".
Fixes gh-35996