Prior to this commit, a DataSize input string could not be parsed if it
contained any whitespace.
With this commit, a DataSize input string can contain leading, trailing,
or 'in between' whitespace. For example, the following will be parsed
to the same DataSize value.
- "1024B"
- "1024 B"
- " 1024B "
- " 1024 B "
Closes gh-28643
Commit d6768ccc18 introduced a regression in the support for merging
annotation attributes in a multi-level annotation hierarchy.
This commit addresses that issue by ensuring that a merged annotation
is once again synthesized if a meta-annotation in the annotation
hierarchy declares attributes that override attributes in the target
annotation.
Closes gh-28716
Prior to this commit, meta-annotations were unnecessarily synthesized
when attempting to synthesize a MergedAnnotation retrieved via the
MergedAnnotations.from(AnnotatedElement, ...).get(<annotationType>) API.
This is a regression in our merged annotation support that was
introduced when the MergedAnnotations API replaced our previous support.
This commit fixes this by revising the logic in TypeMappedAnnotation's
createSynthesizedAnnotation() method so that a meta-annotation is
returned unmodified if it is not synthesizable.
This commit also updates BootstrapUtilsTests, since @BootstrapWith
should never have been synthesized, and Class#getCanonicalName() is
only used in the toString() implementation of an annotation synthesized
by Spring or normal annotations on Java 19+ (see
https://bugs.openjdk.org/browse/JDK-8281462).
Closes gh-28704
Prior to this commit, ObjectToObjectConverter considered the return
type of non-static `to[targetType.simpleName]()` methods but did not
consider the return type of static `valueOf(sourceType)`,
`of(sourceType)`, and `from(sourceType)` methods.
This led to scenarios in which `canConvert()` returned `true`, but a
subsequent `convert()` invocation resulted in a
ConverterNotFoundException, which violates the contract of the
converter.
This commit addresses this issue by taking into account the return type
of a static valueOf/of/from factory method when determining if the
ObjectToObjectConverter supports a particular conversion. Whereas the
existing check in `determineToMethod()` ensures that the method return
type is assignable to the `targetType`, the new check in
`determineFactoryMethod()` leniently ensures that the method return
type and `targetType` are "related" (i.e., reside in the same type
hierarchy).
Closes gh-28609
The TYPE_HIERARCHY_AND_ENCLOSING_CLASSES search strategy for
MergedAnnotations was originally introduced to support @Nested test
classes in JUnit Jupiter (see #23378).
However, while implementing #19930, we determined that the
TYPE_HIERARCHY_AND_ENCLOSING_CLASSES search strategy unfortunately
could not be used since it does not allow the user to control when to
recurse up the enclosing class hierarchy. For example, this search
strategy will automatically search on enclosing classes for static
nested classes as well as for inner classes, when the user probably
only wants one such category of "enclosing class" to be searched.
Consequently, TestContextAnnotationUtils was introduced in the Spring
TestContext Framework to address the shortcomings of the
TYPE_HIERARCHY_AND_ENCLOSING_CLASSES search strategy.
Since this search strategy is unlikely to be useful to general users,
the team has decided to deprecate this search strategy in Spring
Framework 5.3.x and remove it in 6.0.
Closes gh-28079
SocketUtils was introduced in Spring Framework 4.0, primarily to assist
in writing integration tests which start an external server on an
available random port. However, these utilities make no guarantee about
the subsequent availability of a given port and are therefore
unreliable. Instead of using SocketUtils to find an available local
port for a server, it is recommended that users rely on a server's
ability to start on a random port that it selects or is assigned by the
operating system. To interact with that server, the user should query
the server for the port it is currently using.
SocketUtils is now deprecated in 5.3.16 and will be removed in 6.0.
Closes gh-28052
In 3ec612aaf8, I accidentally removed tests that verified support for
non-synthesizable merged annotations for recursive annotations in
Kotlin.
This commit reinstates those non-synthesizable tests while retaining
the synthesizable tests.
Although Java does not allow the definition of recursive annotations,
Kotlin does, and prior to this commit an attempt to synthesize a
merged annotation using the MergedAnnotation API resulted in a
StackOverflowError if there was a recursive cycle in the annotation
definitions.
This commit addresses this issue by tracking which annotations have
already been visited and short circuits the recursive algorithm if a
cycle is detected.
Closes gh-28012
Although the initial report in gh-28015 only covered inconsistencies
for arrays and strings in the toString() implementations for
annotations between the JDK (after Java 9) and Spring, it has since
come to our attention that there was further room for improvement.
This commit therefore addresses the following in toString() output for
synthesized annotations.
- characters are now wrapped in single quotes.
- bytes are now properly formatted as "(byte) 0x##".
- long, float, and double values are now appended with "L", "f", and
"d", respectively. The use of lowercase for "f" and "d" is solely to
align with the choice made by the JDK team.
However, this commit does not address the following issues which we may
choose to address at a later point in time.
- non-ASCII, non-visible, and non-printable characters within a
character or String literal are not escaped.
- formatting for float and double values does not take into account
whether a value is not a number (NaN) or infinite.
Closes gh-28015
Since the introduction of synthesized annotation support in Spring
Framework 4.2 (a.k.a., merged annotations), the toString()
implementation attempted to align with the formatting used by the JDK
itself. However, Class annotation attributes were formatted using
Class#getName in Spring; whereas, the JDK used Class#toString up until
JDK 9.
In addition, JDK 9 introduced new formatting for toString() for
annotations, apparently intended to align with the syntax used in the
source code declaration of the annotation. However, JDK 9+ formats enum
annotation attributes using Enum#toString instead of Enum#name, which
can lead to issues if toString() is overridden in an enum.
This commit updates the formatting used for synthesized annotations by
ensuring that toString() generates a string that is compatible with the
syntax of the originating source code, going beyond the changes made in
JDK 9 by using Enum#name instead of Enum#toString.
Closes gh-28015
Prior to this commit, the USER_DECLARED_METHODS MethodFilter in
ReflectionUtils did not actually filter methods declared in
java.lang.Object as stated in its Javadoc.
Consequently, if ReflectionUtils.doWithMethods was invoked with
USER_DECLARED_METHODS and Object.class as the class to introspect, all
non-bridge non-synthetic methods declared in java.lang.Object were
passed to the supplied MethodCallback, which breaks the contract of
USER_DECLARED_METHODS.
In addition, if USER_DECLARED_METHODS was composed with a custom
MethodFilter using `USER_DECLARED_METHODS.and(<custom MethodFilter>)`,
that composed method filter allowed all non-bridge non-synthetic
methods declared in java.lang.Object to be passed to the supplied
MethodCallback, which also breaks the contract of
USER_DECLARED_METHODS. This behavior resulted in regressions in code
that had previously used USER_DECLARED_METHODS by itself and then began
using USER_DECLARED_METHODS in a composed filter. For example, since
commit c419ea7ba7 ReflectiveAspectJAdvisorFactory has incorrectly
processed methods in java.lang.Object as candidates for advice methods.
This commit fixes this bug and associated regressions by ensuring that
USER_DECLARED_METHODS actually filters methods declared in
java.lang.Object. In addition, ReflectionUtils.doWithMethods now aborts
its search algorithm early if invoked with the USER_DECLARED_METHODS
filter and Object.class as the class to introspect.
Closes gh-27970
Prior to this commit, XmlValidationModeDetector did not properly parse
all categories of comments (described below). When such categories of
comments were encountered XmlValidationModeDetector may have
incorrectly detected that an XML file used a DTD when it used an XSD,
or vice versa.
This commit revises the parsing algorithm in XmlValidationModeDetector
so that multi-line comments and multiple comments on a single line are
properly recognized.
Specifically, with this commit the following categories of comments are
now handled properly.
- Multiple comments on a single line
- Multi-line comment: beginning on one line and then ending on another
line with an additional comment following on that same line.
- Multi-line comment: beginning at the end of XML content on one line
and then spanning multiple lines.
Closes gh-27915
Prior to this commit, the error message generated for a mismatched
number of generics did not include the information about the class in
question.
This commit improves the error message by providing more context,
specifically the result of invoking toGenericString() on the class.
For example, instead of throwing an IllegalArgumentException with the
error message "Mismatched number of generics specified", the error
message would now be "Mismatched number of generics specified for
public abstract interface java.util.Map<K,V>".
Closes gh-27847
This commit makes sure that the Reactor context from a given mono or
flux is propagated to the Flux returned by a FluxSink. This change
affects both DataBufferUtils::write and internal classes used by the
DefaultPartHttpMessageReader.
Closes gh-27517
In order to be able to use text blocks and other new Java language
features, we are upgrading to a recent version of Checkstyle.
The latest version of spring-javaformat-checkstyle (0.0.28) is built
against Checkstyle 8.32 which does not include support for language
features such as text blocks. Support for text blocks was added in
Checkstyle 8.36.
In addition, there is a binary compatibility issue between
spring-javaformat-checkstyle 0.0.28 and Checkstyle 8.42. Thus we cannot
use Checkstyle 8.42 or higher.
In this commit, we therefore upgrade to spring-javaformat-checkstyle
0.0.28 and downgrade to Checkstyle 8.41.
This change is being applied to `5.3.x` as well as `main` in order to
benefit from the enhanced checking provided in more recent versions of
Checkstyle.
Closes gh-27481
This commit applies several optimizations to StringUtils#cleanPath and
related methods:
* pre-size pathElements deque in StringUtils#cleanPath with
pathElements.length elements, since this this is the maximum size and
the most likely case.
* optimize StringUtils#collectionToDelimitedString to calculate the size
of the resulting String and avoid array auto-resizing in the
StringBuilder.
* If the path did not contain any components that required cleaning,
return the (normalized) path as-is. No need to concatenate the prefix
and the trailing path.
See gh-26316