This commit introduces composite collections (i.e. Collection, Set, Map)
and uses these composites in request predicates, where before new
collections were instantiated.
Closes gh-32245
Add helpers to CollectionUtils for building HashSets and LinkedHashSets
that can hold an expected number of elements without needing to
resize/rehash.
Closes gh-32291
In places where a ConcurrentHashMap was used as a set by wrapping it
with Collections.newSetFromMap, switch to just using the set returned
by ConcurrentHashMap.newKeySet directly.
Closes gh-32294
Delegate to the spliterator method of the underlying collection in
MutablePropertyValues and MutablePropertySources. In both cases, those
collection types have specialized Spliterator implementations.
Delegating to these Spliterators also means the characteristics of the
Spliterator are properly set.
See gh-32281
This commit removes the previous implementation in favor of the new
PlaceholderParser. The only noticeable side effect is that the exception
is no longer an IllegalArgumentException, but rather the dedicated
PlaceholderResolutionException.
See gh-9628
This commit provides a rewrite of the parser for properties containing
potentially placeholders.
Assuming a source where `firstName` = `John` and `lastName` = `Smith`,
the "${firstName}-${lastName}" property is evaluated as "John-Smith".
Compared with the existing implementation in PropertyPlaceholderHelper,
the new implementation offers the following extra features:
1. Placeholder can be escaped using a configurable escape character.
When a placeholder is escaped it is rendered as is. This does apply to
any nested placeholder that wouldn't be escaped. For instance,
"\${firstName}" is evaluated as "${firstName}".
2. The default separator can also be escaped the same way. When the
separator is escaped, the left and right parts are not considered as
the key and the default value respectively. Rather the two parts
combined, including the separator (but not the escape separator) are
used for resolution. For instance, ${java\:comp/env/test} is looking
for a "java:comp/env/test" property.
3. Placeholders are resolved lazily. Previously, all nested placeholders
were resolved before considering if a separator was present. This
implementation only attempts the resolution of the default value if the
key does not provide a value.
4. Failure to resolve a placeholder are more rich, with a dedicated
PlaceholderResolutionException that contains the resolution chain.
See gh-9628
See gh-26268
Prior to this commit, the `SimpleCommandLineArgsParser` would reject
"--" arguments as invalid. As reported by the community, the POSIX
utility conventions (Guideline 10) state that
> The first -- argument that is not an option-argument should be
> accepted as a delimiter indicating the end of options.
> Any following arguments should be treated as operands, even if they
> begin with the '-' character.
This commit updates `SimpleCommandLineArgsParser` to not reject "--"
arguments and instead to consider remaining arguments as non-optional.
See gh-31513
This notably enables Jackson to reflectively call a user-provided
builder class and invoke its declared methods (setters and build) in
a native app.
Closes gh-32238
Schedulers remain strict, just plain executors are lenient on shutdown now.
An early shutdown for executors can be enforced via setStrictEarlyShutdown.
Closes gh-32226
To improve consistency and avoid confusion regarding primitive types
and their wrapper types, this commit ensures that we always use class
literals for primitive types.
For example, instead of using the `Void.TYPE` constant, we now
consistently use `void.class`.
Prior to this commit, the alias resolution error message in
SimpleAliasRegistry was misleading.
When a resolution conflict is detected, the IllegalStateException
thrown by resolveAliases(...) now states that the resolved alias is
already registered for an `existingName` instead of the `registeredName`.
See gh-31353
Closes gh-32025
This commit improves SimpleAliasRegistryTests in the following ways.
- Some existing methods have been split up into smaller test methods
which focus on a single use case.
- The use of Mockito mocks has been replaced by a hand-crafted
StubStringValueResolver which ensures that existing aliases and names
are not accidentally replaced by null thereby removing their removing
there mappings inadvertently.
- Several test methods now include inline comments that document the
current state of the aliasMap in order to clarify what is happening
behind the scenes in the ConcurrentHashMap.
- Several test methods warn that the current expectations are based on
ConcurrentHashMap iteration order!
- New @ParameterizedTest which is currently @Disabled but
demonstrates that complex use cases involving placeholder replacement
can be supported consistently -- regardless of the values of the
aliases involved -- but only if alias registration order is honored.
Closes gh-31353
This is able to resolve the original method even if no bridge method has been generated at the same class hierarchy level (a known difference between the Eclipse compiler and regular javac).
Closes gh-21843
Includes TypeVariable bypass for reflection-free annotation retrieval.
Includes info log message for annotation attribute retrieval failure.
Closes gh-27182
This commit restores support for Kotlin extensions in
web handlers, and adds support for invoking reflectively
suspending extension functions, as well as the other
features supported as of Spring Framework 6.1 like
value classes and default value for parameters.
Closes gh-31876
This commit updates the JSON writers to use a deterministic order for
arrays. Previously, the order could change with the same content,
breaking caching.
Closes gh-31852
This commit ensures that the capacity of the remainder buffer after a
split operation is set directly on the field. Calling capacity(int)
caused a new buffer to be allocated.
Closes gh-31848
This commit introduces ValueCodeGenerator and its Delegate interface
as a way to generate the code for a particular value. Implementations
in spring-core provides support for common value types such a String,
primitives, Collections, etc.
Additional implementations are provided for code generation of bean
definition property values.
Closes gh-28999
Prior to this commit, the AnnotationsScanner used in the
MergedAnnotations infrastructure found duplicate annotations on methods
within multi-level interface hierarchies.
This commit addresses this issue by scanning methods at a given level
in the interface hierarchy using ReflectionUtils#getDeclaredMethods
instead of Class#getMethods, since the latter includes public methods
declared in super-interfaces which will anyway be scanned when
processing super-interfaces recursively.
Closes gh-31803
Prior to this commit, the `ConcurrentReferenceHashMap#restructure`
operation would null out the entire references array before starting the
restructuring operation (in case resizing is not necessary).
This could cause at runtime race conditions where a lookup operation
would return null, when the value is actually cached but not accesible
during the restructuring phase.
This commit ensures that, when resizing is not required, a new reference
list is built (purged of null entries) and then assigned to the
reference array. This way, concurrent reads will not return null for
existing entries and there are less chances of re-calculating cache
entries during the restructuring phase.
Closes gh-31008
Commit 33454a4007 introduced a regression in Comparators.nullsLow() and
Comporators.nullsHigh().
This commit updates the code so that nullsLow() sorts null values lower
than non-null values and nullsHigh sorts null values higher than
non-null values.
See gh-25478
Closes gh-31808
Work performed in conjunction with gh-30941 resulted in a regression.
Specifically, prior to Spring Framework 6.1 a locally declared
@ComponentScan annotation took precedence over @ComponentScan
meta-annotations, which allowed "local" configuration to override
"meta-present" configuration.
This commit modifies the @ComponentScan search algorithm so that
locally declared @ComponentScan annotations are once again favored
over @ComponentScan meta-annotations (and, indirectly, composed
annotations).
See gh-30941 Closes gh-31704
Search for : assertThat\((.+).isEmpty\(\)\).isTrue\(\)
Replace with : assertThat($1).isEmpty()
Search for : assertThat\((.+).isEmpty\(\)\).isFalse\(\)
Replace with : assertThat($1).isNotEmpty()
Closes gh-31758
Search for : assertThat\((.+)\.equals\((\w+)\)\)\.isTrue\(\)
Replace with : assertThat($1).isEqualTo($2)
Search for : assertThat\((.+)\.equals\((\w+)\)\)\.isFalse\(\)
Replace with : assertThat($1).isNotEqualTo($2)
Closes gh-31763
Search for : assertThat\((.+)\.contains\((.+)\)\)\.isTrue\(\)
Replace with : assertThat($1).contains($2)
Search for : assertThat\((.+)\.contains\((.+)\)\)\.isFalse\(\)
Replace with : assertThat($1).doesNotContain($2)
Closes gh-31762
This commit introduces a toString() overload in
FastByteArrayOutputStream that accepts a Charset in order to mirror the
method that was introduced in ByteArrayOutputStream in JDK 10,
including a special case for when a single buffer is in use internally
to avoid the need to resize.
This commit also updates getContentAsString() in
ContentCachingRequestWrapper to use this new toString(Charset) method.
Closes gh-31737
This commit fixes a regression introduced by gh-21139
via the usage of Kotlin reflection to invoke HTTP
handler methods. It ensures that kotlin.Unit is treated
as void by returning null.
It also polishes CoroutinesUtils to have a consistent
handling compared to the regular case, and adds related
tests to prevent future regressions.
Closes gh-31648
In order to prevent leaks of large amounts of non-heap
memory (and potential other efficiency and performance side
effects), this commit updates ResourceUtils#useCachesIfNecessary
to leave the caching flag to its JVM default value for instances
of JarURLConnection.
The previous behavior was originally introduced via gh-9316 and
gh-13755 to avoid I/O failure during webapp hot reloading in
Servlet containers. This is not a popular deployment mode anymore
and we have not been able to reproduce the original issue with
a Java 17 JVM and Tomcat 10.
Closes gh-30955
Adding generated code in the default package is not supported as we
intend to import it, most probably from another package, and that is
not supported. While this situation is hard to replicate with Java,
Kotlin is unfortunately more lenient and users can end up in that
situation if they forget to add a package statement.
This commit checks for the presence of a valid package, and throws
a dedicated exception if necessary.
Closes gh-31628
This commit updates PathMatchingResourcePatternResolver to avoid
returning duplicate resources on MS Windows when searching using the
`classpath*:` prefix and a wildcard pattern that matches resources
which are directly present in a JAR as well as present via classpath
manifest entries.
Closes gh-31598
Allows Kotlin caller to get a non-nullable property,
using a default value when the property is not set.
A method already exists on PropertyResolver which does this,
but takes a Class parameter.
The extension method can eliminate the parameter via reified type,
similar to the other extension methods which exist already.
Closes gh-31523
Prior to this commit, the `ConcurrentReferenceHashMap#Segment` would
recalculate its element count during the restructure phase by
subtracting the number of polled elements from the queue to the current
count.
Later, the newly restructured `references` array would only contain
references that 1) are not in the set of elements to purge and
2) that hold a non-null value.
The issues with this approach are multiple. The newly calculated count
is only an estimate, as some situations can make it invalid, even
temporarily.
* since we initially collected all elements to be purged from the queue,
the GC might have collected new values. This means that we might
filter out more references that we initially intended to
* because the restructure operation re-creates new references for all
elements in the original array, we might later get references from the
queue that are not in the array anymore. This could lead to
"duplicate" removals for the same value
Because several methods in the Segment class have special no-op behavior
when `count == 0`, an invalid count can lead to keys appearing missing
when they are actually still present. In some scenarios, this can
decrease the performance of the cache since values need to be
recalculated.
This commit fixes this inconsistency count issue by first using an
estimate in order to decide whether the array needs a resize and then by
counting the actual numbers of elements inserted in the restructured
array as the new count.
Fixes gh-31373
Since the rewrite of ConcurrentLruCache in Spring Framework 6.0, an
attempt to create a ConcurrentLruCache with zero capacity results in an
IllegalArgumentException even though the documentation states that zero
capacity indicates "no caching, always generating a new value".
This commit restores the ability to configure a ConcurrentLruCache with
zero capacity and introduces corresponding tests (which were first
verified against the 5.3.x branch to ensure backward compatibility).
See gh-26320
Closes gh-31317
Given a @Configuration class named org.example.AppConfig which
contains @Bean methods, in Spring Framework 5.3.x and previous
versions, the following classes were created when generating the CGLIB
proxy.
org.example.AppConfig$$EnhancerBySpringCGLIB$$fd7e9baa
org.example.AppConfig$$FastClassBySpringCGLIB$$3fec86e
org.example.AppConfig$$EnhancerBySpringCGLIB$$fd7e9baa$$FastClassBySpringCGLIB$$82534900
Those class names indicate that 1 class was generated for the proxy for
the @Configuration class itself and that 2 additional FastClass
classes were generated to support proxying of @Bean methods in
superclasses.
However, since Spring Framework 6.0, the following classes are created
when generating the CGLIB proxy.
org.example.AppConfig$$SpringCGLIB$$0
org.example.AppConfig$$SpringCGLIB$$1
org.example.AppConfig$$SpringCGLIB$$2
The above class names make it appear that 3 proxy classes are generated
for each @Configuration class, which is misleading.
To address that and to align more closely with how such generated
classes were named in previous versions of the framework, this commit
modifies SpringNamingPolicy so that generated class names once again
include "FastClass" when the generated class is for a CGLIB FastClass
as opposed to the actual proxy for the @Configuration class.
Consequently, with this commit the following classes are created when
generating the CGLIB proxy.
org.example.AppConfig$$SpringCGLIB$$0
org.example.AppConfig$$SpringCGLIB$$FastClass$$0
org.example.AppConfig$$SpringCGLIB$$FastClass$$1
Closes gh-31272
`PathMatchingResourcePatternResolver` is reflecting on
`org.eclipse.core.runtime.FileLocator` and invoking methods on it for
OSGi support. While this use case is highly unlikely in native images,
registering the reflection entry by itself should be enough.
Fixes gh-31271
This commit adds the relevant reflection hints required by
`KotlinDetector`; this class is trying to detect both `kotlin.Metadata`
and `kotlin.reflect.full.KClasses`.
Fixes gh- 31269
Prior to this commit, `ClassUtils#forName` would always attempt to
resolve the given class name as a nested type. For example, searching
for `org.example.Spring` would try to resolve:
* `org.example.Spring`
* if not available, try `org.example$Spring` as well
Java classes usually start with uppercase letters, so this additional
lookup can be costly and not very useful.
This commit only attempts nested class lookups when the previous segment
starts with an uppercase. So `org.example.Spring.Issue` will look for
`org.example.Spring$Issue`, but `org.example.Spring` will not.
Closes gh-31258
Prior to this commit, the `RuntimeHintsPredicates` would assume that
registering introspection or invocation hints for "all declared methods"
on a type would also include "all public methods". This is not true, as
the Java reflection API itself behaves differently.
`getDeclaredMethods()` does not return a superset of `getMethods()`, as
the latter can return inherited methods, but not the former.
Same reasoning applies to fields.
This commit fixes the hints predicates to only match if the correct hint
has been registered.
Fixes gh-31224
In light of the refinements to ObjectUtils, this commit updates
SynthesizedMergedAnnotationInvocationHandler to use
ObjectUtils.nullSafeHashCode() and removes the now obsolete code in
SynthesizedMergedAnnotationInvocationHandler.
See gh-29051
This commit reverts the deprecation of CommandLinePropertySource and
SimpleCommandLinePropertySource, since we have discovered that Spring
Boot actively uses SimpleCommandLinePropertySource in
org.springframework.boot.SpringApplication.
Closes gh-31207
This commit deprecates the various nullSafeHashCode methods taking array
types as they are superseded by Arrays.hashCode now. This means that
the now only remaining nullSafeHashCode method does not trigger a
warning only if the target type is not an array. At the same time, there
are multiple use of this method on several elements, handling the
accumulation of hash codes.
For that reason, this commit also introduces a nullSafeHash that takes
an array of elements. The only difference between Objects.hash is that
this method handles arrays.
The codebase has been reviewed to use any of those two methods when it
is possible.
Closes gh-29051
gh-30810 introduced explicit support for collections and maps in
ObjectUtils.nullSafeConciseToString() by invoking isEmpty() on a Map or
Collection to determine which concise string representation should be
used. However, this caused a regression in which an exception was
thrown if the Map or Collection was a proxy generated by
AbstractFactoryBean to support <util:set />, <util:list />, and
<util:map /> in XML configuration.
This commit addresses this set of regressions by always returning
"[...]" or "{...}" for a Collection or Map, respectively, disregarding
whether the map is empty or not.
Closes gh-31138
This commit revises the FilePatternResourceHintsRegistrar API and
introduces List<String> overrides of various var-args methods used with
the new builder API.
Closes gh-29161
This commit refines Reactor field precomputing on native
to only compute at build-time fields in the reactor.core
package, since doing so in reactor.netty has unwanted side
effects like Epoll always disabled.
Closes gh-31141
Prior to this commit, `@Async` and `@EventListener` annotated methods
would lose the the logging and observation contexts whenever their
execution was scheduled on a different Thread.
The Context Propagation library supports this use case and can propagate
context values in ThreadLocals, Reactor Context and more.
This commit introduces a new `TaskDecorator` implementation that
leverages the Context Propagation library. When configured on a
`TaskExecutor`, this allows to properly propagate context value through
the execution of the task.
This implementation is completely optional and requires the
"io.micrometer:context-propagation" library on the classpath. Enabling
this feature must be done consciously and sometimes selectively, as
context propagation introduces some overhead.
Closes gh-31130
Create LinkedHashSet with a initialCapacity, prevent under the hood
table resize cost in continuous add operations. Reduce bootstrap time
in the case of large properties.
See gh-27236
If you wish to stop after a certain number of attempts with an
`ExponentialBackOff` you have to calculate the `maxElapsedTime`
corresponding to the number of attempts.
Add a new property to make it more convenient to stop after a
certain number of attempts.
See gh-27071
Prior to this commit, when PathMatchingResourcePatternResolver
processed a `file:` pattern (for example, `file:/app-config/**`) for a
`rootPath` that did not exist in the filesystem, the resolver attempted
to search the directory and logged a WARNING message similar to the
following when it failed to do so.
Failed to search in directory [/app-config/] for files matching pattern
[**]: java.nio.file.NoSuchFileException: /app-config/
To avoid unnecessary attempts to search a nonexistent directory,
PathMatchingResourcePatternResolver now skips searching of a nonexistent
directory and preemptively logs an INFO message similar to the
following.
Skipping search for files matching pattern [**]: directory [/app-config]
does not exist
Closes gh-31111
This commit ensures that PathMatchingResourcePatternResolver's
doFindPathMatchingFileResources() method returns a mutable Set in order
to comply with the documented contract.
This commit implements StringToRegexConverter in Java
in order to avoid circular dependencies between Java
and Kotlin codes that can break IDE support, and for
consistency with the rest of the codebase.
See gh-24311
This commit optimizes ClassUtils#getMostSpecificMethod which is
a method frequently invoked in typical Spring applications.
It refines ClassUtils#isOverridable by considering static and
final modifiers as non overridable and optimizes its implementation.
Closes gh-30272
Since an annotation cannot be extended in Java, there is no need to use
the INHERITED_ANNOTATIONS SearchStrategy to search for meta-annotations
on an annotation.
Prior to this commit, there was an issue with the semantics of property
source overrides. Specifically, a @PropertySource annotation present as
a meta-annotation on a @Configuration class was registered with higher
precedence than a @PropertySource annotation declared closer to (or
directly on) the @Configuration class. Consequently, there was no way
for a "local" @PropertySource annotation to override properties
registered via @PropertySource as a meta-annotation.
This commit addresses this issue by introducing a new overloaded
getMergedRepeatableAnnotationAttributes() variant in
AnnotatedTypeMetadata that allows the caller to supply a
sortByReversedMetaDistance flag. When set to `true`, the annotation
search results will be sorted in reversed order based on each
annotation's meta distance, which effectively orders meta-annotations
before annotations that are declared directly on the underlying element.
ConfigurationClassParser and AnnotationConfigUtils have been updated to
use this new repeatable annotation search method for @PropertySource.
Closes gh-31074
Reuses ValidationAnnotationUtils which is slightly optimized for the detection of Spring's Validated annotation now, also to the benefit of common web scenarios.
Closes gh-21852
Includes query(Class) method with value and property mapping support on JdbcClient.
JdbcClient's singleColumn/singleValue are declared without a Class parameter now.
Closes gh-26594
See gh-30931
AnnotatedTypeMetadata has various methods for finding annotations;
however, prior to this commit it did not provide explicit support for
repeatable annotations.
Although it is possible to craft a search "query" for repeatable
annotations using the MergedAnnotations API via getAnnotations(), that
requires intimate knowledge of the MergedAnnotations API as well as the
structure of repeatable annotations.
Furthermore, the bugs reported in gh-30941 result from the fact that
AnnotationConfigUtils attempts to use the existing functionality in
AnnotatedTypeMetadata to find repeatable annotations without success.
This commit introduces a getMergedRepeatableAnnotationAttributes()
method in AnnotatedTypeMetadata that provides dedicated support for
finding merged repeatable annotation attributes with full @AliasFor
semantics.
Closes gh-31041
The Javadoc for getAnnotationAttributes() states that it supports
"attribute overrides on composed annotations"; however, it actually
supports @AliasFor in general, including attribute aliases within a
given annotation.
This commit updates the Javadoc and corresponding tests to reflect that.
Closes gh-31042
Java 12 introduced java.lang.Class#componentType() as a shortcut for
getComponentType().
Since we started using arrayType() in fe5560400c, this commit switches
to componentType() for consistent API usage style.
Prior to this commit, the ignoreResourceNotFound flag in
@PropertySource was ignored by PropertySourceProcessor if a
PropertySourceFactory threw an exception which wrapped an exception
that would otherwise be ignored -- for example, a FileNotFoundException.
To address this issue, this commit updates PropertySourceFactory so
that it catches RuntimeException and IOException and then checks if the
exception or its cause is an "ignorable" exception in terms of
ignoreResourceNotFound semantics.
Closes gh-22276
Where possible, switch to the Long.parseLong variant that accepts a
start and end index for the supplied CharSequence, thus avoiding making
unnecessary copies of the String input.
Closes gh-30710
In order to reduce the surface area of published APIs in the affected
classes, this commit:
- Reverts the changes made to GeneratedClasses in c354b1014d.
- Reverts the changes made to DefaultGenerationContext in a28ec3a0a8.
- Makes the DefaultGenerationContext(DefaultGenerationContext, String)
constructor protected.
- Reworks the internals of TestContextGenerationContext to align with
the above changes.
See gh-30861
Closes gh-30895
Closes gh-30897
Aligned with shortcut handling in AutowiredAnnotationBeanPostProcessor.
Includes minor MethodInvoker optimization for pre-resolved targetClass.
Closes gh-30883
Prior to this commit, there was no explicit support for arrays,
collections, and maps in nullSafeConciseToString(). This lead to string
representations such as the following, regardless of whether the array,
collection, or map was empty.
- char[]@1623b78d
- java.util.ImmutableCollections$List12@74fe5c40
- java.util.ImmutableCollections$MapN@10e31a9a
This commit introduces explicit support for arrays, collections, and
maps in nullSafeConciseToString(), which results in the following
empty/non-empty string representations.
- array: {} / {...}
- collection: [] / [...]
- map: {} / {...}
The reason a string representation of an array uses "{}" instead of
"[]" (like in Arrays.toString(...)) is that
ObjectUtils.nullSafeToString(<array>) already follows that convention,
and the implementation of nullSafeConciseToString() aligns with that
for the sake of consistency.
Closes gh-30810
This commit extends the list of explicitly supported types in
ObjectUtils.nullSafeConciseToString() with the following.
- Optional
- File
- Path
- InetAddress
- Charset
- Currency
- TimeZone
- ZoneId
- Pattern
Closes gh-30805
ResolvableTypes are only considered equal if of the very same class now.
As a consequence, a forRawClass result is not equal to forClass anymore.
The new equalsType method is available for plain type equality checks.
Closes gh-28608
Closes gh-27748
As a consequence, the spring-messaging HandlerMethod detects interface parameter annotations as well, and the same is available for other HandlerMethod variants.
Closes gh-30801
This commit adds support for WildcardType bounds resolution,
commonly seen in Kotlin due to declaration-site variance,
but also possible in Java even if less common.
Closes gh-22313