This commit documents `ControllerAdviceBean` as internal usage, as it is
not meant for application to manually create controller advice bean
instances.
This also refactors the existing partial implementation of the support
for creating controller advice beans "programmatically".
Closes gh-32776
This commit makes sure to consistently check that the content length
is not set above 2GB. Previously it was only checked in
setContentLength.
Closes gh-33256
This application/javascript MIME type is deprecated.
This commit therefore changes the MIME type mapping for *.js files from
application/javascript to text/javascript in order to align with
industry standards.
Closes gh-33197
This change tracks the multipart nature of the async request
within the `DispatcherServlet`, in the `WebAsyncManager`.
This allows for the second ASYNC dispatch to recognize the
multipart aspect and clean up the associated resources.
Closes gh-33161
This commit makes sure that JAXBContext.newInstance consistently use
the target class classloader to detect the necessary resources.
Previously, the current thread's context classloader was used, which
could lead to not finding the required JAXB components.
Closes gh-33158
The result returned by Kotlin reflective invocation of a function
returning an inline value class is wrapped, which makes sense
from Kotlin POV but from a JVM perspective the associated value
and type should be unwrapped to be consistent with what
would happen with a reflective invocation done by Java.
This commit unwraps such result.
Closes gh-33026
This provides an implementation of an HTTP Handler Adapter that is coded
directly to the Eclipse Jetty core API, bypassing any servlet
implementation.
This includes a Jetty implementation of the spring `WebSocketClient`
interface, `JettyWebSocketClient`, using an explicit dependency to the
jetty-websocket-api.
Closes gh-32097
Co-authored-by: Lachlan Roberts <lachlan@webtide.com>
Co-authored-by: Arjen Poutsma <arjen.poutsma@broadcom.com>
Commit 84714fbae9 introduced usage of the
-Djava.locale.providers=COMPAT command-line argument for javac in order
to allow our JDK 20 builds to pass by using legacy locale data.
That was done to ensure that Date/Time formats using AM/PM produced a
standard space (" ") before the "AM" or "PM" instead of a narrow
non-breaking space (NNBSP "\u202F"), which was introduced in Java 20
due to adoption of Unicode Common Locale Data Repository (CLDR-14032).
This commit removes usage of the -Djava.locale.providers=COMPAT
command-line argument and updates all affected tests to:
- Use an NNBSP before "AM" or "PM" in input text when running on Java 20
or higher.
- Leniently match against any Unicode space character in formatted
values containing "AM" or "PM".
See https://jdk.java.net/20/release-notes#JDK-8284840
See https://unicode-org.atlassian.net/browse/CLDR-14032
See gh-30185
Closes gh-33144
SmartHttpMessageConverter is similar to GenericHttpMessageConverter,
but more consistent with WebFlux Encoder and Decoder contracts, with
the following differences:
- A ResolvableType parameter is used instead of the Type one
- The MethodParameter can be retrieved via the ResolvableType source
- No contextClass parameter
- `@Nullable Map<String, Object> hints` additional parameter for write
and read methods
This commit also refines RestTemplate#canReadResponse in order to use
the most specific converter contract when possible.
Closes gh-33118
Prior to this commit, the fix for gh-32730 disabled the involvment of
the osbervation filter for async dispatches. Instead of relying on ASYNC
dispatches to close the observation for async requests, this is now
using an async listener instead: async dispatches are not guaranteed to
happen once the async request is handled.
This change caused another side-effect: because async dispatches are not
considered anymore by this filter, the observation scope is not
reinstated for async dispatches. For example, `ResponseBodyAdvice`
implementations do not have the observation scope opened during their
execution.
This commit re-enables async dispatches for this filter, but ensures
that observations are not closed during such dispatches as this will be
done by the async listener.
Fixes gh-33091
Prior to this commit, the fix for gh-32575 introduced cases where the
client observation would be stopped twice.
This commit ensures that `RestClient` observations are stopped only once
when the response is closed, or before throwing an unhanlded exception.
Fixes gh-33068
Prior to this commit, the isClientDisconnectedException() method in
DisconnectedClientHelper checked whether the message of the ultimate
exception in an exception chain contained one of the phrases "broken
pipe" or "connection reset by peer". However, that failed to match if
the exception message contained "Connection reset", which is the case
for the SocketException thrown by throwConnectionReset() in
sun.nio.ch.SocketChannelImpl.
This commit therefore replaces the "connection reset by peer" phrase
with "connection reset" in order to support all exception messages
containing "connection reset".
Closes gh-33064
Prior to this commit, WebFlux had Protobuf codecs for managing the
`Message`/`"application/x-protobuf"` encoding and decoding.
The `com.google.protobuf:protobuf-java-util` library has additional
support for JSON (de)serialization, but this is not supported by
existing codecs.
This commit adds the new `ProtobufJsonEncode` and `ProtobufJsonDecoder`
classes that support this use case. Note, the `ProtobufJsonDecoder` has
a significant limitation: it cannot decode JSON arrays as
`Flux<Message>` because there is no available non-blocking parser able
to tokenize JSON arrays into streams of `Databuffer`. Instead,
applications should decode to `Mono<List<Message>>` which causes
additional buffering but is properly supported.
Closes gh-25457
This commit changes the use of HttpSessionRequiredException in
ModelFactory::initModel to an IllegalStateException, because the former
extends ServletException and cannot be used in WebFlux.
Closes gh-33043
This commit compiles our Protobuf against 4.27, effectively raising our
baseline to 3.9+.
This commit also re-generates all the Java messages from the .proto spec
using the latest protoc binary.
Closes gh-33011
Prior to this commit, the `ContentCachingRequestWrapper` could allocate
a `FastByteArrayOutputStream` block that was larger than the content
cache limit given as a consturctor argument. This was due to an
optimization applied in gh-31834 for allocating the right content cache
size when the request size is known.
Fixes gh-32987
Prior to this commit, the `ServerHttpObservationFilter` would support
async dispatches and would do the following:
1. start the observation
2. call the filter chain
3. if async has started, do nothing
4. if not in async mode, stop the observation
This behavior would effectively rely on Async implementations to
complete and dispatch the request back to the container for an async
dispatch. This is what Spring web frameworks do and guarantee.
Some implementations complete the async request but do not dispatch
back; as a result, observations could leak as they are never stopped.
This commit changes the support of async requests. The filter now
opts-out of async dispatches - the filter will not be called for those
anymore. Instead, if the application started async mode during the
initial container dispatch, the filter will register an AsyncListener to
be notified of the outcome of the async handling.
Fixes gh-32730
Commit d7970e4ab8 introduced support for JAXBElement in
Jaxb2XmlEncoder's encodeValue() method; however, canEncode() still
returned false for a JAXBElement element type.
This commit revises canEncode() so that it returns true for an element
type that is assignable from JAXBElement.
See gh-30552
See gh-32972
Closes gh-32977
This commit adds support for the "Partitioned" cookie attribute in
WebFlux servers and the related testing infrastructure.
Note, Undertow does not support this feature at the moment.
Closes gh-31454
Prior to this commit, #31870 added support for constraint annotations on
container elements for handler method argument validation. Supporting
this use case:
```
public void addNames(List<@NotEmpty String> names)
```
This commit does the same for `@Valid` annotation:
```
public void addPeople(List<@Valid Person> people)
```
Fixes gh-32964
This commit ensures that the FormHttpMessageConverter no longer supports
reading Maps (just MultiValueMaps). Plain maps are often used to
represent JSON.
See gh-32826
This commit makes several improvements to MultiValueMap:
- asSingleValueMap offers a single-value view (as opposed to the
existing toSingleValueMap, which offers a copy)
- fromSingleValue is a static method that adapts a Map<?,?> to the
MultiValueMap interface
- fromMultiValue is a static method that adapts a Map<?,List<?>> to the
MultiValueMap interface
Closes gh-32832
This commit changes the FormHttpMessageConverter from a
HttpMessageConverter<MultiValueMap<String, ?>> to a
HttpMessageConverter<Map<String, ?>>, so that normal, single-value maps
can also be used as form representation, both for reading and writing.
Closes gh-32826
This commit allows to extend the `ServerHttpObservationFilter` when the
observation scope is opened. This typically allows to add the current
traceId as a response header.
Closes gh-30632
Includes JAXBContext locking revision (avoiding synchronization) and consistent treatment of DocumentBuilderFactory (in terms of caching as well as locking).
Closes gh-32851
Prior to this commit, `@ExceptionHandler` annotated controller methods
could be mapped using the exception type declaration as an annotation
attribute, or as a method parameter.
While such methods support a wide variety of method arguments and return
types, it was not possible to declare the same exception type on
different methods (in the same controller/controller advice).
This commit adds a new `produces` attribute on `@ExceptionHandler`; with
that, applications can vary the HTTP response depending on the exception
type and the requested content-type by the client:
```
@ExceptionHandler(produces = "application/json")
public ResponseEntity<ErrorMessage> handleJson(IllegalArgumentException exc) {
return ResponseEntity.badRequest().body(new ErrorMessage(exc.getMessage(), 42));
}
@ExceptionHandler(produces = "text/html")
public String handle(IllegalArgumentException exc, Model model) {
model.addAttribute("error", new ErrorMessage(exc.getMessage(), 42));
return "errorView";
}
```
This commit implements support in both Spring MVC and Spring WebFlux.
Closes gh-31936
The code was necessary while ForwardedHeaderFilter was deprecated
but still possible to use. When the filter was removed, this code
could have been removed as well.
Prior to this commit, `DataBufferLimitException` would be thrown by
codecs when the request body was too large for the configured buffer
limit. This exception would not be handled by the web infrastructure and
would result in an HTTP 500 server error.
This commit introduces a new `PayloadTooLargeException` type that will
result in an HTTP 413 "Payload too large" response status.
Closes gh-32558
Improvements include:
- Replace throwing exceptions with failure results in hot areas,
- Verify digits of a string before passing it to Integer::parseInt
- Lazily initialization of fields
- Using LinkedList instead of ArrayList where size is not known
beforehand
See gh-32513
Prior to this commit, HTTP requests sent with the
`HttpComponentsClientHttpRequestFactory` would not set a
"Content-Length" header for empty request bodies. Setting a request
entity is the expected behavior for unsafe HTTP methods, and this would
align the behavior with other HTTP clients.
Developers would often rely on `BufferingClientHttpRequestFactory` to
set this information on the request.
This commit ensures that a `NullEntity` is used for unsafe HTTP methods,
when no body has been set for the request. This result in a
"Content-Length:0" request header.
Fixes gh-32678
This commit changes the guard against multiple subscriptions, as the
previously used doOnSubscribe hook could not function as guard in
certain scenarios.
Closes gh-32727
This commit changes the guard against multiple subscriptions, as the
previously used doOnSubscribe hook could not function as guard in
certain scenarios.
Closes gh-32727
This is equivalent of the same contract for WebFlux. It is implemented
by HandlerMappingIntrospector, and may be called directly by Spring
Security to handle a pre-flight request without delegate to the rest
of the filter chain.
HandlerMappingIntrospector also has the boolean method
allHandlerMappingsUsePathPatternParser that checks whether all handler
mappings are configured to use parsed PathPattern's.
See gh-31823
Prior to this commit, `RestClientException` thrown by status handlers
would not be registered as observation errors. This commit ensures that
such exceptions are first caught, registered in the observation and
rethrown as expected.
Closes gh-32575
Prior to this commit, the `RestClient` observations would be stopped as
soon as the exchange function was called. This means that all errors
related to response decoding or mapping would not be recorded by the
obsevations.
This commit extends the observation recording to the `ResponseSpec` DSL
calls as well as custom exchange functions.
Fixes gh-32575
Prior to this commit, `HttpHeaders#setContentLength` would accept
negative values. Those are not allowed by the RFC and the headers
implementation only uses "-1" as a way to convey that no value was set.
This commit ensures that negative values are rejected.
Fixes gh-32660
Prior to this commit, the `BufferingClientHttpRequestFactory`, through
the `AbstractBufferingClientHttpRequest`, would set a "Content-Length"
header value, even if the buffered body was empty.
This behavior is invalid since no request body would be set by the
client code in the first place.
This commit ensures that this header is only set if a request body has
been buffered and is about to be written to the request.
Fixes gh-32650
This commit introduces a new URL parser based on algorithm provided in
the Living URL standard. This new UrlParser is used by
UriComponentsBuilder::fromUriString, replacing the regular expressions.
Closes gh-32513
Before this change temporary files would not consistently be deleted
when the connection which uploads the multipart files closes naturally.
This change uses the usingWhen Reactor operator to ensure that the
termination of the connection doesn't prevent individual file parts
from being deleted due to a cancellation signal.
Closes gh-31217
This commit refines the expressions for the scheme, user info, host and
port parts of the URL in UriComponentsBuilder to better conform to
RFC 3986.
Fixes gh-32616
Prior to this commit, `BufferingClientHttpRequestWrapper` would always
write to the actual client request body, even if the buffered content
was empty (empty byte array).
This would cause issues with specific client request factories,
especially the OkHttp variant, that would consider empty byte arrays as
non-empty body and would reject such cases for GET requests with an
"IllegalArgumentException: method GET must not have a request body".
This commit only writes to the request if the buffered content is not
empty.
Fixes gh-32612
This commit ensures that the response body is drained and closed when
the response itself is closed, instead of disposing the connection, as
this will disable the connection pool.
Closes gh-32528
This commit reverts some null-safety changes which make sense
on main but are too impactful for 6.1.x for Kotlin developers
using -Xjsr305=strict.
See gh-32475
Prior to this commit when a required parameter defined as a property or
expression placeholder was missing, the exception thrown would refer to
the placeholder instead of the resolved name.
This change covers messaging handlers and web controllers, both blocking
and reactive. It also fixes the error message when handling null values
for non-required parameters, as well as in cases that need conversion.
See gh-32323
Closes gh-32462
The fix for #31254 resulted in an InvalidMimeTypeException being thrown
by MimeTypeUtils.sortBySpecificity() instead of an
IllegalArgumentException. However, InvalidMimeTypeException extends
IllegalArgumentException. Consequently, the change from
IllegalArgumentException to InvalidMimeTypeException did not result in
the desired effect in HeaderContentNegotiationStrategy.
HeaderContentNegotiationStrategy.resolveMediaTypes() still allows the
InvalidMimeTypeException to propagate as-is without wrapping it in an
HttpMediaTypeNotAcceptableException.
To address this issue, this commit catches InvalidMediaTypeException
and InvalidMimeTypeException in HeaderContentNegotiationStrategy and
wraps the exception in an HttpMediaTypeNotAcceptableException.
See gh-31254
See gh-31769
Closes gh-32483
Historically, we have rarely intentionally thrown a
NullPointerException in the Spring Framework. Instead, we prefer to
throw either an IllegalArgumentException or IllegalStateException
instead of a NullPointerException.
However, changes to the code in recent times have introduced the use of
Objects.requireNonNull(Object) which throws a NullPointerException
without an explicit error message.
The latter ends up providing less context than a NullPointerException
thrown by the JVM (since Java 14) due to actually de-referencing a
null-pointer. See https://openjdk.org/jeps/358.
In light of that, this commit revises our current use of
Objects.requireNonNull(Object) by removing it or replacing it with
Assert.notNull().
However, we still use Objects.requireNonNull(T, String) in a few places
where we are required to throw a NullPointerException in order to
comply with a third-party contract such as Reactive Streams.
Closes gh-32430
Prior to this commit, gh-21783 introduced `ReadOnlyHttpHeaders` to avoid
parsing media types multiple times during the lifetime of an HTTP
exchange: such values are cached and the headers map is made read-only.
This also added a new `HttpHeaders.writableHttpHeaders` method to unwrap
the read-only variant when needed.
It turns out this method sends the wrong signal to the community
because:
* the underlying map might be unmodifiable even if this is not an
instance of ReadOnlyHttpHeaders
* developers were assuming that modifying the collection that backs the
read-only instance would work around the cached values for
Content-Type and Accept headers
This commit adds more documentation to highlight the desired behavior
for cached values by the read-only variant, and deprecates the
`writableHttpHeaders` method as `ReadOnlyHttpHeaders` is package private
and we should not surface that concept anyway.
Instead, this commit unwraps the read-only variant if needed when a new
HttpHeaders instance is created.
Closes gh-32116
This commit adds support for application/yaml in MediaType and leverages
jackson-dataformat-yaml in order to support Yaml in RestTemplate,
RestClient and Spring MVC.
See gh-32345