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
Also fix a couple of related issues:
- add AsyncRequestNotUsableException to the list of exceptions
that imply response issues.
- handle exceptions from @ExceptionHandler regardless of whether
thrown immediately or via Publisher.
Closes gh-32359
The following adjustments are also made as a result:
- Use int to check if lock is held and unlock is needed, given that
for non-async requests we don't need to obtain a lock.
- Protect access methods getOutputStream and getWriter with the
same locking and state checks.
Closes gh-32340
This commit updates ServletServerHttpResponse.ServletResponseHttpHeaders
in order to use ServletResponse#getContentType instead of
ServletResponse#getHeader.
It allows to have a consistent behavior between Tomcat (which sets only
the former) and Undertow/Jetty (which set both).
Closes gh-32339
ServletResponseHttpHeaders#get should be annotated with `@Nullable` and
return null instead of a singleton list containing null when there is no
content type header.
Closes gh-32362
In addition to using the ServletOutputStream, it's also possible to call
ServletResponse#flushBuffer, so the ServletOutputStream wrapper logic needs
to apply there as well.
See gh-32340